You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by de...@apache.org on 2017/09/16 05:50:13 UTC

[myfaces-tobago] tag tobago-3.0.3 created (now f1f32f6)

This is an automated email from the ASF dual-hosted git repository.

deki pushed a change to tag tobago-3.0.3
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git.


      at f1f32f6  (commit)
This tag includes the following new commits:

     new 977fdaa  [maven-release-plugin] copy for tag tobago-3.0.2
     new 3a6454b  [maven-release-plugin] copy for tag tobago-3.0.3
     new 217ad9a  [maven-release-plugin] copy for tag tobago-3.0.3
     new f1f32f6  [maven-release-plugin] copy for tag tobago-3.0.3

The 4 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


-- 
To stop receiving notification emails like this one, please contact
['"commits@myfaces.apache.org" <co...@myfaces.apache.org>'].

[myfaces-tobago] 03/03: [maven-release-plugin] copy for tag tobago-3.0.3

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

deki pushed a commit to tag tobago-3.0.3
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit f1f32f6340b20d50049ba68fcd28ae5b7eec5276
Merge: 217ad9a 794e31d
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Fri Feb 3 10:46:40 2017 +0000

    [maven-release-plugin] copy for tag tobago-3.0.3

 pom.xml                                            |    15 +-
 tobago-3.0.x/build-site.sh                         |    56 -
 tobago-3.0.x/pom.xml                               |  1365 ---
 tobago-3.0.x/readme.txt                            |    17 -
 tobago-3.0.x/settings-example.xml                  |    41 -
 tobago-3.0.x/src/changes/changes.xml               |   138 -
 .../src/docbook/resources/basic-controls.png       |   Bin 27032 -> 0 bytes
 .../src/docbook/resources/editor-simple.png        |   Bin 15499 -> 0 bytes
 tobago-3.0.x/src/docbook/resources/editor.png      |   Bin 20292 -> 0 bytes
 tobago-3.0.x/src/docbook/resources/list.png        |   Bin 36110 -> 0 bytes
 tobago-3.0.x/src/docbook/resources/progress.png    |   Bin 470 -> 0 bytes
 tobago-3.0.x/src/docbook/resources/slider.png      |   Bin 446 -> 0 bytes
 .../src/docbook/resources/theme-charlotteville.png |   Bin 2783 -> 0 bytes
 .../src/docbook/resources/theme-richmond.png       |   Bin 2847 -> 0 bytes
 .../src/docbook/resources/theme-scarborough.png    |   Bin 3092 -> 0 bytes
 .../src/docbook/resources/theme-speyside.png       |   Bin 3762 -> 0 bytes
 tobago-3.0.x/src/docbook/tobago-tutorial.xml       |  1515 ---
 tobago-3.0.x/src/site/apt/api.apt                  |   293 -
 tobago-3.0.x/src/site/apt/compatibility.apt        |   128 -
 tobago-3.0.x/src/site/apt/demo.apt                 |    57 -
 tobago-3.0.x/src/site/apt/download.apt             |   190 -
 tobago-3.0.x/src/site/apt/getting-started.apt      |   117 -
 tobago-3.0.x/src/site/apt/guide.apt                |   660 -
 tobago-3.0.x/src/site/apt/howto-test.apt           |    57 -
 tobago-3.0.x/src/site/apt/index.apt                |  1125 --
 tobago-3.0.x/src/site/apt/new-2.0.apt              |   200 -
 tobago-3.0.x/src/site/apt/release-checklist.apt    |   358 -
 tobago-3.0.x/src/site/fml/faq.fml                  |   499 -
 tobago-3.0.x/src/site/resources/doap_tobago.rdf    |    87 -
 .../src/site/resources/images/addressbook.png      |   Bin 11237 -> 0 bytes
 tobago-3.0.x/src/site/resources/images/demo.png    |   Bin 15387 -> 0 bytes
 .../resources/images/guide-addressbook-about.png   |   Bin 70610 -> 0 bytes
 .../resources/images/guide-addressbook-date.png    |   Bin 55473 -> 0 bytes
 .../images/guide-addressbook-editor-simple.png     |   Bin 47398 -> 0 bytes
 .../resources/images/guide-addressbook-editor.png  |   Bin 50108 -> 0 bytes
 .../resources/images/guide-addressbook-list.png    |   Bin 54852 -> 0 bytes
 .../resources/images/guide-addressbook-logging.png |   Bin 58469 -> 0 bytes
 .../resources/images/guide-addressbook-login.png   |   Bin 44486 -> 0 bytes
 .../resources/images/guide-addressbook-memory.png  |   Bin 43322 -> 0 bytes
 .../resources/images/guide-addressbook-menu.png    |   Bin 48348 -> 0 bytes
 .../resources/images/guide-addressbook-popup.png   |   Bin 58388 -> 0 bytes
 .../resources/images/guide-addressbook-upload.png  |   Bin 52695 -> 0 bytes
 .../site/resources/images/guide-basic-controls.png |   Bin 20121 -> 0 bytes
 .../src/site/resources/images/guide-markup.png     |   Bin 2716 -> 0 bytes
 .../src/site/resources/images/guide-menu.png       |   Bin 3907 -> 0 bytes
 .../src/site/resources/images/guide-popup.png      |   Bin 3213 -> 0 bytes
 .../src/site/resources/images/guide-progress.png   |   Bin 2405 -> 0 bytes
 .../src/site/resources/images/guide-sheet.png      |   Bin 8105 -> 0 bytes
 .../site/resources/images/guide-simple-editor.png  |   Bin 2496 -> 0 bytes
 .../src/site/resources/images/guide-tab-group.png  |   Bin 3893 -> 0 bytes
 .../images/guide-theme-charlotteville.png          |   Bin 2783 -> 0 bytes
 .../site/resources/images/guide-theme-richmond.png |   Bin 2847 -> 0 bytes
 .../resources/images/guide-theme-scarborough.png   |   Bin 3092 -> 0 bytes
 .../site/resources/images/guide-theme-speyside.png |   Bin 3762 -> 0 bytes
 .../src/site/resources/images/guide-toolbar.png    |   Bin 7279 -> 0 bytes
 .../src/site/resources/images/guide-upload.png     |   Bin 2970 -> 0 bytes
 tobago-3.0.x/src/site/site.xml                     |    81 -
 tobago-3.0.x/tobago-3.0.txt                        |    22 -
 tobago-3.0.x/tobago-assembly/pom.xml               |   273 -
 .../tobago-assembly/src/main/assembly/dep.xml      |    84 -
 .../tobago-assembly/src/main/resources/LICENSE.txt |   328 -
 .../tobago-assembly/src/main/resources/NOTICE.txt  |    16 -
 .../tobago-assembly/src/main/resources/README.txt  |     6 -
 tobago-3.0.x/tobago-core/assembly-tlddoc.xml       |    43 -
 tobago-3.0.x/tobago-core/pom.xml                   |   328 -
 .../src/main/appended-resources/META-INF/NOTICE    |     3 -
 .../src/main/faces-config/faces-config.xml         |    57 -
 .../LabelValueExpressionFacesMessage.java          |    61 -
 .../myfaces/tobago/application/ProjectStage.java   |    32 -
 .../myfaces/tobago/component/Attributes.java       |   283 -
 .../myfaces/tobago/component/ClientBehaviors.java  |    50 -
 .../tobago/component/DeprecatedDimension.java      |    34 -
 .../apache/myfaces/tobago/component/Facets.java    |    84 -
 .../myfaces/tobago/component/InputSuggest.java     |    36 -
 .../myfaces/tobago/component/InputSuggest2.java    |    29 -
 .../myfaces/tobago/component/LabelLayout.java      |    91 -
 .../component/MethodBindingToMethodExpression.java |   241 -
 .../component/MethodExpressionToMethodBinding.java |   108 -
 .../myfaces/tobago/component/RendererTypes.java    |   152 -
 .../tobago/component/SelectBooleanCommand.java     |    23 -
 .../myfaces/tobago/component/SelectOneCommand.java |    23 -
 .../apache/myfaces/tobago/component/Sorter.java    |   259 -
 .../myfaces/tobago/component/SupportFieldId.java   |    27 -
 .../tobago/component/SupportsAccessKey.java        |    27 -
 .../tobago/component/SupportsLabelLayout.java      |    27 -
 .../myfaces/tobago/component/SupportsStyle.java    |    34 -
 .../tobago/component/UINamingContainer.java        |    27 -
 .../apache/myfaces/tobago/component/Visual.java    |    48 -
 .../apache/myfaces/tobago/config/TobagoConfig.java |    72 -
 .../apache/myfaces/tobago/context/Capability.java  |    40 -
 .../org/apache/myfaces/tobago/context/Markup.java  |   369 -
 .../myfaces/tobago/context/MarkupConfig.java       |    44 -
 .../myfaces/tobago/context/MarkupEditor.java       |    33 -
 .../myfaces/tobago/context/ResourceUtils.java      |    79 -
 .../org/apache/myfaces/tobago/context/Theme.java   |    44 -
 .../apache/myfaces/tobago/context/ThemeImpl.java   |   303 -
 .../myfaces/tobago/context/ThemeResource.java      |    58 -
 .../myfaces/tobago/context/ThemeResources.java     |    82 -
 .../apache/myfaces/tobago/context/ThemeScript.java |    26 -
 .../apache/myfaces/tobago/context/ThemeStyle.java  |    26 -
 .../myfaces/tobago/context/TobagoBundle.java       |   138 -
 .../myfaces/tobago/context/TobagoContext.java      |   110 -
 .../tobago/context/TobagoMessageBundle.java        |    44 -
 .../tobago/context/TobagoResourceBundle.java       |    41 -
 .../tobago/context/TransientStateHolder.java       |    73 -
 .../apache/myfaces/tobago/context/UserAgent.java   |   390 -
 .../myfaces/tobago/convert/CurrencyConverter.java  |    58 -
 .../myfaces/tobago/convert/DurationConverter.java  |   148 -
 .../myfaces/tobago/convert/LocaleConverter.java    |    50 -
 .../myfaces/tobago/convert/MeasureConverter.java   |    58 -
 .../myfaces/tobago/convert/ThemeConverter.java     |    62 -
 .../tobago/el/ConstantMethodExpression.java        |   103 -
 .../org/apache/myfaces/tobago/el/UserWrapper.java  |   122 -
 .../event/AbstractResetInputActionListener.java    |    46 -
 .../tobago/event/CollapsibleActionListener.java    |    87 -
 .../myfaces/tobago/event/FacesEventWrapper.java    |    72 -
 .../event/MethodExpressionStateChangeListener.java |    67 -
 .../event/MethodExpressionTabChangeListener.java   |    67 -
 .../MethodExpressionTreeExpansionListener.java     |    71 -
 .../MethodExpressionTreeSelectedListener.java      |    70 -
 .../myfaces/tobago/event/PageActionEvent.java      |    58 -
 .../tobago/event/ResetFormActionListener.java      |    40 -
 .../tobago/event/ResetInputActionListener.java     |    77 -
 .../apache/myfaces/tobago/event/SheetAction.java   |    70 -
 .../tobago/event/SheetStateChangeEvent.java        |    46 -
 .../tobago/event/SheetStateChangeListener.java     |    27 -
 .../tobago/event/SheetStateChangeSource.java       |    41 -
 .../tobago/event/SheetStateChangeSource2.java      |    29 -
 .../myfaces/tobago/event/SortActionEvent.java      |    49 -
 .../myfaces/tobago/event/SortActionSource.java     |    37 -
 .../myfaces/tobago/event/SortActionSource2.java    |    30 -
 .../myfaces/tobago/event/TabChangeEvent.java       |   100 -
 .../myfaces/tobago/event/TabChangeListener.java    |    28 -
 .../myfaces/tobago/event/TabChangeSource.java      |    41 -
 .../myfaces/tobago/event/TabChangeSource2.java     |    30 -
 .../myfaces/tobago/event/TreeExpansionEvent.java   |    74 -
 .../tobago/event/TreeExpansionListener.java        |    27 -
 .../myfaces/tobago/event/TreeSelectedEvent.java    |    69 -
 .../myfaces/tobago/event/TreeSelectedListener.java |    27 -
 .../ValueExpressionResetInputActionListener.java   |    95 -
 .../ValueExpressionSheetStateChangeListener.java   |   107 -
 .../event/ValueExpressionTabChangeListener.java    |   107 -
 .../myfaces/tobago/facelets/AttributeHandler.java  |   356 -
 .../myfaces/tobago/facelets/ContentTypeRule.java   |    57 -
 .../myfaces/tobago/facelets/ConverterHandler.java  |    81 -
 .../tobago/facelets/DataAttributeHandler.java      |    63 -
 .../tobago/facelets/DefaultResourceResolver.java   |    50 -
 .../myfaces/tobago/facelets/EventHandler.java      |   254 -
 .../facelets/FixCharacterEncodingFilter.java       |    59 -
 .../MetaInfResourcesClasspathResourceResolver.java |    73 -
 .../facelets/ResetInputActionListenerHandler.java  |    68 -
 .../apache/myfaces/tobago/facelets/Resource.java   |   144 -
 .../myfaces/tobago/facelets/ScriptHandler.java     |    40 -
 .../myfaces/tobago/facelets/SegmentLayoutRule.java |   114 -
 .../facelets/SheetStateChangeSourceRule.java       |    62 -
 .../tobago/facelets/SortActionSourceRule.java      |    64 -
 .../myfaces/tobago/facelets/SpanHandler.java       |    68 -
 .../myfaces/tobago/facelets/SuggestMethodRule.java |    83 -
 .../tobago/facelets/SupportsMarkupRule.java        |    67 -
 .../tobago/facelets/TabChangeListenerHandler.java  |    94 -
 .../tobago/facelets/TabChangeSourceRule.java       |    59 -
 .../tobago/facelets/TagMethodExpression.java       |   123 -
 .../tobago/facelets/TobagoComponentHandler.java    |   108 -
 .../tobago/facelets/TobagoValidateHandler.java     |    43 -
 .../tobago/internal/ajax/AjaxInternalUtils.java    |    80 -
 .../internal/ajax/AjaxNavigationListener.java      |    77 -
 .../tobago/internal/ajax/AjaxNavigationState.java  |   206 -
 .../behavior/AttachedListStateWrapper.java         |    43 -
 .../internal/behavior/AttachedStateWrapper.java    |    52 -
 .../tobago/internal/behavior/DeltaStateHelper.java |   763 --
 .../tobago/internal/behavior/EventBehavior.java    |   315 -
 .../tobago/internal/component/AbstractUIBar.java   |    25 -
 .../tobago/internal/component/AbstractUIBox.java   |    25 -
 .../internal/component/AbstractUIButton.java       |    24 -
 .../internal/component/AbstractUIButtons.java      |    23 -
 .../component/AbstractUICollapsiblePanel.java      |   100 -
 .../internal/component/AbstractUIColumn.java       |    27 -
 .../internal/component/AbstractUIColumnBase.java   |    32 -
 .../internal/component/AbstractUIColumnNode.java   |    28 -
 .../component/AbstractUIColumnSelector.java        |    35 -
 .../internal/component/AbstractUICommand.java      |    74 -
 .../internal/component/AbstractUICommandBase.java  |   144 -
 .../tobago/internal/component/AbstractUIData.java  |   314 -
 .../tobago/internal/component/AbstractUIDate.java  |    49 -
 .../tobago/internal/component/AbstractUIEvent.java |    28 -
 .../internal/component/AbstractUIFigure.java       |    25 -
 .../tobago/internal/component/AbstractUIFile.java  |    80 -
 .../internal/component/AbstractUIFlexLayout.java   |    32 -
 .../internal/component/AbstractUIFlowLayout.java   |    27 -
 .../tobago/internal/component/AbstractUIForm.java  |    27 -
 .../internal/component/AbstractUIFormBase.java     |   100 -
 .../internal/component/AbstractUIGridLayout.java   |   124 -
 .../internal/component/AbstractUIHidden.java       |    27 -
 .../tobago/internal/component/AbstractUIImage.java |    31 -
 .../tobago/internal/component/AbstractUIIn.java    |    24 -
 .../tobago/internal/component/AbstractUIInput.java |    62 -
 .../tobago/internal/component/AbstractUILabel.java |    42 -
 .../internal/component/AbstractUILayoutBase.java   |    29 -
 .../tobago/internal/component/AbstractUILink.java  |    29 -
 .../tobago/internal/component/AbstractUILinks.java |    23 -
 .../internal/component/AbstractUIMessages.java     |   126 -
 .../internal/component/AbstractUIObject.java       |    27 -
 .../internal/component/AbstractUIOperation.java    |    29 -
 .../tobago/internal/component/AbstractUIOut.java   |    28 -
 .../tobago/internal/component/AbstractUIPage.java  |   160 -
 .../tobago/internal/component/AbstractUIPanel.java |    25 -
 .../internal/component/AbstractUIPanelBase.java    |    65 -
 .../tobago/internal/component/AbstractUIPopup.java |    26 -
 .../internal/component/AbstractUIProgress.java     |    87 -
 .../tobago/internal/component/AbstractUIRow.java   |    25 -
 .../internal/component/AbstractUIScript.java       |    28 -
 .../internal/component/AbstractUISection.java      |    76 -
 .../component/AbstractUISegmentLayout.java         |    63 -
 .../component/AbstractUISelectBooleanCheckbox.java |    83 -
 .../internal/component/AbstractUISelectItem.java   |    59 -
 .../component/AbstractUISelectManyBase.java        |    42 -
 .../component/AbstractUISelectManyCheckbox.java    |    23 -
 .../component/AbstractUISelectManyListbox.java     |    38 -
 .../component/AbstractUISelectManyShuttle.java     |    50 -
 .../component/AbstractUISelectOneBase.java         |    56 -
 .../component/AbstractUISelectOneChoice.java       |    38 -
 .../component/AbstractUISelectOneListbox.java      |    38 -
 .../component/AbstractUISelectOneRadio.java        |    23 -
 .../internal/component/AbstractUISeparator.java    |    27 -
 .../tobago/internal/component/AbstractUISheet.java |   570 -
 .../internal/component/AbstractUISuggest.java      |    89 -
 .../tobago/internal/component/AbstractUITab.java   |    28 -
 .../internal/component/AbstractUITabGroup.java     |   277 -
 .../internal/component/AbstractUITextarea.java     |    28 -
 .../tobago/internal/component/AbstractUITree.java  |   234 -
 .../internal/component/AbstractUITreeCommand.java  |    23 -
 .../internal/component/AbstractUITreeIndent.java   |    27 -
 .../internal/component/AbstractUITreeListbox.java  |    28 -
 .../internal/component/AbstractUITreeMenu.java     |    30 -
 .../internal/component/AbstractUITreeNode.java     |    28 -
 .../internal/component/AbstractUITreeNodeBase.java |    73 -
 .../internal/component/AbstractUITreeSelect.java   |    46 -
 .../internal/config/ContentSecurityPolicy.java     |   102 -
 .../tobago/internal/config/RendererConfig.java     |    74 -
 .../tobago/internal/config/RenderersConfig.java    |    30 -
 .../internal/config/RenderersConfigImpl.java       |   101 -
 .../internal/config/TobagoConfigBuilder.java       |   120 -
 .../config/TobagoConfigEntityResolver.java         |    71 -
 .../internal/config/TobagoConfigFragment.java      |   195 -
 .../tobago/internal/config/TobagoConfigImpl.java   |   408 -
 .../tobago/internal/config/TobagoConfigParser.java |   452 -
 .../tobago/internal/config/TobagoConfigSorter.java |   332 -
 .../internal/config/TobagoConfigVersion.java       |    69 -
 .../tobago/internal/context/DateTimeI18n.java      |   106 -
 .../myfaces/tobago/internal/layout/BankHead.java   |    59 -
 .../myfaces/tobago/internal/layout/Cell.java       |    51 -
 .../myfaces/tobago/internal/layout/Grid.java       |   447 -
 .../tobago/internal/layout/LayoutUtils.java        |   102 -
 .../myfaces/tobago/internal/layout/MathUtils.java  |   109 -
 .../myfaces/tobago/internal/layout/OriginCell.java |    71 -
 .../myfaces/tobago/internal/layout/SpanCell.java   |    65 -
 .../myfaces/tobago/internal/package-info.java      |    28 -
 .../tobago/internal/renderkit/Collapse.java        |    43 -
 .../myfaces/tobago/internal/renderkit/Command.java |   261 -
 .../tobago/internal/renderkit/CommandMap.java      |   134 -
 .../internal/renderkit/renderer/BarRenderer.java   |   145 -
 .../internal/renderkit/renderer/BoxRenderer.java   |   104 -
 .../renderkit/renderer/ButtonRenderer.java         |    43 -
 .../renderkit/renderer/ButtonsRenderer.java        |    62 -
 .../renderkit/renderer/CalendarRenderer.java       |    45 -
 .../renderkit/renderer/ColumnRenderer.java         |    52 -
 .../renderkit/renderer/ColumnSelectorRenderer.java |    25 -
 .../renderkit/renderer/CommandRendererBase.java    |   207 -
 .../internal/renderkit/renderer/DateRenderer.java  |   113 -
 .../renderer/DecodingCommandRendererBase.java      |    62 -
 .../renderer/DecodingInputRendererBase.java        |    77 -
 .../internal/renderkit/renderer/EventRenderer.java |    23 -
 .../renderkit/renderer/FigureRenderer.java         |    78 -
 .../internal/renderkit/renderer/FileRenderer.java  |   205 -
 .../renderkit/renderer/FlexLayoutRenderer.java     |    96 -
 .../renderkit/renderer/FlowLayoutRenderer.java     |    70 -
 .../renderkit/renderer/FooterRenderer.java         |    57 -
 .../internal/renderkit/renderer/FormRenderer.java  |    55 -
 .../renderkit/renderer/GridLayoutRenderer.java     |   153 -
 .../renderkit/renderer/HeaderRenderer.java         |    61 -
 .../renderkit/renderer/HiddenRenderer.java         |    68 -
 .../internal/renderkit/renderer/ImageRenderer.java |    76 -
 .../internal/renderkit/renderer/InRenderer.java    |   178 -
 .../renderer/LabelLayoutRendererBase.java          |   219 -
 .../internal/renderkit/renderer/LabelRenderer.java |   108 -
 .../internal/renderkit/renderer/LinkRenderer.java  |    23 -
 .../internal/renderkit/renderer/LinksRenderer.java |    75 -
 .../renderkit/renderer/MessagesRenderer.java       |   177 -
 .../renderkit/renderer/ObjectRenderer.java         |    66 -
 .../renderkit/renderer/OperationRenderer.java      |    27 -
 .../internal/renderkit/renderer/OutRenderer.java   |    97 -
 .../internal/renderkit/renderer/PageRenderer.java  |   408 -
 .../internal/renderkit/renderer/PanelRenderer.java |    83 -
 .../renderkit/renderer/PanelRendererBase.java      |    79 -
 .../internal/renderkit/renderer/PopupRenderer.java |    86 -
 .../renderkit/renderer/ProgressRenderer.java       |    76 -
 .../internal/renderkit/renderer/RowRenderer.java   |    45 -
 .../renderkit/renderer/ScriptRenderer.java         |    44 -
 .../renderkit/renderer/SectionRenderer.java        |   106 -
 .../renderkit/renderer/SegmentLayoutRenderer.java  |   125 -
 .../renderer/SelectBooleanCheckboxRenderer.java    |   127 -
 .../renderkit/renderer/SelectItemsRenderer.java    |    27 -
 .../renderer/SelectManyCheckboxRenderer.java       |   119 -
 .../renderer/SelectManyListboxRenderer.java        |    87 -
 .../renderkit/renderer/SelectManyRendererBase.java |   810 --
 .../renderer/SelectManyShuttleRenderer.java        |   154 -
 .../renderer/SelectOneChoiceRenderer.java          |    81 -
 .../renderer/SelectOneListboxRenderer.java         |    85 -
 .../renderkit/renderer/SelectOneRadioRenderer.java |   132 -
 .../renderkit/renderer/SelectOneRendererBase.java  |    53 -
 .../renderer/SelectReferenceRenderer.java          |    51 -
 .../renderkit/renderer/SeparatorRenderer.java      |    67 -
 .../renderer/SheetPageCommandRenderer.java         |    89 -
 .../internal/renderkit/renderer/SheetRenderer.java |  1168 --
 .../internal/renderkit/renderer/StyleRenderer.java |    72 -
 .../renderkit/renderer/SubviewRenderer.java        |    50 -
 .../renderkit/renderer/SuggestRenderer.java        |   163 -
 .../renderkit/renderer/TabGroupRenderer.java       |   338 -
 .../internal/renderkit/renderer/TabRenderer.java   |    30 -
 .../renderkit/renderer/TextareaRenderer.java       |   132 -
 .../renderer/TobagoClientBehaviorRenderer.java     |   185 -
 .../renderkit/renderer/TreeCommandRenderer.java    |    23 -
 .../renderkit/renderer/TreeIconRenderer.java       |    88 -
 .../renderkit/renderer/TreeIndentRenderer.java     |   172 -
 .../renderkit/renderer/TreeLabelRenderer.java      |    71 -
 .../renderkit/renderer/TreeListboxRenderer.java    |   199 -
 .../renderkit/renderer/TreeMenuRenderer.java       |    23 -
 .../renderkit/renderer/TreeNodeRenderer.java       |   222 -
 .../internal/renderkit/renderer/TreeRenderer.java  |   159 -
 .../renderkit/renderer/TreeSelectRenderer.java     |   158 -
 .../renderkit/renderer/VerbatimRenderer.java       |    50 -
 .../taglib/component/AttributeTagDeclaration.java  |    67 -
 .../taglib/component/BarTagDeclaration.java        |    48 -
 .../taglib/component/BoxTagDeclaration.java        |    56 -
 .../taglib/component/ButtonTagDeclaration.java     |    88 -
 .../taglib/component/ButtonsTagDeclaration.java    |    45 -
 .../taglib/component/CalendarTagDeclaration.java   |    54 -
 .../taglib/component/ColumnNodeTagDeclaration.java |    65 -
 .../component/ColumnSelectorTagDeclaration.java    |    44 -
 .../taglib/component/ColumnTagDeclaration.java     |    80 -
 .../taglib/component/ConverterTagDeclaration.java  |    48 -
 .../component/DataAttributeTagDeclaration.java     |    52 -
 .../taglib/component/DateTagDeclaration.java       |    83 -
 .../taglib/component/EventTagDeclaration.java      |    62 -
 .../taglib/component/FigureTagDeclaration.java     |    51 -
 .../taglib/component/FileTagDeclaration.java       |    94 -
 .../taglib/component/FlexLayoutTagDeclaration.java |    77 -
 .../taglib/component/FlowLayoutTagDeclaration.java |    62 -
 .../taglib/component/FooterTagDeclaration.java     |    45 -
 .../taglib/component/FormTagDeclaration.java       |    46 -
 .../taglib/component/GridLayoutTagDeclaration.java |   113 -
 .../taglib/component/HeaderTagDeclaration.java     |    45 -
 .../taglib/component/HiddenTagDeclaration.java     |    54 -
 .../taglib/component/ImageTagDeclaration.java      |    58 -
 .../taglib/component/InTagDeclaration.java         |    95 -
 .../taglib/component/LabelTagDeclaration.java      |    57 -
 .../taglib/component/LinkTagDeclaration.java       |    83 -
 .../taglib/component/LinksTagDeclaration.java      |    42 -
 .../taglib/component/MessagesTagDeclaration.java   |   115 -
 .../taglib/component/ObjectTagDeclaration.java     |    61 -
 .../taglib/component/OperationTagDeclaration.java  |    59 -
 .../taglib/component/OutTagDeclaration.java        |    72 -
 .../taglib/component/PageTagDeclaration.java       |    91 -
 .../taglib/component/PanelTagDeclaration.java      |    67 -
 .../taglib/component/PopupTagDeclaration.java      |    60 -
 .../taglib/component/ProgressTagDeclaration.java   |    72 -
 .../taglib/component/ReloadTagDeclaration.java     |    67 -
 .../ResetInputActionListenerTagDeclaration.java    |    43 -
 .../taglib/component/RowTagDeclaration.java        |    49 -
 .../taglib/component/ScriptTagDeclaration.java     |    54 -
 .../taglib/component/SectionTagDeclaration.java    |    52 -
 .../component/SegmentLayoutTagDeclaration.java     |    75 -
 .../SelectBooleanCheckboxTagDeclaration.java       |    81 -
 .../taglib/component/SelectItemTagDeclaration.java |    92 -
 .../component/SelectItemsTagDeclaration.java       |    92 -
 .../SelectManyCheckboxTagDeclaration.java          |    93 -
 .../component/SelectManyListboxTagDeclaration.java |    87 -
 .../component/SelectManyShuttleTagDeclaration.java |   103 -
 .../component/SelectOneChoiceTagDeclaration.java   |    92 -
 .../component/SelectOneListboxTagDeclaration.java  |    93 -
 .../component/SelectOneRadioTagDeclaration.java    |    94 -
 .../component/SelectReferenceTagDeclaration.java   |    57 -
 .../taglib/component/SeparatorTagDeclaration.java  |    48 -
 .../component/SheetPageCommandTagDeclaration.java  |    34 -
 .../taglib/component/SheetTagDeclaration.java      |   257 -
 .../taglib/component/SpanTagDeclaration.java       |    46 -
 .../taglib/component/StyleTagDeclaration.java      |   268 -
 .../taglib/component/SuggestTagDeclaration.java    |   165 -
 .../component/TabChangeListenerTagDeclaration.java |    50 -
 .../taglib/component/TabGroupTagDeclaration.java   |   115 -
 .../taglib/component/TabTagDeclaration.java        |    63 -
 .../taglib/component/TextareaTagDeclaration.java   |    86 -
 .../component/TreeCommandTagDeclaration.java       |    80 -
 .../taglib/component/TreeIconTagDeclaration.java   |    68 -
 .../taglib/component/TreeIndentTagDeclaration.java |    52 -
 .../taglib/component/TreeLabelTagDeclaration.java  |    54 -
 .../component/TreeListboxTagDeclaration.java       |    86 -
 .../taglib/component/TreeMenuTagDeclaration.java   |    69 -
 .../taglib/component/TreeNodeTagDeclaration.java   |    75 -
 .../taglib/component/TreeSelectTagDeclaration.java |    80 -
 .../taglib/component/TreeTagDeclaration.java       |    95 -
 .../component/ValidateFileItemTagDeclaration.java  |    45 -
 ...ValidateSubmittedValueLengthTagDeclaration.java |    45 -
 .../internal/taglib/component/package-info.java    |    33 -
 .../internal/taglib/declaration/HasAccessKey.java  |    33 -
 .../internal/taglib/declaration/HasAction.java     |    43 -
 .../taglib/declaration/HasActionListener.java      |    39 -
 .../tobago/internal/taglib/declaration/HasAlt.java |    32 -
 .../taglib/declaration/HasAutocomplete.java        |    30 -
 .../internal/taglib/declaration/HasBinding.java    |    33 -
 .../taglib/declaration/HasCollapsedMode.java       |    37 -
 .../taglib/declaration/HasColumnLayout.java        |    35 -
 .../taglib/declaration/HasConfirmation.java        |    32 -
 .../internal/taglib/declaration/HasConverter.java  |    41 -
 .../taglib/declaration/HasConverterMessage.java    |    34 -
 .../internal/taglib/declaration/HasFieldId.java    |    33 -
 .../tobago/internal/taglib/declaration/HasFor.java |    33 -
 .../tobago/internal/taglib/declaration/HasId.java  |    33 -
 .../declaration/HasIdBindingAndRendered.java       |    23 -
 .../internal/taglib/declaration/HasImage.java      |    32 -
 .../internal/taglib/declaration/HasItemLabel.java  |    32 -
 .../internal/taglib/declaration/HasLabel.java      |    32 -
 .../taglib/declaration/HasLabelLayout.java         |    38 -
 .../internal/taglib/declaration/HasLabelWidth.java |    35 -
 .../internal/taglib/declaration/HasLink.java       |    45 -
 .../taglib/declaration/HasPlaceholder.java         |    40 -
 .../taglib/declaration/HasRenderRange.java         |    32 -
 .../taglib/declaration/HasRequiredMessage.java     |    33 -
 .../declaration/HasRequiredMessageForSelect.java   |    33 -
 .../internal/taglib/declaration/HasRowLayout.java  |    35 -
 .../internal/taglib/declaration/HasSanitize.java   |    44 -
 .../internal/taglib/declaration/HasSize.java       |    33 -
 .../internal/taglib/declaration/HasSpacing.java    |    44 -
 .../internal/taglib/declaration/HasState.java      |    36 -
 .../taglib/declaration/HasStateBinding.java        |    28 -
 .../declaration/HasTabChangeListenerType.java      |    33 -
 .../internal/taglib/declaration/HasTabIndex.java   |    40 -
 .../internal/taglib/declaration/HasTarget.java     |    33 -
 .../tobago/internal/taglib/declaration/HasTip.java |    32 -
 .../internal/taglib/declaration/HasValidator.java  |    38 -
 .../taglib/declaration/HasValidatorMessage.java    |    33 -
 .../internal/taglib/declaration/HasValue.java      |    33 -
 .../taglib/declaration/HasValueChangeListener.java |    39 -
 .../tobago/internal/taglib/declaration/HasVar.java |    37 -
 .../internal/taglib/declaration/IsCollapsed.java   |    33 -
 .../taglib/declaration/IsDefaultCommand.java       |    33 -
 .../internal/taglib/declaration/IsDisabled.java    |    32 -
 .../taglib/declaration/IsDisabledBySecurity.java   |    34 -
 .../internal/taglib/declaration/IsDraggable.java   |    44 -
 .../internal/taglib/declaration/IsFixed.java       |    33 -
 .../internal/taglib/declaration/IsFocus.java       |    32 -
 .../taglib/declaration/IsImmediateCommand.java     |    36 -
 .../internal/taglib/declaration/IsInline.java      |    32 -
 .../internal/taglib/declaration/IsMultiple.java    |    30 -
 .../tobago/internal/taglib/declaration/IsOmit.java |    37 -
 .../internal/taglib/declaration/IsPassword.java    |    34 -
 .../internal/taglib/declaration/IsReadonly.java    |    32 -
 .../internal/taglib/declaration/IsRendered.java    |    35 -
 .../internal/taglib/declaration/IsRequired.java    |    34 -
 .../taglib/declaration/IsRequiredForSelect.java    |    34 -
 .../internal/taglib/declaration/IsShowRoot.java    |    36 -
 .../taglib/declaration/IsShowRootJunction.java     |    35 -
 .../internal/taglib/declaration/IsTransition.java  |    36 -
 .../internal/taglib/declaration/IsVisual.java      |    61 -
 .../tobago/internal/util/AccessKeyLogger.java      |    89 -
 .../myfaces/tobago/internal/util/ArrayUtils.java   |    34 -
 .../tobago/internal/util/AuthorizationHelper.java  |   228 -
 .../myfaces/tobago/internal/util/ContentType.java  |    61 -
 .../myfaces/tobago/internal/util/CookieUtils.java  |   120 -
 .../tobago/internal/util/DateFormatUtils.java      |   109 -
 .../myfaces/tobago/internal/util/Deprecation.java  |    51 -
 .../tobago/internal/util/FacesContextUtils.java    |    91 -
 .../tobago/internal/util/FastStringWriter.java     |    74 -
 .../tobago/internal/util/HtmlRendererUtils.java    |   272 -
 .../tobago/internal/util/HtmlWriterUtils.java      |   124 -
 .../tobago/internal/util/HttpPartWrapper.java      |   129 -
 .../myfaces/tobago/internal/util/IoUtils.java      |    39 -
 .../myfaces/tobago/internal/util/JQueryUtils.java  |    32 -
 .../internal/util/JavascriptWriterUtils.java       |   120 -
 .../myfaces/tobago/internal/util/JndiUtils.java    |    78 -
 .../myfaces/tobago/internal/util/JsonUtils.java    |   297 -
 .../tobago/internal/util/JsonWriterUtils.java      |   125 -
 .../tobago/internal/util/MimeTypeUtils.java        |   106 -
 .../myfaces/tobago/internal/util/NumberUtils.java  |    34 -
 .../myfaces/tobago/internal/util/ObjectUtils.java  |    32 -
 .../myfaces/tobago/internal/util/PartUtils.java    |   331 -
 .../myfaces/tobago/internal/util/RenderUtils.java  |   304 -
 .../tobago/internal/util/ResponseUtils.java        |   145 -
 .../tobago/internal/util/ResponseWriterBuffer.java |    82 -
 .../tobago/internal/util/SelectItemUtils.java      |   282 -
 .../myfaces/tobago/internal/util/StringUtils.java  |   581 -
 .../myfaces/tobago/internal/util/WriterUtils.java  |   211 -
 .../internal/webapp/DebugContentTypeFilter.java    |    64 -
 .../internal/webapp/DebugContentTypeResponse.java  |    71 -
 .../webapp/DebugResponseWriterWrapper.java         |   228 -
 .../tobago/internal/webapp/HtmlResponseWriter.java |   166 -
 .../tobago/internal/webapp/LoggingMdcFilter.java   |    78 -
 .../internal/webapp/TobagoResponseWriterBase.java  |   369 -
 .../webapp/TobagoResponseWriterWrapper.java        |   150 -
 .../tobago/internal/webapp/XmlResponseWriter.java  |    94 -
 .../apache/myfaces/tobago/layout/AlignItems.java   |    36 -
 .../myfaces/tobago/layout/AutoLayoutToken.java     |    29 -
 .../myfaces/tobago/layout/ColumnPartition.java     |   131 -
 .../org/apache/myfaces/tobago/layout/Display.java  |    48 -
 .../myfaces/tobago/layout/HideLayoutToken.java     |    26 -
 .../myfaces/tobago/layout/JustifyContent.java      |    36 -
 .../apache/myfaces/tobago/layout/LayoutToken.java  |    23 -
 .../apache/myfaces/tobago/layout/LayoutTokens.java |   146 -
 .../org/apache/myfaces/tobago/layout/Measure.java  |   188 -
 .../myfaces/tobago/layout/MeasureEditor.java       |    34 -
 .../myfaces/tobago/layout/MeasureLayoutToken.java  |    66 -
 .../myfaces/tobago/layout/MinimumLayoutToken.java  |    26 -
 .../org/apache/myfaces/tobago/layout/OrderBy.java  |    31 -
 .../apache/myfaces/tobago/layout/Orientation.java  |    40 -
 .../org/apache/myfaces/tobago/layout/Overflow.java |    43 -
 .../apache/myfaces/tobago/layout/PixelMeasure.java |    78 -
 .../org/apache/myfaces/tobago/layout/Position.java |    48 -
 .../myfaces/tobago/layout/RelativeLayoutToken.java |    63 -
 .../apache/myfaces/tobago/layout/ShowPosition.java |    33 -
 .../apache/myfaces/tobago/layout/TextAlign.java    |    69 -
 .../tobago/lifecycle/SecretPhaseListener.java      |    58 -
 .../tobago/model/AutoSuggestExtensionItem.java     |    42 -
 .../myfaces/tobago/model/AutoSuggestItem.java      |    55 -
 .../myfaces/tobago/model/AutoSuggestItems.java     |    56 -
 .../apache/myfaces/tobago/model/CalendarModel.java |    97 -
 .../apache/myfaces/tobago/model/CollapseMode.java  |    31 -
 .../org/apache/myfaces/tobago/model/DateModel.java |    78 -
 .../apache/myfaces/tobago/model/ExpandedState.java |   251 -
 .../myfaces/tobago/model/ScrollPosition.java       |    74 -
 .../myfaces/tobago/model/ScrollPositionState.java  |    25 -
 .../apache/myfaces/tobago/model/SelectItem.java    |   130 -
 .../apache/myfaces/tobago/model/Selectable.java    |   148 -
 .../apache/myfaces/tobago/model/SelectedState.java |    81 -
 .../apache/myfaces/tobago/model/SheetState.java    |   184 -
 .../tobago/model/SortableByApplication.java        |    26 -
 .../apache/myfaces/tobago/model/SuggestFilter.java |    42 -
 .../apache/myfaces/tobago/model/SwitchType.java    |    34 -
 .../apache/myfaces/tobago/model/TreeDataModel.java |    71 -
 .../myfaces/tobago/model/TreeNodeDataModel.java    |   305 -
 .../org/apache/myfaces/tobago/model/TreePath.java  |   132 -
 .../org/apache/myfaces/tobago/model/TreeState.java |    57 -
 .../myfaces/tobago/portlet/PortletUtils.java       |    55 -
 .../myfaces/tobago/renderkit/GenericRenderer.java  |    26 -
 .../tobago/renderkit/LabelWithAccessKey.java       |    96 -
 .../myfaces/tobago/renderkit/RendererBase.java     |    85 -
 .../myfaces/tobago/renderkit/TobagoRenderKit.java  |   181 -
 .../tobago/renderkit/css/BootstrapClass.java       |   281 -
 .../css/BootstrapDateTimePickerClass.java          |    42 -
 .../myfaces/tobago/renderkit/css/Classes.java      |   155 -
 .../myfaces/tobago/renderkit/css/CssItem.java      |    30 -
 .../myfaces/tobago/renderkit/css/CustomClass.java  |    87 -
 .../tobago/renderkit/css/CustomClassEditor.java    |    38 -
 .../renderkit/css/FontAwesomeIconEncoder.java      |   101 -
 .../myfaces/tobago/renderkit/css/IconEncoder.java  |    30 -
 .../apache/myfaces/tobago/renderkit/css/Icons.java |    42 -
 .../apache/myfaces/tobago/renderkit/css/Style.java |   679 --
 .../myfaces/tobago/renderkit/css/TobagoClass.java  |   148 -
 .../myfaces/tobago/renderkit/html/Arias.java       |    58 -
 .../tobago/renderkit/html/DataAttributes.java      |   224 -
 .../tobago/renderkit/html/HtmlAttributes.java      |   141 -
 .../tobago/renderkit/html/HtmlButtonTypes.java     |    38 -
 .../tobago/renderkit/html/HtmlElements.java        |   186 -
 .../tobago/renderkit/html/HtmlInputTypes.java      |    45 -
 .../tobago/renderkit/html/HtmlRoleValues.java      |    44 -
 .../myfaces/tobago/renderkit/html/HtmlTypes.java   |    25 -
 .../renderkit/html/MarkupLanguageAttributes.java   |    25 -
 .../tobago/sanitizer/IgnoringSanitizer.java        |    48 -
 .../myfaces/tobago/sanitizer/JsoupSanitizer.java   |    95 -
 .../myfaces/tobago/sanitizer/SanitizeMode.java     |    28 -
 .../apache/myfaces/tobago/sanitizer/Sanitizer.java |    29 -
 .../tobago/servlet/NonFacesRequestServlet.java     |    98 -
 .../myfaces/tobago/servlet/ResourceServlet.java    |   170 -
 .../org/apache/myfaces/tobago/util/AjaxUtils.java  |    77 -
 .../apache/myfaces/tobago/util/BeanComparator.java |    95 -
 .../apache/myfaces/tobago/util/ComparatorBase.java |   126 -
 .../apache/myfaces/tobago/util/ComponentUtils.java |   859 --
 .../myfaces/tobago/util/ContextCallback.java       |    28 -
 .../myfaces/tobago/util/CreateComponentUtils.java  |    27 -
 .../myfaces/tobago/util/DebugActionListener.java   |    47 -
 .../tobago/util/DebugNavigationHandler.java        |    58 -
 .../myfaces/tobago/util/DebugPhaseListener.java    |   157 -
 .../org/apache/myfaces/tobago/util/DebugUtils.java |   112 -
 .../apache/myfaces/tobago/util/FacesELUtils.java   |    45 -
 .../apache/myfaces/tobago/util/FacesVersion.java   |   122 -
 .../apache/myfaces/tobago/util/LocaleUtils.java    |    97 -
 .../apache/myfaces/tobago/util/MessageFormat.java  |    76 -
 .../apache/myfaces/tobago/util/MessageUtils.java   |   148 -
 .../tobago/util/ValueBindingComparator.java        |   131 -
 .../tobago/util/ValueExpressionComparator.java     |   128 -
 .../myfaces/tobago/util/VariableResolverUtils.java |    49 -
 .../org/apache/myfaces/tobago/util/XmlUtils.java   |   169 -
 .../validator/ClearValidatorsActionListener.java   |    84 -
 .../tobago/validator/FileItemValidator.java        |   132 -
 .../validator/SubmittedValueLengthValidator.java   |   144 -
 .../tobago/webapp/LogoutActionListener.java        |    64 -
 .../org/apache/myfaces/tobago/webapp/Secret.java   |   126 -
 .../tobago/webapp/SecretSessionListener.java       |    40 -
 .../tobago/webapp/TobagoResponseWriter.java        |   317 -
 .../webapp/TobagoServletContextListener.java       |    86 -
 .../src/main/resources/META-INF/web-fragment.xml   |    43 -
 .../myfaces/tobago/config/tobago-config-1.0.29.dtd |    50 -
 .../myfaces/tobago/config/tobago-config-1.0.30.dtd |    59 -
 .../myfaces/tobago/config/tobago-config-1.0.34.dtd |    63 -
 .../myfaces/tobago/config/tobago-config-1.5.xsd    |   152 -
 .../myfaces/tobago/config/tobago-config-1.6.xsd    |   168 -
 .../myfaces/tobago/config/tobago-config-2.0.6.xsd  |   215 -
 .../myfaces/tobago/config/tobago-config-2.0.xsd    |   201 -
 .../myfaces/tobago/config/tobago-config-3.0.xsd    |   206 -
 .../myfaces/tobago/config/tobago-config_1_0.dtd    |    62 -
 .../myfaces/tobago/context/TobagoMessage.xml       |    43 -
 .../myfaces/tobago/context/TobagoMessage_de.xml    |    47 -
 .../myfaces/tobago/context/TobagoMessage_es.xml    |    44 -
 .../myfaces/tobago/context/TobagoResource.xml      |    91 -
 .../myfaces/tobago/context/TobagoResource_de.xml   |    93 -
 .../myfaces/tobago/context/TobagoResource_es.xml   |    92 -
 .../tobago/component/ClientBehaviorsUnitTest.java  |    32 -
 .../myfaces/tobago/component/FacetsUnitTest.java   |    32 -
 ...OverwritingOfGeneratedUIComponentsUnitTest.java |   155 -
 .../tobago/component/RendererTypesUnitTest.java    |    43 -
 .../myfaces/tobago/component/SorterUnitTest.java   |    57 -
 .../tobago/component/UIMessagesUnitTest.java       |   134 -
 .../myfaces/tobago/component/UISheetUnitTest.java  |   404 -
 .../myfaces/tobago/context/MarkupUnitTest.java     |   148 -
 .../tobago/context/ResourceUtilsUnitTest.java      |    38 -
 .../myfaces/tobago/context/UserAgentUnitTest.java  |   190 -
 .../tobago/convert/DurationConverterUnitTest.java  |    88 -
 .../internal/config/AbstractTobagoTestBase.java    |   116 -
 .../config/TobagoConfigMergingUnitTest.java        |   135 -
 .../config/TobagoConfigParserUnitTest.java         |   190 -
 .../config/TobagoConfigSorterUnitTest.java         |   197 -
 .../internal/context/ThemeParserUnitTest.java      |   102 -
 .../internal/renderkit/CommandUnitTest.java        |    71 -
 .../tobago/internal/layout/GridUnitTest.java       |   233 -
 .../tobago/internal/layout/MathUtilsUnitTest.java  |    97 -
 .../internal/mock/faces/MockRenderersConfig.java   |    41 -
 .../tobago/internal/mock/faces/MockTheme.java      |    97 -
 .../internal/mock/servlet/MockHttpSession.java     |   116 -
 .../mock/servlet/MockServletInputStream.java       |    43 -
 .../tobago/internal/util/JsonUtilsUnitTest.java    |   157 -
 .../internal/util/MimeTypeUtilsUnitTest.java       |    87 -
 .../tobago/internal/util/PartUtilsUnitTest.java    |   108 -
 .../tobago/internal/util/StringUtilsUnitTest.java  |    54 -
 .../myfaces/tobago/layout/AlignItemsUnitTest.java  |    32 -
 .../tobago/layout/ColumnPartitionUnitTest.java     |    59 -
 .../myfaces/tobago/layout/DisplayUnitTest.java     |    31 -
 .../tobago/layout/JustifyContentUnitTest.java      |    31 -
 .../tobago/layout/LayoutTokensUnitTest.java        |    48 -
 .../myfaces/tobago/layout/MeasureUnitTest.java     |    55 -
 .../myfaces/tobago/layout/OrderByUnitTest.java     |    31 -
 .../myfaces/tobago/layout/OrientationUnitTest.java |    31 -
 .../myfaces/tobago/layout/OverflowUnitTest.java    |    31 -
 .../myfaces/tobago/layout/PositionUnitTest.java    |    31 -
 .../tobago/layout/ShowPositionUnitTest.java        |    31 -
 .../myfaces/tobago/layout/TextAlignUnitTest.java   |    31 -
 .../myfaces/tobago/model/CollapseModeUnitTest.java |    31 -
 .../tobago/model/ExpandedStateUnitTest.java        |   339 -
 .../myfaces/tobago/model/SelectableUnitTest.java   |    31 -
 .../tobago/model/SuggestFilterUnitTest.java        |    33 -
 .../myfaces/tobago/model/SwitchTypeUnitTest.java   |    31 -
 .../myfaces/tobago/model/TreePathUnitTest.java     |   110 -
 .../renderkit/LabelWithAccessKeyUnitTest.java      |   124 -
 .../tobago/renderkit/css/ClassesUnitTest.java      |   122 -
 .../tobago/renderkit/css/CustomClassUnitTest.java  |    43 -
 .../tobago/renderkit/css/StyleUnitTest.java        |    99 -
 .../tobago/renderkit/css/TobagoClassUnitTest.java  |    62 -
 .../tobago/renderkit/html/AriasUnitTest.java       |    43 -
 .../renderkit/html/DataAttributesUnitTest.java     |    46 -
 .../renderkit/html/HtmlElementsUnitTest.java       |    58 -
 .../tobago/sanitizer/SanitizeModeUnitTest.java     |    31 -
 .../tobago/util/ComponentUtilsUnitTest.java        |    55 -
 .../apache/myfaces/tobago/util/EnumUnitTest.java   |    62 -
 .../tobago/util/HtmlWriterUtilsUnitTest.java       |   122 -
 .../tobago/util/JavascriptWriterUtilsTest.java     |    58 -
 .../myfaces/tobago/util/LocaleUtilsUnitTest.java   |    60 -
 .../myfaces/tobago/util/RangeParserUnitTest.java   |    60 -
 .../webapp/TobagoResponseWriterUnitTest.java       |   151 -
 .../src/test/resources/logback-test.xml            |    36 -
 .../src/test/resources/theme-config.xml            |    42 -
 .../src/test/resources/theme-config2.xml           |    37 -
 .../src/test/resources/theme-config3.xml           |    33 -
 .../src/test/resources/theme-config4.xml           |    33 -
 .../src/test/resources/tobago-config-1.0.30.xml    |    30 -
 .../src/test/resources/tobago-config-1.5.xml       |    44 -
 .../src/test/resources/tobago-config-2.0.xml       |   102 -
 .../test/resources/tobago-config-fail-1.0.30.xml   |    27 -
 .../src/test/resources/tobago-config-fail-1.5.xml  |    30 -
 .../src/test/resources/tobago-config-fail-2.0.xml  |    29 -
 .../tobago-config-fail-unknown-version.xml         |    26 -
 .../resources/tobago-config-for-unit-tests.xml     |    33 -
 .../src/test/resources/tobago-config-merge-0.xml   |    34 -
 .../src/test/resources/tobago-config-merge-1.xml   |    53 -
 .../src/test/resources/tobago-config-merge-2.xml   |    43 -
 .../test/resources/tobago-config-untidy-2.0.xml    |   186 -
 .../src/test/resources/web-jsptaglibrary_1_2.dtd   |   108 -
 tobago-3.0.x/tobago-example/pom.xml                |   462 -
 .../src/test/jetty/override-mojarra-web.xml        |    35 -
 .../src/test/jetty/override-myfaces-web.xml        |    35 -
 .../src/test/resources/jettykeystore               |   Bin 1286 -> 0 bytes
 .../tobago-example-addressbook/pom.xml             |   402 -
 .../src/main/appended-resources/META-INF/LICENSE   |     4 -
 .../src/main/appended-resources/META-INF/NOTICE    |     2 -
 .../tobago/example/addressbook/Address.java        |   327 -
 .../tobago/example/addressbook/AddressDao.java     |    35 -
 .../DerbyShutdownServletContextListener.java       |    50 -
 .../tobago/example/addressbook/EmailAddress.java   |    75 -
 .../example/addressbook/InMemoryAddressDao.java    |    91 -
 .../tobago/example/addressbook/JpaAddressDao.java  |   102 -
 .../tobago/example/addressbook/KillSession.java    |    50 -
 .../example/addressbook/OpenJpaLoadTimeWeaver.java |    70 -
 .../tobago/example/addressbook/Picture.java        |    67 -
 .../example/addressbook/web/AdminController.java   |    75 -
 .../tobago/example/addressbook/web/Controller.java |   433 -
 .../tobago/example/addressbook/web/Countries.java  |    44 -
 .../addressbook/web/EmailAddressConverter.java     |    55 -
 .../addressbook/web/EmailAddressValidator.java     |    64 -
 .../example/addressbook/web/LocaleConverter.java   |    63 -
 .../example/addressbook/web/MessageUtils.java      |    61 -
 .../example/addressbook/web/PictureServlet.java    |    63 -
 .../addressbook/web/RandomAddressGenerator.java    |    75 -
 .../addressbook/web/SelectItemComparator.java      |    34 -
 .../addressbook/web/StartupPhaseListener.java      |    88 -
 .../src/main/resources/META-INF/persistence.xml    |    39 -
 .../src/main/resources/logback.xml                 |    36 -
 .../src/main/webapp/META-INF/context.xml           |    26 -
 .../src/main/webapp/WEB-INF/beans.xml              |    36 -
 .../src/main/webapp/WEB-INF/faces-config.xml       |    67 -
 .../src/main/webapp/WEB-INF/ibm-web-bnd.xmi        |    27 -
 .../src/main/webapp/WEB-INF/ibm-web-ext.xml        |    30 -
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    45 -
 .../src/main/webapp/WEB-INF/web.xml                |   132 -
 .../html/scarborough/standard/style/tobago.css     |    29 -
 .../html/speyside/standard/style/tobago.css        |    29 -
 .../standard/image/addressbook/icon/flag-de.png    |   Bin 545 -> 0 bytes
 .../standard/image/addressbook/icon/flag-gb.png    |   Bin 699 -> 0 bytes
 .../standard/image/addressbook/icon/flag-us.png    |   Bin 609 -> 0 bytes
 .../standard/standard/image/empty-portrait.png     |   Bin 3269 -> 0 bytes
 .../standard/standard/image/empty-portrait_de.png  |   Bin 2860 -> 0 bytes
 .../categories/preferences-systemDisabled.png      |   Bin 521 -> 0 bytes
 .../categories/preferences-systemDisabled.png      |   Bin 1766 -> 0 bytes
 .../mimetypes/x-office-address-bookDisabled.png    |   Bin 1667 -> 0 bytes
 .../address-book-splash-screen.png                 |   Bin 10989 -> 0 bytes
 .../standard/property/addressbook.properties.xml   |    59 -
 .../property/addressbook_de.properties.xml         |    60 -
 .../standard/property/error/messages.properties    |    27 -
 .../standard/standard/property/resource.properties |    98 -
 .../standard/property/resource_de.properties       |    84 -
 .../standard/property/resource_en_GB.properties    |    22 -
 .../standard/property/resource_en_US.properties    |    17 -
 .../src/main/webapp/addressbook/admin/admin.xhtml  |    40 -
 .../src/main/webapp/addressbook/admin/memory.xhtml |    40 -
 .../src/main/webapp/addressbook/editor.xhtml       |    79 -
 .../src/main/webapp/addressbook/layout/basic.xhtml |   156 -
 .../src/main/webapp/addressbook/list.xhtml         |   133 -
 .../src/main/webapp/addressbook/start.xhtml        |    67 -
 .../src/main/webapp/addressbook/tab/business.xhtml |    49 -
 .../src/main/webapp/addressbook/tab/misc.xhtml     |    32 -
 .../src/main/webapp/addressbook/tab/personal.xhtml |   128 -
 .../src/main/webapp/auth/error.xhtml               |    57 -
 .../src/main/webapp/auth/login.js                  |    45 -
 .../src/main/webapp/auth/login.xhtml               |    79 -
 .../src/main/webapp/auth/logout.js                 |    27 -
 .../src/main/webapp/auth/logout.xhtml              |    56 -
 .../src/main/webapp/error.xhtml                    |    56 -
 .../src/main/webapp/icon/favicon.ico               |   Bin 1150 -> 0 bytes
 .../src/main/webapp/index.html                     |    27 -
 .../src/test/resources/realm.properties            |    20 -
 .../tobago-example/tobago-example-assembly/pom.xml |    91 -
 .../src/main/assembly/dep.xml                      |    44 -
 .../src/main/resources/LICENSE.txt                 |   255 -
 .../src/main/resources/NOTICE.txt                  |    16 -
 .../tobago-example/tobago-example-blank/pom.xml    |    42 -
 .../apache/myfaces/tobago/example/blank/Hello.java |    50 -
 .../src/main/resources/logback.xml                 |    38 -
 .../src/main/webapp/META-INF/context.xml           |    26 -
 .../src/main/webapp/WEB-INF/faces-config.xml       |    36 -
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    35 -
 .../src/main/webapp/WEB-INF/web.xml                |    74 -
 .../src/main/webapp/helloWorld.xhtml               |    34 -
 .../src/main/webapp/index.html                     |    27 -
 .../tobago-example/tobago-example-data/pom.xml     |    37 -
 .../tobago/example/data/CantorInterval.java        |   150 -
 .../myfaces/tobago/example/data/CategoryTree.java  |    88 -
 .../myfaces/tobago/example/data/CommandNode.java   |    51 -
 .../tobago/example/data/CommandNodeFactory.java    |    40 -
 .../myfaces/tobago/example/data/Element.java       |    47 -
 .../myfaces/tobago/example/data/LocaleEntry.java   |    75 -
 .../myfaces/tobago/example/data/LocaleList.java    |    97 -
 .../tobago/example/data/MixedCommandTree.java      |    46 -
 .../myfaces/tobago/example/data/NamedNode.java     |    72 -
 .../apache/myfaces/tobago/example/data/Node.java   |   133 -
 .../apache/myfaces/tobago/example/data/Planet.java |    99 -
 .../myfaces/tobago/example/data/Salutation.java    |    48 -
 .../tobago/example/data/SalutationConverter.java   |    43 -
 .../myfaces/tobago/example/data/SmallTree.java     |    34 -
 .../apache/myfaces/tobago/example/data/Solar.java  |    42 -
 .../myfaces/tobago/example/data/SolarObject.java   |   366 -
 .../resources/META-INF/resources/data/EUR-14.png   |   Bin 3274 -> 0 bytes
 .../main/resources/META-INF/resources/data/EUR.png |   Bin 3651 -> 0 bytes
 .../resources/META-INF/resources/data/JPY-14.png   |   Bin 3672 -> 0 bytes
 .../main/resources/META-INF/resources/data/JPY.png |   Bin 3955 -> 0 bytes
 .../resources/META-INF/resources/data/TTD-14.png   |   Bin 3896 -> 0 bytes
 .../main/resources/META-INF/resources/data/TTD.png |   Bin 4358 -> 0 bytes
 .../resources/META-INF/resources/data/USD-14.png   |   Bin 3762 -> 0 bytes
 .../main/resources/META-INF/resources/data/USD.png |   Bin 4285 -> 0 bytes
 .../META-INF/resources/data/edit-solar.xhtml       |    27 -
 .../resources/data/sun-behind-mountains.jpg        |   Bin 14656 -> 0 bytes
 .../tobago-example/tobago-example-demo/pom.xml     |   785 --
 .../src/main/appended-resouces/META-INF/LICENSE    |    51 -
 .../src/main/appended-resouces/META-INF/NOTICE     |     9 -
 .../tobago/example/demo/ButtonLinkController.java  |    42 -
 .../tobago/example/demo/CkeditorController.java    |    85 -
 .../example/demo/CollapsibleBoxController.java     |    47 -
 .../tobago/example/demo/CollapsibleController.java |    60 -
 .../example/demo/CollapsiblePanelController.java   |    47 -
 .../example/demo/CollapsiblePopupController.java   |    47 -
 .../example/demo/CollapsibleSectionController.java |    47 -
 .../tobago/example/demo/ConversionController.java  |    39 -
 .../example/demo/CurrentValueController.java       |    84 -
 .../tobago/example/demo/DateController.java        |    79 -
 .../example/demo/DefaultCommandController.java     |    67 -
 .../myfaces/tobago/example/demo/DemoBundle.java    |    42 -
 .../tobago/example/demo/DemoController.java        |   294 -
 .../tobago/example/demo/EventController.java       |   260 -
 .../tobago/example/demo/ExceptionController.java   |    41 -
 .../tobago/example/demo/ExecuteController.java     |   100 -
 .../tobago/example/demo/ForEachController.java     |   114 -
 .../tobago/example/demo/FormAjaxController.java    |    57 -
 .../tobago/example/demo/FormController.java        |    53 -
 .../example/demo/FormRequiredController.java       |    57 -
 .../tobago/example/demo/GroupController.java       |   141 -
 .../myfaces/tobago/example/demo/InController.java  |    48 -
 .../example/demo/InputSuggestController.java       |   194 -
 .../myfaces/tobago/example/demo/Jsr303Bean.java    |    63 -
 .../apache/myfaces/tobago/example/demo/Login.java  |    96 -
 .../myfaces/tobago/example/demo/ManifestEntry.java |    41 -
 .../tobago/example/demo/ManifestReader.java        |    81 -
 .../tobago/example/demo/MessagesController.java    |    84 -
 .../tobago/example/demo/NavigationNode.java        |   117 -
 .../tobago/example/demo/NavigationState.java       |   143 -
 .../tobago/example/demo/NavigationTree.java        |   177 -
 .../tobago/example/demo/ObjectController.java      |    33 -
 .../tobago/example/demo/OnOffConverter.java        |    49 -
 .../myfaces/tobago/example/demo/OutController.java |    33 -
 .../tobago/example/demo/PanelController.java       |    44 -
 .../example/demo/PartialReloadController.java      |   129 -
 .../myfaces/tobago/example/demo/PlanetExample.java |    76 -
 .../tobago/example/demo/PopupController.java       |    66 -
 .../demo/PrettyUrlForMenuNavigationHandler.java    |    61 -
 .../tobago/example/demo/ProgressController.java    |    77 -
 .../tobago/example/demo/ResizeController.java      |    36 -
 .../tobago/example/demo/RoleController.java        |    56 -
 .../demo/SelectBooleanCheckboxController.java      |    88 -
 .../tobago/example/demo/SelectController.java      |    51 -
 .../tobago/example/demo/SelectItemModel.java       |   102 -
 .../example/demo/SelectManyCheckboxController.java |    66 -
 .../example/demo/SelectManyListboxController.java  |    75 -
 .../example/demo/SelectManyShuttleController.java  |    75 -
 .../example/demo/SelectOneChoiceController.java    |    39 -
 .../example/demo/SelectOneListboxController.java   |    65 -
 .../example/demo/SelectOneRadioController.java     |    61 -
 .../myfaces/tobago/example/demo/ServerInfo.java    |   126 -
 .../tobago/example/demo/SeverityController.java    |    53 -
 .../myfaces/tobago/example/demo/SheetConfig.java   |   201 -
 .../tobago/example/demo/SheetController.java       |   162 -
 .../tobago/example/demo/SheetFilterController.java |   308 -
 .../example/demo/SheetSortingController.java       |    93 -
 .../tobago/example/demo/SheetTreeController.java   |    42 -
 .../tobago/example/demo/SolarConverter.java        |    44 -
 .../tobago/example/demo/SourceFileReader.java      |    51 -
 .../tobago/example/demo/SuggestController.java     |    86 -
 .../demo/SynchronizeNavigationPhaseListener.java   |    64 -
 .../myfaces/tobago/example/demo/TabController.java |    97 -
 .../tobago/example/demo/TestController.java        |    53 -
 .../tobago/example/demo/TestExceptionHandler.java  |    74 -
 .../example/demo/TestExceptionHandlerFactory.java  |    40 -
 .../tobago/example/demo/TextareaController.java    |    57 -
 .../tobago/example/demo/ThemeController.java       |    74 -
 .../tobago/example/demo/TinyMceController.java     |    52 -
 .../example/demo/TreeCommandTypesController.java   |    60 -
 .../tobago/example/demo/TreeController.java        |    78 -
 .../tobago/example/demo/TreeEditorController.java  |   217 -
 .../tobago/example/demo/TreeSelectController.java  |    83 -
 .../tobago/example/demo/UniversalLoggingInfo.java  |   253 -
 .../tobago/example/demo/UploadController.java      |   119 -
 .../myfaces/tobago/example/demo/UploadItem.java    |    64 -
 .../tobago/example/demo/ValidationController.java  |    61 -
 .../example/demo/ValidationJsr303Controller.java   |    53 -
 .../actionlistener/SimpleTabChangeListener.java    |    55 -
 .../demo/bestpractice/BestPracticeController.java  |    87 -
 .../demo/bestpractice/ToolBarCustomizer.java       |   102 -
 .../demo/bestpractice/TransitionController.java    |    49 -
 .../demo/clientConfig/ClientConfigController.java  |   195 -
 .../clientConfig/ClientConfigPhaseListener.java    |    54 -
 .../example/demo/formatter/AbstractConverter.java  |   104 -
 .../tobago/example/demo/formatter/Converter.java   |    30 -
 .../example/demo/formatter/JspTagConverter.java    |    97 -
 .../example/demo/formatter/SourceFormatter.java    |    69 -
 .../example/demo/formatter/StringExpression.java   |   111 -
 .../example/demo/formatter/TagConverter.java       |    45 -
 .../myfaces/tobago/example/demo/info/Activity.java |    80 -
 .../tobago/example/demo/info/ActivityList.java     |    78 -
 .../example/demo/info/ActivityPhaseListener.java   |    60 -
 .../example/demo/info/ActivitySessionListener.java |    45 -
 .../example/demo/nonfacesrequest/FishPond.java     |    83 -
 .../myfaces/tobago/example/demo/sudoku/Sudoku.java |   263 -
 .../src/main/resources/logback.xml                 |    36 -
 .../apache/myfaces/tobago/example/demo/Demo.xml    |   429 -
 .../apache/myfaces/tobago/example/demo/Demo_de.xml |   196 -
 .../tobago/example/demo/demo_en.properties.xml     |    24 -
 .../tobago/example/demo/demo_ja.properties.xml     |    24 -
 .../tobago/example/demo/demo_ru.properties.xml     |    24 -
 .../src/main/webapp/META-INF/context.xml           |    26 -
 .../src/main/webapp/WEB-INF/beans.xml              |    32 -
 .../src/main/webapp/WEB-INF/faces-config.xml       |    91 -
 .../src/main/webapp/WEB-INF/sun-web.xml            |    33 -
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    91 -
 .../src/main/webapp/WEB-INF/web.xml                |   198 -
 .../10-intro/30-new+in+3+0/new+in+3+0.xhtml        |   157 -
 .../50-migration/97-migration/migration30.xhtml    |   304 -
 .../50-migration/98-migration/migration20.xhtml    |   192 -
 .../50-migration/99-migration/migration15.xhtml    |   229 -
 .../content/10-intro/50-migration/migration.xhtml  |    32 -
 .../src/main/webapp/content/10-intro/intro.xhtml   |    74 -
 .../20-component/010-input/10-in/in.test.js        |    50 -
 .../content/20-component/010-input/10-in/in.xhtml  |    82 -
 .../010-input/20-suggest/suggest.test.js           |   541 -
 .../010-input/20-suggest/suggest.xhtml             |    86 -
 .../010-input/30-textarea/textarea.xhtml           |    62 -
 .../20-component/010-input/40-date/date.test.js    |   111 -
 .../20-component/010-input/40-date/date.xhtml      |   198 -
 .../010-input/50-input-group/group.test.js         |   108 -
 .../010-input/50-input-group/group.xhtml           |   153 -
 .../content/20-component/010-input/input.xhtml     |    55 -
 .../20-component/020-output/10-out/out.xhtml       |    59 -
 .../20-component/020-output/20-label/label.xhtml   |    58 -
 .../020-output/30-messages/messages.xhtml          |    91 -
 .../20-component/020-output/40-image/image.xhtml   |    52 -
 .../20-component/020-output/45-figure/figure.xhtml |    48 -
 .../020-output/50-progress/progress.xhtml          |    87 -
 .../20-component/020-output/60-object/object.js    |    64 -
 .../20-component/020-output/60-object/object.xhtml |    85 -
 .../content/20-component/020-output/output.xhtml   |    58 -
 .../selectBooleanCheckbox.test.js                  |   164 -
 .../selectBooleanCheckbox.xhtml                    |    77 -
 .../20-selectOneChoice/selectOneChoice.test.js     |   100 -
 .../20-selectOneChoice/selectOneChoice.xhtml       |    92 -
 .../30-selectOneRadio/selectOneRadio.test.js       |   108 -
 .../30-selectOneRadio/selectOneRadio.xhtml         |   118 -
 .../40-selectOneListbox/selectOneListbox.test.js   |   100 -
 .../40-selectOneListbox/selectOneListbox.xhtml     |    96 -
 .../selectManyCheckbox.test.js                     |   132 -
 .../50-selectManyCheckbox/selectManyCheckbox.xhtml |   100 -
 .../60-selectManyListbox/selectManyListbox.xhtml   |    90 -
 .../70-selectManyShuttle/selectManyShuttle.xhtml   |   124 -
 .../content/20-component/030-select/select.xhtml   |    78 -
 .../040-command/00-button+link/button+link.xhtml   |   154 -
 .../040-command/00-button+link/sample.html         |    24 -
 .../040-command/00-button+link/sample_de.html      |    24 -
 .../040-command/10-default/default-command.xhtml   |    78 -
 .../040-command/20-buttons/buttons.xhtml           |    82 -
 .../21-buttons-customizer/buttons-customizer.xhtml |    68 -
 .../x-buttons-item-delete.xhtml                    |    20 -
 .../x-buttons-item-edit.xhtml                      |    20 -
 .../21-buttons-customizer/x-buttons-item-new.xhtml |    20 -
 .../20-component/040-command/25-links/links.xhtml  |    75 -
 .../content/20-component/040-command/command.xhtml |    60 -
 .../20-component/050-container/10-box/box.xhtml    |    63 -
 .../050-container/20-panel/panel.xhtml             |    78 -
 .../050-container/30-separator/separator.xhtml     |    40 -
 .../050-container/40-section/section.xhtml         |    66 -
 .../50-header+footer/header+footer.xhtml           |    45 -
 .../50-header+footer/x-header-footer-example.xhtml |    41 -
 .../20-component/050-container/60-bar/bar.xhtml    |    83 -
 .../20-component/050-container/container.xhtml     |    59 -
 .../content/20-component/060-popup/popup.test.js   |   373 -
 .../content/20-component/060-popup/popup.xhtml     |   145 -
 .../070-tab/00-client/tab-client.xhtml             |    74 -
 .../20-component/070-tab/01-ajax/tab-ajax.xhtml    |   150 -
 .../070-tab/02-server/tab-server.xhtml             |   119 -
 .../webapp/content/20-component/070-tab/tab.xhtml  |    71 -
 .../00-content/sheet-column-content.xhtml          |    68 -
 .../080-sheet/10-sort/sheet-sorting.test.js        |  1182 --
 .../080-sheet/10-sort/sheet-sorting.xhtml          |    83 -
 .../20-selector/sheet-column-selector.xhtml        |    69 -
 .../080-sheet/30-event/sheet-event.test.js         |   191 -
 .../080-sheet/30-event/sheet-event.xhtml           |   121 -
 .../080-sheet/35-markup/sheet-markup.xhtml         |    66 -
 .../080-sheet/50-filter/sheet-filter.xhtml         |   111 -
 .../55-staticheader/sheet-static-header.xhtml      |   118 -
 .../60-multiheader/sheet-multi-header.xhtml        |   123 -
 .../080-sheet/70-tree/sheet-tree.xhtml             |    69 -
 .../080-sheet/80-editable/sheet-editable.xhtml     |    81 -
 .../content/20-component/080-sheet/sheet.xhtml     |    71 -
 .../20-component/080-sheet/x-sheet-nested.xhtml    |    46 -
 .../090-tree/00-command/tree-command-types.xhtml   |    50 -
 .../090-tree/01-select/tree-select.test.js         |   320 -
 .../090-tree/01-select/tree-select.xhtml           |    66 -
 .../090-tree/02-editor/tree-editor.xhtml           |    79 -
 .../20-component/090-tree/03-menu/tree-menu.xhtml  |    45 -
 .../090-tree/04-listbox/tree-listbox.xhtml         |    39 -
 .../content/20-component/090-tree/tree.xhtml       |   117 -
 .../content/20-component/100-upload/upload.xhtml   |    94 -
 .../20-component/110-wysiwyg/00-tinymce/tinymce.js |    76 -
 .../110-wysiwyg/00-tinymce/tinymce.xhtml           |    65 -
 .../110-wysiwyg/01-ckeditor/ckeditor.xhtml         |    58 -
 .../110-wysiwyg/01-ckeditor/demo-ckeditor.js       |    55 -
 .../20-component/110-wysiwyg/wysiwyg-editor.xhtml  |    68 -
 .../webapp/content/20-component/component.xhtml    |    26 -
 .../06-validation/00/content-validation.test.js    |   254 -
 .../06-validation/00/content-validation.xhtml      |   117 -
 .../06-validation/01/validation-jsr303.test.js     |   106 -
 .../06-validation/01/validation-jsr303.xhtml       |    51 -
 .../30-concept/06-validation/02/severity.xhtml     |    33 -
 .../30-concept/06-validation/validation.xhtml      |    33 -
 .../30-concept/07-conversion/conversion.xhtml      |   108 -
 .../08-form/10-required/form-required.test.js      |   221 -
 .../08-form/10-required/form-required.xhtml        |    80 -
 .../30-concept/08-form/20-ajax/form-ajax.test.js   |   546 -
 .../30-concept/08-form/20-ajax/form-ajax.xhtml     |   116 -
 .../webapp/content/30-concept/08-form/form.test.js |    76 -
 .../webapp/content/30-concept/08-form/form.xhtml   |    62 -
 .../webapp/content/30-concept/10-theme/theme.xhtml |    60 -
 .../content/30-concept/12-browser/browser.xhtml    |    25 -
 .../content/30-concept/14-locale/locale.xhtml      |    48 -
 .../30-concept/16-layout/10-flow/flow-layout.xhtml |    95 -
 .../30-concept/16-layout/20-flex/flex-layout.xhtml |    97 -
 .../16-layout/30-segment/segment-layout.xhtml      |    90 -
 .../16-layout/40-labeled/labeled-layout.xhtml      |    86 -
 .../30-concept/16-layout/50-grid/grid-layout.xhtml |    30 -
 .../content/30-concept/16-layout/layout.xhtml      |    62 -
 .../content/30-concept/20-format/format.xhtml      |    55 -
 .../webapp/content/30-concept/21-error/error.xhtml |    49 -
 .../30-concept/21-error/x-error-in-syntax.xhtml    |    24 -
 .../30-concept/23-transition/transition.xhtml      |    63 -
 .../23-transition/x-transition-after-sleep.xhtml   |    28 -
 .../24-non-faces-response/non-faces-response.xhtml |    49 -
 .../30-concept/24-non-faces-response/x-sample.pdf  |   Bin 10723 -> 0 bytes
 .../facelets-as-resources.xhtml                    |    34 -
 .../content/30-concept/50-partial/partial.css      |    20 -
 .../content/30-concept/50-partial/partial.xhtml    |   144 -
 .../30-concept/51-for-each/for-each.test.js        |    73 -
 .../content/30-concept/51-for-each/for-each.xhtml  |    81 -
 .../00-collapsible-box/collapsible-box.test.js     |   408 -
 .../00-collapsible-box/collapsible-box.xhtml       |   149 -
 .../10-collapsible-popup/collapsible-popup.test.js |   207 -
 .../10-collapsible-popup/collapsible-popup.xhtml   |    96 -
 .../20-collapsible-panel/collapsible-panel.test.js |   339 -
 .../20-collapsible-panel/collapsible-panel.xhtml   |   123 -
 .../collapsible-section.test.js                    |   340 -
 .../collapsible-section.xhtml                      |   121 -
 .../30-concept/53-collapsible/collapsible.xhtml    |   101 -
 .../30-concept/65-accessKey/accessKey.xhtml        |    92 -
 .../30-concept/70-dataAttribute/dataAttribute.js   |    69 -
 .../70-dataAttribute/dataAttribute.xhtml           |    71 -
 .../content/30-concept/75-resize/resize.xhtml      |    35 -
 .../webapp/content/30-concept/77-focus/focus.xhtml |    45 -
 .../30-concept/80-security/10/sanitize.xhtml       |    33 -
 .../30-concept/80-security/20-roles/roles.xhtml    |    81 -
 .../80-security/content-security-policy.xhtml      |    54 -
 .../90-non-faces-request/non-faces-request.xhtml   |    45 -
 .../90-non-faces-request/x-fish-pond.xhtml         |    46 -
 .../main/webapp/content/30-concept/concept.xhtml   |    26 -
 .../webapp/content/35-deprecated/10-tx/tx.xhtml    |    49 -
 .../15-suggest-method/suggest-method.test.js       |    75 -
 .../15-suggest-method/suggest-method.xhtml         |    53 -
 .../content/35-deprecated/20-toolBar/toolBar.xhtml |   115 -
 .../content/35-deprecated/25-menubar/menubar.xhtml |    68 -
 .../35-deprecated/70-grid-layout/grid-layout.xhtml |   101 -
 .../webapp/content/35-deprecated/deprecated.xhtml  |    25 -
 .../webapp/content/40-test/1040-date/date.test.js  |    33 -
 .../webapp/content/40-test/1040-date/date.xhtml    |    30 -
 .../content/40-test/2000-selectItem/currency.xhtml |    39 -
 .../40-test/2000-selectItem/list-of-objects.xhtml  |    54 -
 .../40-test/2000-selectItem/type-of-literals.xhtml |    58 -
 .../3000-sheet/10-sheet-types/sheet-types.test.js  |   104 -
 .../3000-sheet/10-sheet-types/sheet-types.xhtml    |    70 -
 .../3000-sheet/20-1000-entries/1000-entries.xhtml  |    43 -
 .../webapp/content/40-test/3000-sheet/sheet.xhtml  |    28 -
 .../40-test/4000-button+link/button+link.test.js   |   129 -
 .../40-test/4000-button+link/button+link.xhtml     |    89 -
 .../40-test/4000-button+link/x-action.xhtml        |    27 -
 .../content/40-test/4000-button+link/x-link.xhtml  |    27 -
 .../content/40-test/5000-form/sheet-in-form.xhtml  |    97 -
 .../rendererBase-getCurrentValue.test.js           |    45 -
 .../rendererBase-getCurrentValue.xhtml             |    44 -
 .../20-ajax-execute/ajax-execute.test.js           |   101 -
 .../50000-java/20-ajax-execute/ajax-execute.xhtml  |    65 -
 .../webapp/content/40-test/50000-java/java.xhtml   |    28 -
 .../content/40-test/6000-event/event.test.js       |   364 -
 .../webapp/content/40-test/6000-event/event.xhtml  |   103 -
 .../content/40-test/6000-event/x-event-bar.xhtml   |    27 -
 .../40-test/6000-event/x-event-button.xhtml        |    31 -
 .../6000-event/x-event-component-content.xhtml     |   133 -
 .../content/40-test/6000-event/x-event-in.xhtml    |    31 -
 .../content/40-test/6000-event/x-event-row.xhtml   |   156 -
 .../40-test/6000-event/x-event-textarea.xhtml      |    31 -
 .../4000-button+link/button+link.xhtml             |    73 -
 .../5000-lengthOfInputs/lengthOfInputs.xhtml       |    38 -
 .../content/40-test/60000-manual/manual.xhtml      |    25 -
 .../40-test/7000-layout/markup-spread-flex.xhtml   |    46 -
 .../40-test/7000-layout/markup-spread-grid.xhtml   |    46 -
 .../src/main/webapp/content/40-test/test.xhtml     |    28 -
 .../src/main/webapp/error/404.xhtml                |    27 -
 .../src/main/webapp/error/error.test.js            |    26 -
 .../src/main/webapp/error/exception.xhtml          |    54 -
 .../src/main/webapp/icon/favicon.ico               |   Bin 3638 -> 0 bytes
 .../src/main/webapp/image/alps.png                 |   Bin 160353 -> 0 bytes
 .../webapp/image/charlotteville/theme-photo.jpg    |   Bin 84811 -> 0 bytes
 .../src/main/webapp/image/feather-leaf.png         |   Bin 1633 -> 0 bytes
 .../src/main/webapp/image/feather-open.png         |   Bin 1631 -> 0 bytes
 .../src/main/webapp/image/feather.png              |   Bin 1617 -> 0 bytes
 .../src/main/webapp/image/richmond/theme-photo.jpg |   Bin 60609 -> 0 bytes
 .../src/main/webapp/image/scarborough/country.png  |   Bin 3407 -> 0 bytes
 .../webapp/image/scarborough/country_de_AT.png     |   Bin 1503 -> 0 bytes
 .../webapp/image/scarborough/country_de_CH.png     |   Bin 1861 -> 0 bytes
 .../webapp/image/scarborough/country_de_DE.png     |   Bin 2026 -> 0 bytes
 .../webapp/image/scarborough/country_en_GB.png     |   Bin 2107 -> 0 bytes
 .../webapp/image/scarborough/country_en_US.png     |   Bin 1705 -> 0 bytes
 .../webapp/image/scarborough/country_ja_JP.png     |   Bin 1623 -> 0 bytes
 .../webapp/image/scarborough/country_ru_RU.png     |   Bin 1843 -> 0 bytes
 .../main/webapp/image/scarborough/theme-photo.jpg  |   Bin 82245 -> 0 bytes
 .../src/main/webapp/image/speyside/theme-photo.jpg |   Bin 94846 -> 0 bytes
 .../src/main/webapp/image/standard/theme-photo.jpg |   Bin 3776 -> 0 bytes
 .../src/main/webapp/image/tobago_head.png          |   Bin 2484 -> 0 bytes
 .../tobago-example-demo/src/main/webapp/index.html |    27 -
 .../tobago-example-demo/src/main/webapp/init.xhtml |    39 -
 .../src/main/webapp/logging-info.xhtml             |    84 -
 .../src/main/webapp/login.xhtml                    |    41 -
 .../tobago-example-demo/src/main/webapp/main.xhtml |    79 -
 .../tobago-example-demo/src/main/webapp/menu.xhtml |   140 -
 .../src/main/webapp/navigation.xhtml               |    32 -
 .../src/main/webapp/plain.xhtml                    |    31 -
 .../src/main/webapp/script/demo.js                 |   110 -
 .../src/main/webapp/script/prism.js                |   682 --
 .../src/main/webapp/script/qunit-1.23.1.js         |  4334 -------
 .../src/main/webapp/script/tobago-test.js          |    40 -
 .../src/main/webapp/server-info.xhtml              |    99 -
 .../src/main/webapp/style/demo.css                 |    55 -
 .../src/main/webapp/style/prism.css                |   138 -
 .../src/main/webapp/style/qunit-1.23.1.css         |   305 -
 .../src/main/webapp/style/tobago.css               |    36 -
 .../tobago-example-demo/src/main/webapp/test.xhtml |    36 -
 .../standard/property/demo.properties.xml          |    23 -
 .../richmond/standard/property/demo.properties.xml |    23 -
 .../standard/property/demo.properties.xml          |    23 -
 .../speyside/standard/property/demo.properties.xml |    24 -
 .../src/origin/image/clickImage.psd                |   Bin 34787 -> 0 bytes
 .../src/origin/image/country.psd                   |   Bin 54825 -> 0 bytes
 .../src/origin/image/country_de_AT.psd             |   Bin 22119 -> 0 bytes
 .../src/origin/image/country_de_CH.psd             |   Bin 24348 -> 0 bytes
 .../src/origin/image/country_de_DE.psd             |   Bin 26282 -> 0 bytes
 .../src/origin/image/country_en_GB.psd             |   Bin 26279 -> 0 bytes
 .../src/origin/image/country_en_US.psd             |   Bin 23170 -> 0 bytes
 .../src/origin/image/country_ja_JP.psd             |   Bin 23830 -> 0 bytes
 .../src/origin/image/country_ru_RU.psd             |   Bin 24509 -> 0 bytes
 .../tobago/example/demo/ArquillianTest.java        |   106 -
 .../tobago/example/demo/NavigationUnitTest.java    |    67 -
 .../myfaces/tobago/example/demo/QUnitTests.java    |   429 -
 .../tobago/example/demo/sudoku/SudokuUnitTest.java |    73 -
 .../src/test/resources/arquillian.xml              |     1 -
 .../src/test/resources/realm.properties            |    20 -
 .../src/test/resources/server.xml                  |    39 -
 .../src/test/tomee/conf/tomcat-users.xml           |    25 -
 .../tobago-example/tobago-example-portlet/pom.xml  |    29 -
 .../myfaces/tobago/example/portlet/User.java       |    32 -
 .../src/main/resources/logback.xml                 |    38 -
 .../src/main/webapp/WEB-INF/faces-config.xml       |    50 -
 .../src/main/webapp/WEB-INF/liferay-portlet.xml    |    27 -
 .../src/main/webapp/WEB-INF/portlet.xml            |    41 -
 .../src/main/webapp/WEB-INF/web.xml                |    46 -
 .../src/main/webapp/hello.xhtml                    |    32 -
 .../src/main/webapp/index.xhtml                    |    32 -
 .../tobago-example/tobago-example-test/pom.xml     |   292 -
 .../myfaces/tobago/example/test/Attribute.java     |    56 -
 .../myfaces/tobago/example/test/Bootstrap.java     |    51 -
 .../example/test/ClientConfigController.java       |   156 -
 .../tobago/example/test/DateController.java        |    51 -
 .../tobago/example/test/DirectoryBrowser.java      |   108 -
 .../myfaces/tobago/example/test/DynamicBean.java   |    62 -
 .../myfaces/tobago/example/test/DynamicPanel.java  |    40 -
 .../myfaces/tobago/example/test/DynamicPanel1.java |    33 -
 .../myfaces/tobago/example/test/DynamicPanel2.java |    42 -
 .../myfaces/tobago/example/test/DynamicPanel3.java |    44 -
 .../myfaces/tobago/example/test/ErrorTest.java     |    28 -
 .../tobago/example/test/ErrorTestException.java    |    27 -
 .../apache/myfaces/tobago/example/test/Hidden.java |    56 -
 .../myfaces/tobago/example/test/Immediate.java     |    80 -
 .../apache/myfaces/tobago/example/test/InBean.java |    45 -
 .../example/test/InputSuggestController.java       |    48 -
 .../myfaces/tobago/example/test/KillSession.java   |    40 -
 .../myfaces/tobago/example/test/MeasureBean.java   |    95 -
 .../myfaces/tobago/example/test/Messages.java      |    44 -
 .../myfaces/tobago/example/test/PageItem.java      |    91 -
 .../myfaces/tobago/example/test/Partially.java     |    72 -
 .../myfaces/tobago/example/test/PopupData.java     |    33 -
 .../tobago/example/test/PopupModalAttribute.java   |    31 -
 .../example/test/PopupReferenceController.java     |   110 -
 .../myfaces/tobago/example/test/Progress.java      |    43 -
 .../apache/myfaces/tobago/example/test/Reload.java |    51 -
 .../myfaces/tobago/example/test/ResourceBean.java  |    79 -
 .../myfaces/tobago/example/test/ResourceEntry.java |    97 -
 .../myfaces/tobago/example/test/ResourceType.java  |    25 -
 .../myfaces/tobago/example/test/ScriptEvent.java   |    50 -
 .../tobago/example/test/ScriptEventItem.java       |    47 -
 .../tobago/example/test/ScriptEventServlet.java    |    57 -
 .../example/test/SelectBooleanCheckboxBean.java    |    80 -
 .../tobago/example/test/SelectManyListboxBean.java |   120 -
 .../tobago/example/test/SheetController.java       |    67 -
 .../tobago/example/test/SheetSortController.java   |   141 -
 .../myfaces/tobago/example/test/Shuttle.java       |    47 -
 .../tobago/example/test/TestExceptionHandler.java  |    69 -
 .../example/test/TestExceptionHandlerFactory.java  |    40 -
 .../tobago/example/test/TestPageFilter.java        |   132 -
 .../myfaces/tobago/example/test/Tobago1041.java    |    64 -
 .../tobago/example/test/TreeController.java        |    79 -
 .../tobago/example/test/TrueAndFalseList.java      |    31 -
 .../example/test/UndefinedRowCountDataModel.java   |    36 -
 .../apache/myfaces/tobago/example/test/Upload.java |    60 -
 .../myfaces/tobago/example/test/Version.java       |    63 -
 .../myfaces/tobago/example/test/WaitFilter.java    |    64 -
 .../tobago/example/test/ZIndexController.java      |    44 -
 .../src/main/resources/META-INF/popup.xhtml        |    38 -
 .../META-INF/tobago-example-test.taglib.xml        |    32 -
 .../src/main/resources/logback.xml                 |    36 -
 .../tobago-example-test/src/main/webapp/404.xhtml  |    39 -
 .../tobago-example-test/src/main/webapp/500.xhtml  |    38 -
 .../src/main/webapp/WEB-INF/faces-config.xml       |   262 -
 .../src/main/webapp/WEB-INF/sun-web.xml            |    33 -
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    58 -
 .../src/main/webapp/WEB-INF/web.xml                |   164 -
 .../src/main/webapp/facet/contextMenu/panel.xhtml  |    66 -
 .../src/main/webapp/image/feather-leaf.png         |   Bin 1633 -> 0 bytes
 .../src/main/webapp/image/foo.gif                  |   Bin 1579 -> 0 bytes
 .../src/main/webapp/image/foo.png                  |   Bin 247 -> 0 bytes
 .../src/main/webapp/image/fooDisabled.gif          |   Bin 1568 -> 0 bytes
 .../src/main/webapp/image/fooDisabled.png          |   Bin 199 -> 0 bytes
 .../src/main/webapp/image/wait/cat.jpg             |   Bin 5921 -> 0 bytes
 .../src/main/webapp/immediate.xhtml                |    47 -
 .../tobago-example-test/src/main/webapp/index.html |    27 -
 .../src/main/webapp/meta-test/meta-0-ok.xhtml      |    29 -
 .../src/main/webapp/meta-test/meta-1-fail.xhtml    |    33 -
 .../src/main/webapp/meta-test/meta-2-ok.xhtml      |    29 -
 .../src/main/webapp/meta-test/meta-3-ok.xhtml      |    29 -
 .../main/webapp/meta-test/meta-4-not-tobago.xhtml  |    28 -
 .../webapp/meta-test/meta-5-error-on-server.xhtml  |    30 -
 .../src/main/webapp/navigation.xhtml               |    65 -
 .../src/main/webapp/partially/encoding.xhtml       |    72 -
 .../src/main/webapp/pidgeon-point.jpg              |   Bin 15539 -> 0 bytes
 .../src/main/webapp/pidgeon-pointDisabled.jpg      |   Bin 12227 -> 0 bytes
 .../src/main/webapp/pidgeon-pointHover.jpg         |   Bin 12158 -> 0 bytes
 .../src/main/webapp/resource-manager/image.xhtml   |    42 -
 .../src/main/webapp/resource-manager/script.xhtml  |   100 -
 .../src/main/webapp/script/tobago-assert.js        |   169 -
 .../src/main/webapp/script/tobago.js               |    22 -
 .../src/main/webapp/simple.xhtml                   |    28 -
 .../src/main/webapp/style/tobago.css               |    20 -
 .../webapp/test/accessKey/accessKey-auto-off.xhtml |    39 -
 .../webapp/test/accessKey/accessKey-auto-on.xhtml  |    39 -
 .../src/main/webapp/test/attribute/attribute.xhtml |    80 -
 .../main/webapp/test/attribute/mode-valueIfSet.js  |    39 -
 .../webapp/test/attribute/mode-valueIfSet.xhtml    |   106 -
 .../test/attribute/popup-modal.selenium.html       |   143 -
 .../main/webapp/test/attribute/popup-modal.xhtml   |    39 -
 .../src/main/webapp/test/box/box-box-auto.xhtml    |    62 -
 .../main/webapp/test/box/box-box-relative.xhtml    |    43 -
 .../src/main/webapp/test/box/box.xhtml             |    45 -
 .../webapp/test/button/button-static-layout.xhtml  |    50 -
 .../main/webapp/test/button/defaultCommand.xhtml   |    42 -
 .../test/button/link-attribute.selenium.html       |    77 -
 .../main/webapp/test/button/link-attribute.xhtml   |    34 -
 .../src/main/webapp/test/button/plain.html         |    22 -
 .../src/main/webapp/test/button/plain.xhtml        |    31 -
 .../src/main/webapp/test/button/plain_de.html      |    22 -
 .../src/main/webapp/test/button/plain_de.xhtml     |    31 -
 .../src/main/webapp/test/cell/3x3-center.xhtml     |    45 -
 .../webapp/test/cell/position-4x4-span-steps.xhtml |    73 -
 .../src/main/webapp/test/cell/subview.xhtml        |    51 -
 .../src/main/webapp/test/date/date-layout.xhtml    |    43 -
 .../main/webapp/test/date/date-tobago-1105.xhtml   |    72 -
 .../src/main/webapp/test/date/date.xhtml           |    89 -
 .../src/main/webapp/test/date/datetime.js          |   178 -
 .../src/main/webapp/test/date/datetime.xhtml       |   496 -
 .../main/webapp/test/error/display-exception.xhtml |    39 -
 .../main/webapp/test/error/throw-exception.xhtml   |    47 -
 .../src/main/webapp/test/file/file-markup.xhtml    |    40 -
 .../src/main/webapp/test/file/file.xhtml           |    31 -
 .../test/flexLayout/flexLayout-horizontal.xhtml    |    33 -
 .../webapp/test/flexLayout/flexLayout-simple.xhtml |    29 -
 .../test/flexLayout/flexLayout-vertical.xhtml      |    36 -
 .../test/flowLayout/flowLayout-textAlign.xhtml     |    83 -
 .../src/main/webapp/test/footer/footer-fixed.xhtml |    63 -
 .../src/main/webapp/test/footer/footer.xhtml       |    63 -
 .../main/webapp/test/forEach/dynamic-include.xhtml |    61 -
 .../webapp/test/forEach/panel-one-fragment.xhtml   |    33 -
 .../webapp/test/forEach/panel-three-fragment.xhtml |    34 -
 .../webapp/test/forEach/panel-two-fragment.xhtml   |    34 -
 .../test/gridLayout/auto-vertical-in+in.xhtml      |    41 -
 .../gridLayout/constraints-border+padding.xhtml    |    40 -
 .../test/gridLayout/constraints-border.xhtml       |    38 -
 .../test/gridLayout/constraints-padding.xhtml      |    38 -
 .../gridLayout/current-vs-preferred-in-auto.xhtml  |    41 -
 .../horizontal-600px-asterisk-default.xhtml        |    36 -
 .../horizontal-600px-default-300px.xhtml           |    38 -
 .../horizontal-600px-default-default.xhtml         |    36 -
 .../horizontal-default-default-600px.xhtml         |    38 -
 .../webapp/test/gridLayout/margin-fallback.xhtml   |    36 -
 .../src/main/webapp/test/gridLayout/margin.xhtml   |    39 -
 .../src/main/webapp/test/gridLayout/nested-4.xhtml |    76 -
 .../webapp/test/gridLayout/nested-simple.xhtml     |    44 -
 .../src/main/webapp/test/gridLayout/nested-v.xhtml |    47 -
 .../src/main/webapp/test/gridLayout/nested.xhtml   |    80 -
 .../webapp/test/gridLayout/not-exact-4x4.xhtml     |    68 -
 .../main/webapp/test/gridLayout/not-exact.xhtml    |    39 -
 .../test/gridLayout/position-1+1x1-span.xhtml      |    40 -
 .../test/gridLayout/position-10x10-span.xhtml      |   120 -
 .../webapp/test/gridLayout/position-2x2-out.xhtml  |    42 -
 .../test/gridLayout/position-2x2-span-bottom.xhtml |    43 -
 .../test/gridLayout/position-2x2-span-left.xhtml   |    42 -
 .../test/gridLayout/position-2x2-span-right.xhtml  |    42 -
 .../test/gridLayout/position-2x2-span-top.xhtml    |    43 -
 .../main/webapp/test/gridLayout/position-2x2.xhtml |    42 -
 .../test/gridLayout/position-4x4-span-steps.xhtml  |    68 -
 .../gridLayout/proportion-versus-minimum.xhtml     |    51 -
 .../relative-inside-auto-1-1-cannot-match.xhtml    |    62 -
 .../test/gridLayout/relative-inside-auto-1-1.xhtml |    62 -
 .../test/gridLayout/relative-inside-auto-1-3.xhtml |    62 -
 .../relative-inside-auto-2-columns.xhtml           |    48 -
 .../gridLayout/relative-inside-auto-2-rows.xhtml   |    48 -
 .../gridLayout/rendered-auto-2x2-all-but-1.xhtml   |    49 -
 .../gridLayout/rendered-auto-2x2-all-but-2.xhtml   |    49 -
 .../gridLayout/rendered-auto-2x2-all-but-3.xhtml   |    49 -
 .../gridLayout/rendered-auto-2x2-all-but-4.xhtml   |    49 -
 .../rendered-combinations-3-images-fragment.xhtml  |    43 -
 .../test/gridLayout/rendered-combinations.xhtml    |   284 -
 .../gridLayout/rendered-pixel-2x2-all-but-1.xhtml  |    41 -
 .../gridLayout/rendered-pixel-2x2-all-but-2.xhtml  |    41 -
 .../gridLayout/rendered-pixel-2x2-all-but-3.xhtml  |    41 -
 .../gridLayout/rendered-pixel-2x2-all-but-4.xhtml  |    41 -
 .../gridLayout/rendered-prop-2x2-all-but-1.xhtml   |    42 -
 .../gridLayout/rendered-prop-2x2-all-but-2.xhtml   |    42 -
 .../gridLayout/rendered-prop-2x2-all-but-3.xhtml   |    42 -
 .../gridLayout/rendered-prop-2x2-all-but-4.xhtml   |    42 -
 .../src/main/webapp/test/gridLayout/rigid.xhtml    |   140 -
 .../test/gridLayout/scrolling-2-levels.xhtml       |    60 -
 .../webapp/test/gridLayout/scrolling-box.xhtml     |    52 -
 .../webapp/test/gridLayout/scrolling-page.xhtml    |    49 -
 .../gridLayout/scrolling-panel-with-border.xhtml   |    53 -
 .../webapp/test/gridLayout/scrolling-panel.xhtml   |    52 -
 .../webapp/test/gridLayout/scrolling-tab.xhtml     |    57 -
 .../main/webapp/test/gridLayout/size-auto.xhtml    |    44 -
 .../main/webapp/test/gridLayout/size-maximum.xhtml |    39 -
 .../main/webapp/test/gridLayout/size-minimum.xhtml |    39 -
 .../webapp/test/gridLayout/size-preferred.xhtml    |    39 -
 .../src/main/webapp/test/gridLayout/size-set.xhtml |    36 -
 .../webapp/test/gridLayout/spacing-nested.xhtml    |   125 -
 .../webapp/test/gridLayout/spacing-simple.xhtml    |    52 -
 .../test/gridLayout/tabGroup-auto-auto.xhtml       |    69 -
 .../webapp/test/gridLayout/tabGroup-auto.xhtml     |    69 -
 .../webapp/test/gridLayout/tabGroup-relative.xhtml |    56 -
 .../main/webapp/test/gridLayout/tobago-1239.xhtml  |    43 -
 .../main/webapp/test/gridLayout/tobago-1243.xhtml  |    51 -
 .../gridLayout/too-less-components-empty.xhtml     |    31 -
 .../too-less-components-horizontal-6.xhtml         |    40 -
 .../too-less-components-horizontal.xhtml           |    36 -
 .../too-less-components-vertical-6.xhtml           |    40 -
 .../gridLayout/too-less-components-vertical.xhtml  |    36 -
 .../test/gridLayout/too-much-components.xhtml      |    42 -
 .../transparent-for-layout-fragment.xhtml          |    29 -
 .../test/gridLayout/transparent-for-layout.xhtml   |    54 -
 .../src/main/webapp/test/header/header-fixed.xhtml |    62 -
 .../src/main/webapp/test/header/header.xhtml       |    62 -
 .../src/main/webapp/test/hidden/hidden.xhtml       |    61 -
 .../main/webapp/test/image/alphaBlendingBug.xhtml  |    57 -
 .../src/main/webapp/test/image/disabled.xhtml      |    52 -
 .../src/main/webapp/test/image/image.xhtml         |    38 -
 .../src/main/webapp/test/in/id-and-fieldId.js      |    87 -
 .../src/main/webapp/test/in/id-and-fieldId.xhtml   |   139 -
 .../src/main/webapp/test/in/in-layout.xhtml        |    45 -
 .../src/main/webapp/test/in/in-tx.xhtml            |    41 -
 .../src/main/webapp/test/in/in.xhtml               |    38 -
 .../src/main/webapp/test/label/for-auto.xhtml      |   117 -
 .../src/main/webapp/test/label/label-tx.xhtml      |    39 -
 .../src/main/webapp/test/label/label.xhtml         |    45 -
 .../src/main/webapp/test/link/link-layout.xhtml    |    59 -
 .../webapp/test/markup/tobago-1215.selenium.html   |    59 -
 .../src/main/webapp/test/markup/tobago-1215.xhtml  |    43 -
 .../test/messages/messages-confirmation.xhtml      |    37 -
 .../src/main/webapp/test/messages/messages.xhtml   |    35 -
 .../src/main/webapp/test/object/object-full.xhtml  |    43 -
 .../src/main/webapp/test/page/html.xhtml           |    40 -
 .../src/main/webapp/test/page/page.xhtml           |    28 -
 .../test/popup/popup-bug-tobago-1091.selenium.html |    57 -
 .../webapp/test/popup/popup-bug-tobago-1091.xhtml  |    66 -
 .../test/popup/popup-bug-tobago-1103.selenium.html |   157 -
 .../webapp/test/popup/popup-bug-tobago-1103.xhtml  |    97 -
 ...popup-close-after-submit-and-ajax.selenium.html |    67 -
 .../popup/popup-close-after-submit-and-ajax.xhtml  |    65 -
 .../test/popup/popup-draggable.selenium.html       |    67 -
 .../main/webapp/test/popup/popup-draggable.xhtml   |    48 -
 .../main/webapp/test/popup/popup-in-sheet.xhtml    |   108 -
 .../src/main/webapp/test/popup/z-index.xhtml       |   388 -
 .../test/progress/progress-tobago-1218.xhtml       |    32 -
 .../src/main/webapp/test/progress/progress.xhtml   |    32 -
 .../src/main/webapp/test/reload/tip.xhtml          |    49 -
 .../webapp/test/resource/resource-manager.xhtml    |    51 -
 .../src/main/webapp/test/resource/tobago-694.xhtml |    43 -
 .../src/main/webapp/test/script/script-event.js    |    37 -
 .../src/main/webapp/test/script/script-event.xhtml |    75 -
 .../src/main/webapp/test/section/section.xhtml     |    52 -
 .../test/segmentLayout/buttons-with-image.xhtml    |    98 -
 .../main/webapp/test/segmentLayout/simple-1.xhtml  |    33 -
 .../main/webapp/test/segmentLayout/simple-2.xhtml  |    38 -
 .../main/webapp/test/segmentLayout/simple-3.xhtml  |    43 -
 .../checkbox-bug-tobago-1041.xhtml                 |   181 -
 .../selectBooleanCheckbox-layout.xhtml             |    49 -
 .../selectBooleanCheckbox.xhtml                    |   132 -
 .../selectManyCheckbox-layout.xhtml                |    48 -
 .../selectManyCheckbox/selectManyCheckbox.xhtml    |    96 -
 .../selectManyListbox-layout.xhtml                 |    48 -
 .../selectManyListbox-value.xhtml                  |    76 -
 .../test/selectManyListbox/selectManyListbox.xhtml |    86 -
 .../selectManyShuttle-layout.xhtml                 |    50 -
 .../selectManyShuttle-value.selenium.html          |    80 -
 .../selectManyShuttle-value.xhtml                  |    66 -
 .../test/selectManyShuttle/selectManyShuttle.xhtml |    87 -
 .../selectOneChoice/selectOneChoice-layout.xhtml   |    48 -
 .../test/selectOneChoice/selectOneChoice.xhtml     |    88 -
 .../selectOneListbox/selectOneListbox-layout.xhtml |    48 -
 .../test/selectOneListbox/selectOneListbox.xhtml   |    86 -
 .../selectOneRadio/selectOneRadio-layout.xhtml     |    48 -
 .../test/selectOneRadio/selectOneRadio.xhtml       |    96 -
 .../separator/separator-with-label-facet.xhtml     |    41 -
 .../test/separator/separator-with-label.xhtml      |    37 -
 .../test/separator/separator-without-label.xhtml   |    37 -
 .../sheet/sheet-auto-height-header-footer.xhtml    |   125 -
 .../webapp/test/sheet/sheet-auto-height-rows.xhtml |    98 -
 .../main/webapp/test/sheet/sheet-auto-width.xhtml  |    52 -
 .../test/sheet/sheet-bug-tobago-1090.selenium.html |    89 -
 .../webapp/test/sheet/sheet-bug-tobago-1090.xhtml  |    55 -
 .../src/main/webapp/test/sheet/sheet-large.js      |    34 -
 .../src/main/webapp/test/sheet/sheet-large.xhtml   |    66 -
 .../webapp/test/sheet/sheet-multi-header.xhtml     |   103 -
 .../webapp/test/sheet/sheet-paging-1.selenium.html |    44 -
 .../main/webapp/test/sheet/sheet-paging-1.xhtml    |    36 -
 .../test/sheet/sheet-paging-11.selenium.html       |    44 -
 .../main/webapp/test/sheet/sheet-paging-11.xhtml   |    39 -
 .../test/sheet/sheet-paging-20.selenium.html       |    44 -
 .../main/webapp/test/sheet/sheet-paging-20.xhtml   |    36 -
 .../src/main/webapp/test/sheet/sheet-reload.js     |    38 -
 .../src/main/webapp/test/sheet/sheet-reload.xhtml  |    54 -
 .../webapp/test/sheet/sheet-selector.selenium.html |   354 -
 .../main/webapp/test/sheet/sheet-selector.xhtml    |    78 -
 .../src/main/webapp/test/sheet/sheet-simple.js     |    27 -
 .../src/main/webapp/test/sheet/sheet-simple.xhtml  |    43 -
 .../webapp/test/sheet/sheet-sort.selenium.html     |   219 -
 .../src/main/webapp/test/sheet/sheet-sort.xhtml    |    58 -
 .../src/main/webapp/test/sheet/sheet-tree.xhtml    |    56 -
 .../test/sheet/sheet-unknown-row-count.xhtml       |    40 -
 .../sheet/sheet-without-columns-definition.xhtml   |    34 -
 .../main/webapp/test/suggest/tc-in-suggest.xhtml   |    34 -
 .../main/webapp/test/suggest/tx-in-suggest.xhtml   |    34 -
 .../src/main/webapp/test/tabGroup/client.xhtml     |    56 -
 .../test/tabGroup/selectedIndexWithoutSetter.xhtml |    35 -
 .../src/main/webapp/test/tabGroup/simple.xhtml     |   102 -
 .../test/tabGroup/tabGroup-layout-1164.xhtml       |    46 -
 .../main/webapp/test/text/textarea-layout.xhtml    |    42 -
 .../src/main/webapp/test/time/time.xhtml           |   105 -
 .../src/main/webapp/test/tree/tree-command.xhtml   |    40 -
 .../webapp/test/tree/tree-expanded.selenium.html   |    72 -
 .../src/main/webapp/test/tree/tree-expanded.xhtml  |    41 -
 .../src/main/webapp/test/tree/tree-infinite.xhtml  |    45 -
 .../test/tree/tree-marked-with-model.selenium.html |    98 -
 .../webapp/test/tree/tree-marked-with-model.xhtml  |    61 -
 .../tree/tree-marked-without-model.selenium.html   |    98 -
 .../test/tree/tree-marked-without-model.xhtml      |    59 -
 .../webapp/test/tree/tree-select-via-state.xhtml   |    49 -
 .../webapp/test/tree/tree-select-via-value.xhtml   |    50 -
 .../webapp/test/tree/tree-select.selenium.html     |   113 -
 .../webapp/test/tree/tree-show-attributes.xhtml    |    90 -
 .../webapp/test/tree/tree-simple-with-data.xhtml   |    42 -
 .../src/main/webapp/test/tree/tree-simple.xhtml    |    41 -
 .../main/webapp/test/treeListbox/treeListbox.xhtml |    34 -
 .../webapp/test/treeMenu/treeMenu-command.xhtml    |    39 -
 .../webapp/test/treeMenu/treeMenu-simple.xhtml     |    39 -
 .../test/type/measure-image-with-constraints.xhtml |   142 -
 .../type/measure-image-without-constraints.xhtml   |   112 -
 .../src/main/webapp/test/version/version.js        |    44 -
 .../src/main/webapp/test/version/version.xhtml     |    50 -
 .../html/standard/standard/script/tobago.js        |    22 -
 .../tobago/example/test/AutomaticSeleniumTest.java |   129 -
 .../tobago/example/test/SeleniumScript.java        |   116 -
 .../tobago/example/test/SeleniumScriptItem.java    |    44 -
 .../myfaces/tobago/example/test/SeleniumTest.java  |    57 -
 .../tobago/example/test/SimpleSeleniumTest.java    |    35 -
 .../example/test/TestPageFilterUnitTest.java       |    45 -
 .../example/test/TestTheAutomaticSeleniumTest.java |   130 -
 .../tobago/example/test/TobagoSelenium.java        |    98 -
 tobago-3.0.x/tobago-extension/pom.xml              |    40 -
 .../tobago-extension/tobago-sandbox/pom.xml        |   289 -
 .../tobago-extension/tobago-sandbox/readme.txt     |     6 -
 .../src/main/appended-resources/META-INF/NOTICE    |     3 -
 .../src/main/faces-config/faces-config.xml         |    28 -
 .../internal/component/AbstractUINumberSlider.java |    47 -
 .../internal/component/AbstractUISplitLayout.java  |   135 -
 .../taglib/sandbox/NumberSliderTagDeclaration.java |    64 -
 .../taglib/sandbox/SplitLayoutTagDeclaration.java  |    73 -
 .../internal/taglib/sandbox/package-info.java      |    33 -
 .../sandbox/standard/tag/NumberSliderRenderer.java |   185 -
 .../standard/tag/SplitLayoutRenderer.java          |   166 -
 .../src/main/resources/META-INF/tobago-config.xml  |    47 -
 .../html/scarborough/standard/image/sliderEnd.png  |   Bin 71 -> 0 bytes
 .../scarborough/standard/image/sliderTriangle.png  |   Bin 92 -> 0 bytes
 .../html/scarborough/standard/script/tobago.js     |    81 -
 .../html/scarborough/standard/style/tobago.css     |    63 -
 tobago-3.0.x/tobago-pmd-config.xml                 |    52 -
 tobago-3.0.x/tobago-theme/pom.xml                  |   236 -
 tobago-3.0.x/tobago-theme/rebuild-theme.sh         |    50 -
 .../tobago-theme-charlotteville/pom.xml            |    44 -
 .../src/main/appended-resources/META-INF/NOTICE    |     3 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ------------
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 -
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 -
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ------
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 -
 .../src/main/resources/META-INF/tobago-config.xml  |    55 -
 .../src/main/scss/_custom.scss                     |    26 -
 .../src/main/scss/_tobago.scss                     |   918 --
 .../tobago-theme/tobago-theme-richmond/pom.xml     |    47 -
 .../src/main/appended-resources/META-INF/NOTICE    |     4 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ------------
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 -
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 -
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ------
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 -
 .../src/main/resources/META-INF/tobago-config.xml  |    55 -
 .../src/main/scss/_custom.scss                     |    33 -
 .../src/main/scss/_tobago.scss                     |   918 --
 .../tobago-theme/tobago-theme-scarborough/pom.xml  |    45 -
 .../src/main/appended-resources/META-INF/NOTICE    |     3 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ------------
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 -
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 -
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ------
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 -
 .../src/main/resources/META-INF/tobago-config.xml  |    55 -
 .../src/main/scss/_custom.scss                     |    26 -
 .../src/main/scss/_tobago.scss                     |   918 --
 .../tobago-theme/tobago-theme-speyside/pom.xml     |    46 -
 .../src/main/appended-resources/META-INF/NOTICE    |     3 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ------------
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 -
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 -
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ------
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 -
 .../META-INF/resources/tobago/speyside/image/I.png |   Bin 80 -> 0 bytes
 .../META-INF/resources/tobago/speyside/image/L.png |   Bin 84 -> 0 bytes
 .../resources/tobago/speyside/image/Lminus.png     |   Bin 112 -> 0 bytes
 .../resources/tobago/speyside/image/Lplus.png      |   Bin 112 -> 0 bytes
 .../resources/tobago/speyside/image/MenuArrow.png  |   Bin 88 -> 0 bytes
 .../tobago/speyside/image/MenuCheckmark.png        |   Bin 129 -> 0 bytes
 .../tobago/speyside/image/MenuRadioChecked.png     |   Bin 89 -> 0 bytes
 .../resources/tobago/speyside/image/Rminus.png     |   Bin 102 -> 0 bytes
 .../resources/tobago/speyside/image/Rplus.png      |   Bin 112 -> 0 bytes
 .../META-INF/resources/tobago/speyside/image/T.png |   Bin 83 -> 0 bytes
 .../resources/tobago/speyside/image/Tminus.png     |   Bin 112 -> 0 bytes
 .../resources/tobago/speyside/image/Tplus.png      |   Bin 112 -> 0 bytes
 .../tobago/speyside/image/box-header-bg.png        |   Bin 263 -> 0 bytes
 .../tobago/speyside/image/file-upload.png          |   Bin 189 -> 0 bytes
 .../tobago/speyside/image/label-error-bg.png       |   Bin 81 -> 0 bytes
 .../tobago/speyside/image/label_underline.png      |   Bin 68 -> 0 bytes
 .../resources/tobago/speyside/image/minus.png      |   Bin 102 -> 0 bytes
 .../resources/tobago/speyside/image/nav_bg.png     |   Bin 79 -> 0 bytes
 .../resources/tobago/speyside/image/next.png       |   Bin 80 -> 0 bytes
 .../tobago/speyside/image/nextDisabled.png         |   Bin 84 -> 0 bytes
 .../resources/tobago/speyside/image/plus.png       |   Bin 112 -> 0 bytes
 .../resources/tobago/speyside/image/poweredBy.png  |   Bin 1115 -> 0 bytes
 .../resources/tobago/speyside/image/prev.png       |   Bin 80 -> 0 bytes
 .../tobago/speyside/image/prevDisabled.png         |   Bin 84 -> 0 bytes
 .../resources/tobago/speyside/image/red.png        |   Bin 69 -> 0 bytes
 .../resources/tobago/speyside/image/remove.png     |   Bin 108 -> 0 bytes
 .../speyside/image/tab-header-selected-bg.png      |   Bin 659 -> 0 bytes
 .../speyside/image/tab-header-unselected-bg.png    |   Bin 656 -> 0 bytes
 .../resources/tobago/speyside/image/tabNext.png    |   Bin 82 -> 0 bytes
 .../tobago/speyside/image/tabNextDisabled.png      |   Bin 86 -> 0 bytes
 .../resources/tobago/speyside/image/tabPrev.png    |   Bin 82 -> 0 bytes
 .../tobago/speyside/image/tabPrevDisabled.png      |   Bin 87 -> 0 bytes
 .../tobago/speyside/image/toolbarButtonMenu.png    |   Bin 92 -> 0 bytes
 .../speyside/image/toolbarButtonMenuDisabled.png   |   Bin 92 -> 0 bytes
 .../tobago/speyside/image/treeMenuClose.png        |   Bin 99 -> 0 bytes
 .../tobago/speyside/image/treeMenuOpen.png         |   Bin 89 -> 0 bytes
 .../tobago/speyside/image/treeNode-icon-leaf.png   |   Bin 211 -> 0 bytes
 .../tobago/speyside/image/treeNode-icon-open.png   |   Bin 176 -> 0 bytes
 .../tobago/speyside/image/treeNode-icon.png        |   Bin 189 -> 0 bytes
 .../resources/tobago/speyside/image/unchecked.png  |   Bin 85 -> 0 bytes
 .../tobago/speyside/image/uncheckedDisabled.png    |   Bin 86 -> 0 bytes
 .../resources/tobago/speyside/image/upload.png     |   Bin 118 -> 0 bytes
 .../src/main/resources/META-INF/tobago-config.xml  |    55 -
 .../src/main/scss/_custom.scss                     |    26 -
 .../src/main/scss/_tobago.scss                     |   918 --
 .../lib/closure-compiler-LICENSE.txt               |   202 -
 .../lib/compiler-20120430.jar                      |   Bin 5407463 -> 0 bytes
 .../tobago-theme/tobago-theme-standard/pom.xml     |   133 -
 .../src/main/appended-resources/META-INF/LICENSE   |   263 -
 .../src/main/appended-resources/META-INF/NOTICE    |    26 -
 .../4.17.37/css/bootstrap-datetimepicker.css       |   373 -
 .../4.17.37/css/bootstrap-datetimepicker.min.css   |     5 -
 .../4.17.37/js/bootstrap-datetimepicker.js         |  2552 ----
 .../4.17.37/js/bootstrap-datetimepicker.min.js     |     9 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ------------
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 -
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 -
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 -
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ------
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 -
 .../font-awesome/4.6.1/css/font-awesome.css        |  2178 ----
 .../font-awesome/4.6.1/css/font-awesome.min.css    |     4 -
 .../font-awesome/4.6.1/fonts/FontAwesome.otf       |   Bin 123112 -> 0 bytes
 .../4.6.1/fonts/fontawesome-webfont.eot            |   Bin 75220 -> 0 bytes
 .../4.6.1/fonts/fontawesome-webfont.svg            |   685 --
 .../4.6.1/fonts/fontawesome-webfont.ttf            |   Bin 150920 -> 0 bytes
 .../4.6.1/fonts/fontawesome-webfont.woff           |   Bin 89076 -> 0 bytes
 .../4.6.1/fonts/fontawesome-webfont.woff2          |   Bin 70728 -> 0 bytes
 .../standard/jquery-ui/1.12.1.custom/jquery-ui.js  |   748 --
 .../jquery-ui/1.12.1.custom/jquery-ui.min.js       |     6 -
 .../tobago/standard/jquery/jquery-2.2.4.js         |  9814 ---------------
 .../tobago/standard/jquery/jquery-2.2.4.min.js     |     4 -
 .../tobago/standard/jquery/jquery-2.2.4.min.map    |     1 -
 .../standard/moment/2.13.0/moment-with-locales.js  | 12051 -------------------
 .../moment/2.13.0/moment-with-locales.min.js       |    76 -
 .../tobago/standard/script/tobago-calendar.js      |   250 -
 .../tobago/standard/script/tobago-console.js       |   306 -
 .../resources/tobago/standard/script/tobago-in.js  |    17 -
 .../resources/tobago/standard/script/tobago-jsf.js |  9510 ---------------
 .../tobago/standard/script/tobago-layout.js        |   269 -
 .../tobago/standard/script/tobago-overlay.js       |   134 -
 .../tobago/standard/script/tobago-popup.js         |    85 -
 .../tobago/standard/script/tobago-sheet.js         |   730 --
 .../tobago/standard/script/tobago-suggest.js       |   136 -
 .../resources/tobago/standard/script/tobago-tab.js |    94 -
 .../tobago/standard/script/tobago-tree.js          |   311 -
 .../tobago/standard/script/tobago-utils.js         |   123 -
 .../resources/tobago/standard/script/tobago.js     |  1445 ---
 .../tether/1.1.1/css/tether-theme-arrows-dark.css  |   106 -
 .../1.1.1/css/tether-theme-arrows-dark.min.css     |     1 -
 .../tether/1.1.1/css/tether-theme-arrows.css       |   110 -
 .../tether/1.1.1/css/tether-theme-arrows.min.css   |     1 -
 .../tether/1.1.1/css/tether-theme-basic.css        |    21 -
 .../tether/1.1.1/css/tether-theme-basic.min.css    |     1 -
 .../tobago/standard/tether/1.1.1/css/tether.css    |     8 -
 .../standard/tether/1.1.1/css/tether.min.css       |     1 -
 .../tobago/standard/tether/1.1.1/js/tether.js      |  1715 ---
 .../tobago/standard/tether/1.1.1/js/tether.min.js  |     1 -
 .../0.11.1-patched-with-1212/typeahead.js          |  1540 ---
 .../0.11.1-patched-with-1212/typeahead.min.js      |     7 -
 .../src/main/resources/META-INF/tobago-config.xml  |   400 -
 .../src/main/scss/_custom.scss                     |    19 -
 .../src/main/scss/_tobago.scss                     |   918 --
 .../renderkit/html/CssClassCompareUnitTest.java    |    94 -
 tobago-3.0.x/tobago-tool/pom.xml                   |    34 -
 .../tobago-tool/tobago-tool-annotation/pom.xml     |    28 -
 .../src/main/appended-resouces/META-INF/NOTICE     |     3 -
 .../myfaces/tobago/apt/annotation/Behavior.java    |    33 -
 .../apt/annotation/BodyContentDescription.java     |    37 -
 .../myfaces/tobago/apt/annotation/Category.java    |    30 -
 .../myfaces/tobago/apt/annotation/Converter.java   |    32 -
 .../tobago/apt/annotation/DynamicExpression.java   |   105 -
 .../tobago/apt/annotation/ExtensionTag.java        |    38 -
 .../myfaces/tobago/apt/annotation/Facet.java       |    44 -
 .../myfaces/tobago/apt/annotation/Preliminary.java |    36 -
 .../myfaces/tobago/apt/annotation/SimpleTag.java   |    28 -
 .../apache/myfaces/tobago/apt/annotation/Tag.java  |    44 -
 .../tobago/apt/annotation/TagAttribute.java        |    43 -
 .../myfaces/tobago/apt/annotation/Taglib.java      |    37 -
 .../tobago/apt/annotation/UIComponentTag.java      |    75 -
 .../apt/annotation/UIComponentTagAttribute.java    |    65 -
 .../myfaces/tobago/apt/annotation/Validator.java   |    32 -
 .../tobago/apt/annotation/ValidatorTag.java        |    29 -
 tobago-3.0.x/tobago-tool/tobago-tool-apt/pom.xml   |   119 -
 .../src/main/appended-resouces/META-INF/NOTICE     |     3 -
 .../apache/myfaces/tobago/apt/AnnotationUtils.java |    45 -
 .../myfaces/tobago/apt/generate/ClassInfo.java     |    92 -
 .../myfaces/tobago/apt/generate/ClassUtils.java    |    71 -
 .../myfaces/tobago/apt/generate/ComponentInfo.java |   127 -
 .../tobago/apt/generate/ComponentPropertyInfo.java |    61 -
 .../myfaces/tobago/apt/generate/Imports.java       |    67 -
 .../myfaces/tobago/apt/generate/PropertyInfo.java  |   262 -
 .../myfaces/tobago/apt/generate/RendererInfo.java  |    40 -
 .../myfaces/tobago/apt/generate/TagInfo.java       |    95 -
 .../tobago/apt/processor/AbstractGenerator.java    |   125 -
 .../apt/processor/CheckstyleConfigGenerator.java   |   350 -
 .../tobago/apt/processor/ClassesGenerator.java     |   283 -
 .../tobago/apt/processor/FacesConfigGenerator.java |   648 -
 .../tobago/apt/processor/TaglibGenerator.java      |   523 -
 .../org/apache/myfaces/tobago/apt/component.stg    |   587 -
 .../CheckstyleConfigGeneratorUnitTest.java         |    53 -
 tobago-assembly/pom.xml                            |     2 +-
 tobago-core/pom.xml                                |     2 +-
 .../internal/component/AbstractUICommand.java      |     5 +-
 .../internal/renderkit/renderer/PageRenderer.java  |     5 +
 .../myfaces/tobago/renderkit/TobagoRenderKit.java  |     3 +-
 .../myfaces/tobago/renderkit/css/TobagoClass.java  |     1 +
 tobago-example/pom.xml                             |     2 +-
 tobago-example/tobago-example-addressbook/pom.xml  |     2 +-
 tobago-example/tobago-example-assembly/pom.xml     |     2 +-
 tobago-example/tobago-example-blank/pom.xml        |     2 +-
 tobago-example/tobago-example-data/pom.xml         |     2 +-
 tobago-example/tobago-example-demo/pom.xml         |     2 +-
 .../tobago/example/demo/SheetFilterController.java |    23 +
 .../demo/bestpractice/BestPracticeController.java  |    14 +-
 .../010-input/20-suggest/suggest.test.js           |   160 +-
 .../010-input/20-suggest/suggest.xhtml             |     2 +-
 .../080-sheet/50-filter/sheet-filter.xhtml         |     6 +-
 .../24-non-faces-response/non-faces-response.xhtml |    18 +-
 .../30-concept/24-non-faces-response/x-sample.txt  |     0
 .../15-suggest-method/suggest-method.test.js       |     9 +-
 tobago-example/tobago-example-portlet/pom.xml      |     2 +-
 tobago-example/tobago-example-test/pom.xml         |     2 +-
 tobago-extension/pom.xml                           |     2 +-
 tobago-extension/tobago-sandbox/pom.xml            |     2 +-
 tobago-theme/pom.xml                               |     2 +-
 tobago-theme/tobago-theme-charlotteville/pom.xml   |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |    23 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     2 +-
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     2 +-
 .../src/main/scss/_tobago.scss                     |    23 +-
 tobago-theme/tobago-theme-richmond/pom.xml         |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |    23 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     2 +-
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     2 +-
 .../src/main/scss/_tobago.scss                     |    23 +-
 tobago-theme/tobago-theme-scarborough/pom.xml      |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |    23 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     2 +-
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     2 +-
 .../src/main/scss/_tobago.scss                     |    23 +-
 tobago-theme/tobago-theme-speyside/pom.xml         |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |    23 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     2 +-
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     2 +-
 .../src/main/scss/_tobago.scss                     |    23 +-
 tobago-theme/tobago-theme-standard/pom.xml         |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |    23 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     2 +-
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     2 +-
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     2 +-
 .../tobago/standard/script/tobago-suggest.js       |    27 +-
 .../resources/tobago/standard/script/tobago.js     |     9 +-
 .../src/main/scss/_tobago.scss                     |    23 +-
 tobago-tool/pom.xml                                |     2 +-
 tobago-tool/tobago-tool-annotation/pom.xml         |     2 +-
 tobago-tool/tobago-tool-apt/pom.xml                |     2 +-
 1759 files changed, 442 insertions(+), 242471 deletions(-)

-- 
To stop receiving notification emails like this one, please contact
"commits@myfaces.apache.org" <co...@myfaces.apache.org>.

[myfaces-tobago] 02/03: [maven-release-plugin] copy for tag tobago-3.0.3

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

deki pushed a commit to tag tobago-3.0.3
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit 217ad9a8d3b7bb7a388d46a1b9ccd0a0056d41b3
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Fri Feb 3 09:46:49 2017 +0000

    [maven-release-plugin] copy for tag tobago-3.0.3
---
 tobago-3.0.x/build-site.sh                         |    56 +
 tobago-3.0.x/pom.xml                               |  1365 +++
 tobago-3.0.x/readme.txt                            |    17 +
 tobago-3.0.x/settings-example.xml                  |    41 +
 tobago-3.0.x/src/changes/changes.xml               |   138 +
 .../src/docbook/resources/basic-controls.png       |   Bin 0 -> 27032 bytes
 .../src/docbook/resources/editor-simple.png        |   Bin 0 -> 15499 bytes
 tobago-3.0.x/src/docbook/resources/editor.png      |   Bin 0 -> 20292 bytes
 tobago-3.0.x/src/docbook/resources/list.png        |   Bin 0 -> 36110 bytes
 tobago-3.0.x/src/docbook/resources/progress.png    |   Bin 0 -> 470 bytes
 tobago-3.0.x/src/docbook/resources/slider.png      |   Bin 0 -> 446 bytes
 .../src/docbook/resources/theme-charlotteville.png |   Bin 0 -> 2783 bytes
 .../src/docbook/resources/theme-richmond.png       |   Bin 0 -> 2847 bytes
 .../src/docbook/resources/theme-scarborough.png    |   Bin 0 -> 3092 bytes
 .../src/docbook/resources/theme-speyside.png       |   Bin 0 -> 3762 bytes
 tobago-3.0.x/src/docbook/tobago-tutorial.xml       |  1515 +++
 tobago-3.0.x/src/site/apt/api.apt                  |   293 +
 tobago-3.0.x/src/site/apt/compatibility.apt        |   128 +
 tobago-3.0.x/src/site/apt/demo.apt                 |    57 +
 tobago-3.0.x/src/site/apt/download.apt             |   190 +
 tobago-3.0.x/src/site/apt/getting-started.apt      |   117 +
 tobago-3.0.x/src/site/apt/guide.apt                |   660 +
 tobago-3.0.x/src/site/apt/howto-test.apt           |    57 +
 tobago-3.0.x/src/site/apt/index.apt                |  1125 ++
 tobago-3.0.x/src/site/apt/new-2.0.apt              |   200 +
 tobago-3.0.x/src/site/apt/release-checklist.apt    |   358 +
 tobago-3.0.x/src/site/fml/faq.fml                  |   499 +
 tobago-3.0.x/src/site/resources/doap_tobago.rdf    |    87 +
 .../src/site/resources/images/addressbook.png      |   Bin 0 -> 11237 bytes
 tobago-3.0.x/src/site/resources/images/demo.png    |   Bin 0 -> 15387 bytes
 .../resources/images/guide-addressbook-about.png   |   Bin 0 -> 70610 bytes
 .../resources/images/guide-addressbook-date.png    |   Bin 0 -> 55473 bytes
 .../images/guide-addressbook-editor-simple.png     |   Bin 0 -> 47398 bytes
 .../resources/images/guide-addressbook-editor.png  |   Bin 0 -> 50108 bytes
 .../resources/images/guide-addressbook-list.png    |   Bin 0 -> 54852 bytes
 .../resources/images/guide-addressbook-logging.png |   Bin 0 -> 58469 bytes
 .../resources/images/guide-addressbook-login.png   |   Bin 0 -> 44486 bytes
 .../resources/images/guide-addressbook-memory.png  |   Bin 0 -> 43322 bytes
 .../resources/images/guide-addressbook-menu.png    |   Bin 0 -> 48348 bytes
 .../resources/images/guide-addressbook-popup.png   |   Bin 0 -> 58388 bytes
 .../resources/images/guide-addressbook-upload.png  |   Bin 0 -> 52695 bytes
 .../site/resources/images/guide-basic-controls.png |   Bin 0 -> 20121 bytes
 .../src/site/resources/images/guide-markup.png     |   Bin 0 -> 2716 bytes
 .../src/site/resources/images/guide-menu.png       |   Bin 0 -> 3907 bytes
 .../src/site/resources/images/guide-popup.png      |   Bin 0 -> 3213 bytes
 .../src/site/resources/images/guide-progress.png   |   Bin 0 -> 2405 bytes
 .../src/site/resources/images/guide-sheet.png      |   Bin 0 -> 8105 bytes
 .../site/resources/images/guide-simple-editor.png  |   Bin 0 -> 2496 bytes
 .../src/site/resources/images/guide-tab-group.png  |   Bin 0 -> 3893 bytes
 .../images/guide-theme-charlotteville.png          |   Bin 0 -> 2783 bytes
 .../site/resources/images/guide-theme-richmond.png |   Bin 0 -> 2847 bytes
 .../resources/images/guide-theme-scarborough.png   |   Bin 0 -> 3092 bytes
 .../site/resources/images/guide-theme-speyside.png |   Bin 0 -> 3762 bytes
 .../src/site/resources/images/guide-toolbar.png    |   Bin 0 -> 7279 bytes
 .../src/site/resources/images/guide-upload.png     |   Bin 0 -> 2970 bytes
 tobago-3.0.x/src/site/site.xml                     |    81 +
 tobago-3.0.x/tobago-3.0.txt                        |    22 +
 tobago-3.0.x/tobago-assembly/pom.xml               |   273 +
 .../tobago-assembly/src/main/assembly/dep.xml      |    84 +
 .../tobago-assembly/src/main/resources/LICENSE.txt |   328 +
 .../tobago-assembly/src/main/resources/NOTICE.txt  |    16 +
 .../tobago-assembly/src/main/resources/README.txt  |     6 +
 tobago-3.0.x/tobago-core/assembly-tlddoc.xml       |    43 +
 tobago-3.0.x/tobago-core/pom.xml                   |   328 +
 .../src/main/appended-resources/META-INF/NOTICE    |     3 +
 .../src/main/faces-config/faces-config.xml         |    57 +
 .../LabelValueExpressionFacesMessage.java          |    61 +
 .../myfaces/tobago/application/ProjectStage.java   |    32 +
 .../myfaces/tobago/component/Attributes.java       |   283 +
 .../myfaces/tobago/component/ClientBehaviors.java  |    50 +
 .../tobago/component/DeprecatedDimension.java      |    34 +
 .../apache/myfaces/tobago/component/Facets.java    |    84 +
 .../myfaces/tobago/component/InputSuggest.java     |    36 +
 .../myfaces/tobago/component/InputSuggest2.java    |    29 +
 .../myfaces/tobago/component/LabelLayout.java      |    91 +
 .../component/MethodBindingToMethodExpression.java |   241 +
 .../component/MethodExpressionToMethodBinding.java |   108 +
 .../myfaces/tobago/component/RendererTypes.java    |   152 +
 .../tobago/component/SelectBooleanCommand.java     |    23 +
 .../myfaces/tobago/component/SelectOneCommand.java |    23 +
 .../apache/myfaces/tobago/component/Sorter.java    |   259 +
 .../myfaces/tobago/component/SupportFieldId.java   |    27 +
 .../tobago/component/SupportsAccessKey.java        |    27 +
 .../tobago/component/SupportsLabelLayout.java      |    27 +
 .../myfaces/tobago/component/SupportsStyle.java    |    34 +
 .../tobago/component/UINamingContainer.java        |    27 +
 .../apache/myfaces/tobago/component/Visual.java    |    48 +
 .../apache/myfaces/tobago/config/TobagoConfig.java |    72 +
 .../apache/myfaces/tobago/context/Capability.java  |    40 +
 .../org/apache/myfaces/tobago/context/Markup.java  |   369 +
 .../myfaces/tobago/context/MarkupConfig.java       |    44 +
 .../myfaces/tobago/context/MarkupEditor.java       |    33 +
 .../myfaces/tobago/context/ResourceUtils.java      |    79 +
 .../org/apache/myfaces/tobago/context/Theme.java   |    44 +
 .../apache/myfaces/tobago/context/ThemeImpl.java   |   303 +
 .../myfaces/tobago/context/ThemeResource.java      |    58 +
 .../myfaces/tobago/context/ThemeResources.java     |    82 +
 .../apache/myfaces/tobago/context/ThemeScript.java |    26 +
 .../apache/myfaces/tobago/context/ThemeStyle.java  |    26 +
 .../myfaces/tobago/context/TobagoBundle.java       |   138 +
 .../myfaces/tobago/context/TobagoContext.java      |   110 +
 .../tobago/context/TobagoMessageBundle.java        |    44 +
 .../tobago/context/TobagoResourceBundle.java       |    41 +
 .../tobago/context/TransientStateHolder.java       |    73 +
 .../apache/myfaces/tobago/context/UserAgent.java   |   390 +
 .../myfaces/tobago/convert/CurrencyConverter.java  |    58 +
 .../myfaces/tobago/convert/DurationConverter.java  |   148 +
 .../myfaces/tobago/convert/LocaleConverter.java    |    50 +
 .../myfaces/tobago/convert/MeasureConverter.java   |    58 +
 .../myfaces/tobago/convert/ThemeConverter.java     |    62 +
 .../tobago/el/ConstantMethodExpression.java        |   103 +
 .../org/apache/myfaces/tobago/el/UserWrapper.java  |   122 +
 .../event/AbstractResetInputActionListener.java    |    46 +
 .../tobago/event/CollapsibleActionListener.java    |    87 +
 .../myfaces/tobago/event/FacesEventWrapper.java    |    72 +
 .../event/MethodExpressionStateChangeListener.java |    67 +
 .../event/MethodExpressionTabChangeListener.java   |    67 +
 .../MethodExpressionTreeExpansionListener.java     |    71 +
 .../MethodExpressionTreeSelectedListener.java      |    70 +
 .../myfaces/tobago/event/PageActionEvent.java      |    58 +
 .../tobago/event/ResetFormActionListener.java      |    40 +
 .../tobago/event/ResetInputActionListener.java     |    77 +
 .../apache/myfaces/tobago/event/SheetAction.java   |    70 +
 .../tobago/event/SheetStateChangeEvent.java        |    46 +
 .../tobago/event/SheetStateChangeListener.java     |    27 +
 .../tobago/event/SheetStateChangeSource.java       |    41 +
 .../tobago/event/SheetStateChangeSource2.java      |    29 +
 .../myfaces/tobago/event/SortActionEvent.java      |    49 +
 .../myfaces/tobago/event/SortActionSource.java     |    37 +
 .../myfaces/tobago/event/SortActionSource2.java    |    30 +
 .../myfaces/tobago/event/TabChangeEvent.java       |   100 +
 .../myfaces/tobago/event/TabChangeListener.java    |    28 +
 .../myfaces/tobago/event/TabChangeSource.java      |    41 +
 .../myfaces/tobago/event/TabChangeSource2.java     |    30 +
 .../myfaces/tobago/event/TreeExpansionEvent.java   |    74 +
 .../tobago/event/TreeExpansionListener.java        |    27 +
 .../myfaces/tobago/event/TreeSelectedEvent.java    |    69 +
 .../myfaces/tobago/event/TreeSelectedListener.java |    27 +
 .../ValueExpressionResetInputActionListener.java   |    95 +
 .../ValueExpressionSheetStateChangeListener.java   |   107 +
 .../event/ValueExpressionTabChangeListener.java    |   107 +
 .../myfaces/tobago/facelets/AttributeHandler.java  |   356 +
 .../myfaces/tobago/facelets/ContentTypeRule.java   |    57 +
 .../myfaces/tobago/facelets/ConverterHandler.java  |    81 +
 .../tobago/facelets/DataAttributeHandler.java      |    63 +
 .../tobago/facelets/DefaultResourceResolver.java   |    50 +
 .../myfaces/tobago/facelets/EventHandler.java      |   254 +
 .../facelets/FixCharacterEncodingFilter.java       |    59 +
 .../MetaInfResourcesClasspathResourceResolver.java |    73 +
 .../facelets/ResetInputActionListenerHandler.java  |    68 +
 .../apache/myfaces/tobago/facelets/Resource.java   |   144 +
 .../myfaces/tobago/facelets/ScriptHandler.java     |    40 +
 .../myfaces/tobago/facelets/SegmentLayoutRule.java |   114 +
 .../facelets/SheetStateChangeSourceRule.java       |    62 +
 .../tobago/facelets/SortActionSourceRule.java      |    64 +
 .../myfaces/tobago/facelets/SpanHandler.java       |    68 +
 .../myfaces/tobago/facelets/SuggestMethodRule.java |    83 +
 .../tobago/facelets/SupportsMarkupRule.java        |    67 +
 .../tobago/facelets/TabChangeListenerHandler.java  |    94 +
 .../tobago/facelets/TabChangeSourceRule.java       |    59 +
 .../tobago/facelets/TagMethodExpression.java       |   123 +
 .../tobago/facelets/TobagoComponentHandler.java    |   108 +
 .../tobago/facelets/TobagoValidateHandler.java     |    43 +
 .../tobago/internal/ajax/AjaxInternalUtils.java    |    80 +
 .../internal/ajax/AjaxNavigationListener.java      |    77 +
 .../tobago/internal/ajax/AjaxNavigationState.java  |   206 +
 .../behavior/AttachedListStateWrapper.java         |    43 +
 .../internal/behavior/AttachedStateWrapper.java    |    52 +
 .../tobago/internal/behavior/DeltaStateHelper.java |   763 ++
 .../tobago/internal/behavior/EventBehavior.java    |   315 +
 .../tobago/internal/component/AbstractUIBar.java   |    25 +
 .../tobago/internal/component/AbstractUIBox.java   |    25 +
 .../internal/component/AbstractUIButton.java       |    24 +
 .../internal/component/AbstractUIButtons.java      |    23 +
 .../component/AbstractUICollapsiblePanel.java      |   100 +
 .../internal/component/AbstractUIColumn.java       |    27 +
 .../internal/component/AbstractUIColumnBase.java   |    32 +
 .../internal/component/AbstractUIColumnNode.java   |    28 +
 .../component/AbstractUIColumnSelector.java        |    35 +
 .../internal/component/AbstractUICommand.java      |    74 +
 .../internal/component/AbstractUICommandBase.java  |   144 +
 .../tobago/internal/component/AbstractUIData.java  |   314 +
 .../tobago/internal/component/AbstractUIDate.java  |    49 +
 .../tobago/internal/component/AbstractUIEvent.java |    28 +
 .../internal/component/AbstractUIFigure.java       |    25 +
 .../tobago/internal/component/AbstractUIFile.java  |    80 +
 .../internal/component/AbstractUIFlexLayout.java   |    32 +
 .../internal/component/AbstractUIFlowLayout.java   |    27 +
 .../tobago/internal/component/AbstractUIForm.java  |    27 +
 .../internal/component/AbstractUIFormBase.java     |   100 +
 .../internal/component/AbstractUIGridLayout.java   |   124 +
 .../internal/component/AbstractUIHidden.java       |    27 +
 .../tobago/internal/component/AbstractUIImage.java |    31 +
 .../tobago/internal/component/AbstractUIIn.java    |    24 +
 .../tobago/internal/component/AbstractUIInput.java |    62 +
 .../tobago/internal/component/AbstractUILabel.java |    42 +
 .../internal/component/AbstractUILayoutBase.java   |    29 +
 .../tobago/internal/component/AbstractUILink.java  |    29 +
 .../tobago/internal/component/AbstractUILinks.java |    23 +
 .../internal/component/AbstractUIMessages.java     |   126 +
 .../internal/component/AbstractUIObject.java       |    27 +
 .../internal/component/AbstractUIOperation.java    |    29 +
 .../tobago/internal/component/AbstractUIOut.java   |    28 +
 .../tobago/internal/component/AbstractUIPage.java  |   160 +
 .../tobago/internal/component/AbstractUIPanel.java |    25 +
 .../internal/component/AbstractUIPanelBase.java    |    65 +
 .../tobago/internal/component/AbstractUIPopup.java |    26 +
 .../internal/component/AbstractUIProgress.java     |    87 +
 .../tobago/internal/component/AbstractUIRow.java   |    25 +
 .../internal/component/AbstractUIScript.java       |    28 +
 .../internal/component/AbstractUISection.java      |    76 +
 .../component/AbstractUISegmentLayout.java         |    63 +
 .../component/AbstractUISelectBooleanCheckbox.java |    83 +
 .../internal/component/AbstractUISelectItem.java   |    59 +
 .../component/AbstractUISelectManyBase.java        |    42 +
 .../component/AbstractUISelectManyCheckbox.java    |    23 +
 .../component/AbstractUISelectManyListbox.java     |    38 +
 .../component/AbstractUISelectManyShuttle.java     |    50 +
 .../component/AbstractUISelectOneBase.java         |    56 +
 .../component/AbstractUISelectOneChoice.java       |    38 +
 .../component/AbstractUISelectOneListbox.java      |    38 +
 .../component/AbstractUISelectOneRadio.java        |    23 +
 .../internal/component/AbstractUISeparator.java    |    27 +
 .../tobago/internal/component/AbstractUISheet.java |   570 +
 .../internal/component/AbstractUISuggest.java      |    89 +
 .../tobago/internal/component/AbstractUITab.java   |    28 +
 .../internal/component/AbstractUITabGroup.java     |   277 +
 .../internal/component/AbstractUITextarea.java     |    28 +
 .../tobago/internal/component/AbstractUITree.java  |   234 +
 .../internal/component/AbstractUITreeCommand.java  |    23 +
 .../internal/component/AbstractUITreeIndent.java   |    27 +
 .../internal/component/AbstractUITreeListbox.java  |    28 +
 .../internal/component/AbstractUITreeMenu.java     |    30 +
 .../internal/component/AbstractUITreeNode.java     |    28 +
 .../internal/component/AbstractUITreeNodeBase.java |    73 +
 .../internal/component/AbstractUITreeSelect.java   |    46 +
 .../internal/config/ContentSecurityPolicy.java     |   102 +
 .../tobago/internal/config/RendererConfig.java     |    74 +
 .../tobago/internal/config/RenderersConfig.java    |    30 +
 .../internal/config/RenderersConfigImpl.java       |   101 +
 .../internal/config/TobagoConfigBuilder.java       |   120 +
 .../config/TobagoConfigEntityResolver.java         |    71 +
 .../internal/config/TobagoConfigFragment.java      |   195 +
 .../tobago/internal/config/TobagoConfigImpl.java   |   408 +
 .../tobago/internal/config/TobagoConfigParser.java |   452 +
 .../tobago/internal/config/TobagoConfigSorter.java |   332 +
 .../internal/config/TobagoConfigVersion.java       |    69 +
 .../tobago/internal/context/DateTimeI18n.java      |   106 +
 .../myfaces/tobago/internal/layout/BankHead.java   |    59 +
 .../myfaces/tobago/internal/layout/Cell.java       |    51 +
 .../myfaces/tobago/internal/layout/Grid.java       |   447 +
 .../tobago/internal/layout/LayoutUtils.java        |   102 +
 .../myfaces/tobago/internal/layout/MathUtils.java  |   109 +
 .../myfaces/tobago/internal/layout/OriginCell.java |    71 +
 .../myfaces/tobago/internal/layout/SpanCell.java   |    65 +
 .../myfaces/tobago/internal/package-info.java      |    28 +
 .../tobago/internal/renderkit/Collapse.java        |    43 +
 .../myfaces/tobago/internal/renderkit/Command.java |   261 +
 .../tobago/internal/renderkit/CommandMap.java      |   134 +
 .../internal/renderkit/renderer/BarRenderer.java   |   145 +
 .../internal/renderkit/renderer/BoxRenderer.java   |   104 +
 .../renderkit/renderer/ButtonRenderer.java         |    43 +
 .../renderkit/renderer/ButtonsRenderer.java        |    62 +
 .../renderkit/renderer/CalendarRenderer.java       |    45 +
 .../renderkit/renderer/ColumnRenderer.java         |    52 +
 .../renderkit/renderer/ColumnSelectorRenderer.java |    25 +
 .../renderkit/renderer/CommandRendererBase.java    |   207 +
 .../internal/renderkit/renderer/DateRenderer.java  |   113 +
 .../renderer/DecodingCommandRendererBase.java      |    62 +
 .../renderer/DecodingInputRendererBase.java        |    77 +
 .../internal/renderkit/renderer/EventRenderer.java |    23 +
 .../renderkit/renderer/FigureRenderer.java         |    78 +
 .../internal/renderkit/renderer/FileRenderer.java  |   205 +
 .../renderkit/renderer/FlexLayoutRenderer.java     |    96 +
 .../renderkit/renderer/FlowLayoutRenderer.java     |    70 +
 .../renderkit/renderer/FooterRenderer.java         |    57 +
 .../internal/renderkit/renderer/FormRenderer.java  |    55 +
 .../renderkit/renderer/GridLayoutRenderer.java     |   153 +
 .../renderkit/renderer/HeaderRenderer.java         |    61 +
 .../renderkit/renderer/HiddenRenderer.java         |    68 +
 .../internal/renderkit/renderer/ImageRenderer.java |    76 +
 .../internal/renderkit/renderer/InRenderer.java    |   178 +
 .../renderer/LabelLayoutRendererBase.java          |   219 +
 .../internal/renderkit/renderer/LabelRenderer.java |   108 +
 .../internal/renderkit/renderer/LinkRenderer.java  |    23 +
 .../internal/renderkit/renderer/LinksRenderer.java |    75 +
 .../renderkit/renderer/MessagesRenderer.java       |   177 +
 .../renderkit/renderer/ObjectRenderer.java         |    66 +
 .../renderkit/renderer/OperationRenderer.java      |    27 +
 .../internal/renderkit/renderer/OutRenderer.java   |    97 +
 .../internal/renderkit/renderer/PageRenderer.java  |   408 +
 .../internal/renderkit/renderer/PanelRenderer.java |    83 +
 .../renderkit/renderer/PanelRendererBase.java      |    79 +
 .../internal/renderkit/renderer/PopupRenderer.java |    86 +
 .../renderkit/renderer/ProgressRenderer.java       |    76 +
 .../internal/renderkit/renderer/RowRenderer.java   |    45 +
 .../renderkit/renderer/ScriptRenderer.java         |    44 +
 .../renderkit/renderer/SectionRenderer.java        |   106 +
 .../renderkit/renderer/SegmentLayoutRenderer.java  |   125 +
 .../renderer/SelectBooleanCheckboxRenderer.java    |   127 +
 .../renderkit/renderer/SelectItemsRenderer.java    |    27 +
 .../renderer/SelectManyCheckboxRenderer.java       |   119 +
 .../renderer/SelectManyListboxRenderer.java        |    87 +
 .../renderkit/renderer/SelectManyRendererBase.java |   810 ++
 .../renderer/SelectManyShuttleRenderer.java        |   154 +
 .../renderer/SelectOneChoiceRenderer.java          |    81 +
 .../renderer/SelectOneListboxRenderer.java         |    85 +
 .../renderkit/renderer/SelectOneRadioRenderer.java |   132 +
 .../renderkit/renderer/SelectOneRendererBase.java  |    53 +
 .../renderer/SelectReferenceRenderer.java          |    51 +
 .../renderkit/renderer/SeparatorRenderer.java      |    67 +
 .../renderer/SheetPageCommandRenderer.java         |    89 +
 .../internal/renderkit/renderer/SheetRenderer.java |  1168 ++
 .../internal/renderkit/renderer/StyleRenderer.java |    72 +
 .../renderkit/renderer/SubviewRenderer.java        |    50 +
 .../renderkit/renderer/SuggestRenderer.java        |   163 +
 .../renderkit/renderer/TabGroupRenderer.java       |   338 +
 .../internal/renderkit/renderer/TabRenderer.java   |    30 +
 .../renderkit/renderer/TextareaRenderer.java       |   132 +
 .../renderer/TobagoClientBehaviorRenderer.java     |   185 +
 .../renderkit/renderer/TreeCommandRenderer.java    |    23 +
 .../renderkit/renderer/TreeIconRenderer.java       |    88 +
 .../renderkit/renderer/TreeIndentRenderer.java     |   172 +
 .../renderkit/renderer/TreeLabelRenderer.java      |    71 +
 .../renderkit/renderer/TreeListboxRenderer.java    |   199 +
 .../renderkit/renderer/TreeMenuRenderer.java       |    23 +
 .../renderkit/renderer/TreeNodeRenderer.java       |   222 +
 .../internal/renderkit/renderer/TreeRenderer.java  |   159 +
 .../renderkit/renderer/TreeSelectRenderer.java     |   158 +
 .../renderkit/renderer/VerbatimRenderer.java       |    50 +
 .../taglib/component/AttributeTagDeclaration.java  |    67 +
 .../taglib/component/BarTagDeclaration.java        |    48 +
 .../taglib/component/BoxTagDeclaration.java        |    56 +
 .../taglib/component/ButtonTagDeclaration.java     |    88 +
 .../taglib/component/ButtonsTagDeclaration.java    |    45 +
 .../taglib/component/CalendarTagDeclaration.java   |    54 +
 .../taglib/component/ColumnNodeTagDeclaration.java |    65 +
 .../component/ColumnSelectorTagDeclaration.java    |    44 +
 .../taglib/component/ColumnTagDeclaration.java     |    80 +
 .../taglib/component/ConverterTagDeclaration.java  |    48 +
 .../component/DataAttributeTagDeclaration.java     |    52 +
 .../taglib/component/DateTagDeclaration.java       |    83 +
 .../taglib/component/EventTagDeclaration.java      |    62 +
 .../taglib/component/FigureTagDeclaration.java     |    51 +
 .../taglib/component/FileTagDeclaration.java       |    94 +
 .../taglib/component/FlexLayoutTagDeclaration.java |    77 +
 .../taglib/component/FlowLayoutTagDeclaration.java |    62 +
 .../taglib/component/FooterTagDeclaration.java     |    45 +
 .../taglib/component/FormTagDeclaration.java       |    46 +
 .../taglib/component/GridLayoutTagDeclaration.java |   113 +
 .../taglib/component/HeaderTagDeclaration.java     |    45 +
 .../taglib/component/HiddenTagDeclaration.java     |    54 +
 .../taglib/component/ImageTagDeclaration.java      |    58 +
 .../taglib/component/InTagDeclaration.java         |    95 +
 .../taglib/component/LabelTagDeclaration.java      |    57 +
 .../taglib/component/LinkTagDeclaration.java       |    83 +
 .../taglib/component/LinksTagDeclaration.java      |    42 +
 .../taglib/component/MessagesTagDeclaration.java   |   115 +
 .../taglib/component/ObjectTagDeclaration.java     |    61 +
 .../taglib/component/OperationTagDeclaration.java  |    59 +
 .../taglib/component/OutTagDeclaration.java        |    72 +
 .../taglib/component/PageTagDeclaration.java       |    91 +
 .../taglib/component/PanelTagDeclaration.java      |    67 +
 .../taglib/component/PopupTagDeclaration.java      |    60 +
 .../taglib/component/ProgressTagDeclaration.java   |    72 +
 .../taglib/component/ReloadTagDeclaration.java     |    67 +
 .../ResetInputActionListenerTagDeclaration.java    |    43 +
 .../taglib/component/RowTagDeclaration.java        |    49 +
 .../taglib/component/ScriptTagDeclaration.java     |    54 +
 .../taglib/component/SectionTagDeclaration.java    |    52 +
 .../component/SegmentLayoutTagDeclaration.java     |    75 +
 .../SelectBooleanCheckboxTagDeclaration.java       |    81 +
 .../taglib/component/SelectItemTagDeclaration.java |    92 +
 .../component/SelectItemsTagDeclaration.java       |    92 +
 .../SelectManyCheckboxTagDeclaration.java          |    93 +
 .../component/SelectManyListboxTagDeclaration.java |    87 +
 .../component/SelectManyShuttleTagDeclaration.java |   103 +
 .../component/SelectOneChoiceTagDeclaration.java   |    92 +
 .../component/SelectOneListboxTagDeclaration.java  |    93 +
 .../component/SelectOneRadioTagDeclaration.java    |    94 +
 .../component/SelectReferenceTagDeclaration.java   |    57 +
 .../taglib/component/SeparatorTagDeclaration.java  |    48 +
 .../component/SheetPageCommandTagDeclaration.java  |    34 +
 .../taglib/component/SheetTagDeclaration.java      |   257 +
 .../taglib/component/SpanTagDeclaration.java       |    46 +
 .../taglib/component/StyleTagDeclaration.java      |   268 +
 .../taglib/component/SuggestTagDeclaration.java    |   165 +
 .../component/TabChangeListenerTagDeclaration.java |    50 +
 .../taglib/component/TabGroupTagDeclaration.java   |   115 +
 .../taglib/component/TabTagDeclaration.java        |    63 +
 .../taglib/component/TextareaTagDeclaration.java   |    86 +
 .../component/TreeCommandTagDeclaration.java       |    80 +
 .../taglib/component/TreeIconTagDeclaration.java   |    68 +
 .../taglib/component/TreeIndentTagDeclaration.java |    52 +
 .../taglib/component/TreeLabelTagDeclaration.java  |    54 +
 .../component/TreeListboxTagDeclaration.java       |    86 +
 .../taglib/component/TreeMenuTagDeclaration.java   |    69 +
 .../taglib/component/TreeNodeTagDeclaration.java   |    75 +
 .../taglib/component/TreeSelectTagDeclaration.java |    80 +
 .../taglib/component/TreeTagDeclaration.java       |    95 +
 .../component/ValidateFileItemTagDeclaration.java  |    45 +
 ...ValidateSubmittedValueLengthTagDeclaration.java |    45 +
 .../internal/taglib/component/package-info.java    |    33 +
 .../internal/taglib/declaration/HasAccessKey.java  |    33 +
 .../internal/taglib/declaration/HasAction.java     |    43 +
 .../taglib/declaration/HasActionListener.java      |    39 +
 .../tobago/internal/taglib/declaration/HasAlt.java |    32 +
 .../taglib/declaration/HasAutocomplete.java        |    30 +
 .../internal/taglib/declaration/HasBinding.java    |    33 +
 .../taglib/declaration/HasCollapsedMode.java       |    37 +
 .../taglib/declaration/HasColumnLayout.java        |    35 +
 .../taglib/declaration/HasConfirmation.java        |    32 +
 .../internal/taglib/declaration/HasConverter.java  |    41 +
 .../taglib/declaration/HasConverterMessage.java    |    34 +
 .../internal/taglib/declaration/HasFieldId.java    |    33 +
 .../tobago/internal/taglib/declaration/HasFor.java |    33 +
 .../tobago/internal/taglib/declaration/HasId.java  |    33 +
 .../declaration/HasIdBindingAndRendered.java       |    23 +
 .../internal/taglib/declaration/HasImage.java      |    32 +
 .../internal/taglib/declaration/HasItemLabel.java  |    32 +
 .../internal/taglib/declaration/HasLabel.java      |    32 +
 .../taglib/declaration/HasLabelLayout.java         |    38 +
 .../internal/taglib/declaration/HasLabelWidth.java |    35 +
 .../internal/taglib/declaration/HasLink.java       |    45 +
 .../taglib/declaration/HasPlaceholder.java         |    40 +
 .../taglib/declaration/HasRenderRange.java         |    32 +
 .../taglib/declaration/HasRequiredMessage.java     |    33 +
 .../declaration/HasRequiredMessageForSelect.java   |    33 +
 .../internal/taglib/declaration/HasRowLayout.java  |    35 +
 .../internal/taglib/declaration/HasSanitize.java   |    44 +
 .../internal/taglib/declaration/HasSize.java       |    33 +
 .../internal/taglib/declaration/HasSpacing.java    |    44 +
 .../internal/taglib/declaration/HasState.java      |    36 +
 .../taglib/declaration/HasStateBinding.java        |    28 +
 .../declaration/HasTabChangeListenerType.java      |    33 +
 .../internal/taglib/declaration/HasTabIndex.java   |    40 +
 .../internal/taglib/declaration/HasTarget.java     |    33 +
 .../tobago/internal/taglib/declaration/HasTip.java |    32 +
 .../internal/taglib/declaration/HasValidator.java  |    38 +
 .../taglib/declaration/HasValidatorMessage.java    |    33 +
 .../internal/taglib/declaration/HasValue.java      |    33 +
 .../taglib/declaration/HasValueChangeListener.java |    39 +
 .../tobago/internal/taglib/declaration/HasVar.java |    37 +
 .../internal/taglib/declaration/IsCollapsed.java   |    33 +
 .../taglib/declaration/IsDefaultCommand.java       |    33 +
 .../internal/taglib/declaration/IsDisabled.java    |    32 +
 .../taglib/declaration/IsDisabledBySecurity.java   |    34 +
 .../internal/taglib/declaration/IsDraggable.java   |    44 +
 .../internal/taglib/declaration/IsFixed.java       |    33 +
 .../internal/taglib/declaration/IsFocus.java       |    32 +
 .../taglib/declaration/IsImmediateCommand.java     |    36 +
 .../internal/taglib/declaration/IsInline.java      |    32 +
 .../internal/taglib/declaration/IsMultiple.java    |    30 +
 .../tobago/internal/taglib/declaration/IsOmit.java |    37 +
 .../internal/taglib/declaration/IsPassword.java    |    34 +
 .../internal/taglib/declaration/IsReadonly.java    |    32 +
 .../internal/taglib/declaration/IsRendered.java    |    35 +
 .../internal/taglib/declaration/IsRequired.java    |    34 +
 .../taglib/declaration/IsRequiredForSelect.java    |    34 +
 .../internal/taglib/declaration/IsShowRoot.java    |    36 +
 .../taglib/declaration/IsShowRootJunction.java     |    35 +
 .../internal/taglib/declaration/IsTransition.java  |    36 +
 .../internal/taglib/declaration/IsVisual.java      |    61 +
 .../tobago/internal/util/AccessKeyLogger.java      |    89 +
 .../myfaces/tobago/internal/util/ArrayUtils.java   |    34 +
 .../tobago/internal/util/AuthorizationHelper.java  |   228 +
 .../myfaces/tobago/internal/util/ContentType.java  |    61 +
 .../myfaces/tobago/internal/util/CookieUtils.java  |   120 +
 .../tobago/internal/util/DateFormatUtils.java      |   109 +
 .../myfaces/tobago/internal/util/Deprecation.java  |    51 +
 .../tobago/internal/util/FacesContextUtils.java    |    91 +
 .../tobago/internal/util/FastStringWriter.java     |    74 +
 .../tobago/internal/util/HtmlRendererUtils.java    |   272 +
 .../tobago/internal/util/HtmlWriterUtils.java      |   124 +
 .../tobago/internal/util/HttpPartWrapper.java      |   129 +
 .../myfaces/tobago/internal/util/IoUtils.java      |    39 +
 .../myfaces/tobago/internal/util/JQueryUtils.java  |    32 +
 .../internal/util/JavascriptWriterUtils.java       |   120 +
 .../myfaces/tobago/internal/util/JndiUtils.java    |    78 +
 .../myfaces/tobago/internal/util/JsonUtils.java    |   297 +
 .../tobago/internal/util/JsonWriterUtils.java      |   125 +
 .../tobago/internal/util/MimeTypeUtils.java        |   106 +
 .../myfaces/tobago/internal/util/NumberUtils.java  |    34 +
 .../myfaces/tobago/internal/util/ObjectUtils.java  |    32 +
 .../myfaces/tobago/internal/util/PartUtils.java    |   331 +
 .../myfaces/tobago/internal/util/RenderUtils.java  |   304 +
 .../tobago/internal/util/ResponseUtils.java        |   145 +
 .../tobago/internal/util/ResponseWriterBuffer.java |    82 +
 .../tobago/internal/util/SelectItemUtils.java      |   282 +
 .../myfaces/tobago/internal/util/StringUtils.java  |   581 +
 .../myfaces/tobago/internal/util/WriterUtils.java  |   211 +
 .../internal/webapp/DebugContentTypeFilter.java    |    64 +
 .../internal/webapp/DebugContentTypeResponse.java  |    71 +
 .../webapp/DebugResponseWriterWrapper.java         |   228 +
 .../tobago/internal/webapp/HtmlResponseWriter.java |   166 +
 .../tobago/internal/webapp/LoggingMdcFilter.java   |    78 +
 .../internal/webapp/TobagoResponseWriterBase.java  |   369 +
 .../webapp/TobagoResponseWriterWrapper.java        |   150 +
 .../tobago/internal/webapp/XmlResponseWriter.java  |    94 +
 .../apache/myfaces/tobago/layout/AlignItems.java   |    36 +
 .../myfaces/tobago/layout/AutoLayoutToken.java     |    29 +
 .../myfaces/tobago/layout/ColumnPartition.java     |   131 +
 .../org/apache/myfaces/tobago/layout/Display.java  |    48 +
 .../myfaces/tobago/layout/HideLayoutToken.java     |    26 +
 .../myfaces/tobago/layout/JustifyContent.java      |    36 +
 .../apache/myfaces/tobago/layout/LayoutToken.java  |    23 +
 .../apache/myfaces/tobago/layout/LayoutTokens.java |   146 +
 .../org/apache/myfaces/tobago/layout/Measure.java  |   188 +
 .../myfaces/tobago/layout/MeasureEditor.java       |    34 +
 .../myfaces/tobago/layout/MeasureLayoutToken.java  |    66 +
 .../myfaces/tobago/layout/MinimumLayoutToken.java  |    26 +
 .../org/apache/myfaces/tobago/layout/OrderBy.java  |    31 +
 .../apache/myfaces/tobago/layout/Orientation.java  |    40 +
 .../org/apache/myfaces/tobago/layout/Overflow.java |    43 +
 .../apache/myfaces/tobago/layout/PixelMeasure.java |    78 +
 .../org/apache/myfaces/tobago/layout/Position.java |    48 +
 .../myfaces/tobago/layout/RelativeLayoutToken.java |    63 +
 .../apache/myfaces/tobago/layout/ShowPosition.java |    33 +
 .../apache/myfaces/tobago/layout/TextAlign.java    |    69 +
 .../tobago/lifecycle/SecretPhaseListener.java      |    58 +
 .../tobago/model/AutoSuggestExtensionItem.java     |    42 +
 .../myfaces/tobago/model/AutoSuggestItem.java      |    55 +
 .../myfaces/tobago/model/AutoSuggestItems.java     |    56 +
 .../apache/myfaces/tobago/model/CalendarModel.java |    97 +
 .../apache/myfaces/tobago/model/CollapseMode.java  |    31 +
 .../org/apache/myfaces/tobago/model/DateModel.java |    78 +
 .../apache/myfaces/tobago/model/ExpandedState.java |   251 +
 .../myfaces/tobago/model/ScrollPosition.java       |    74 +
 .../myfaces/tobago/model/ScrollPositionState.java  |    25 +
 .../apache/myfaces/tobago/model/SelectItem.java    |   130 +
 .../apache/myfaces/tobago/model/Selectable.java    |   148 +
 .../apache/myfaces/tobago/model/SelectedState.java |    81 +
 .../apache/myfaces/tobago/model/SheetState.java    |   184 +
 .../tobago/model/SortableByApplication.java        |    26 +
 .../apache/myfaces/tobago/model/SuggestFilter.java |    42 +
 .../apache/myfaces/tobago/model/SwitchType.java    |    34 +
 .../apache/myfaces/tobago/model/TreeDataModel.java |    71 +
 .../myfaces/tobago/model/TreeNodeDataModel.java    |   305 +
 .../org/apache/myfaces/tobago/model/TreePath.java  |   132 +
 .../org/apache/myfaces/tobago/model/TreeState.java |    57 +
 .../myfaces/tobago/portlet/PortletUtils.java       |    55 +
 .../myfaces/tobago/renderkit/GenericRenderer.java  |    26 +
 .../tobago/renderkit/LabelWithAccessKey.java       |    96 +
 .../myfaces/tobago/renderkit/RendererBase.java     |    85 +
 .../myfaces/tobago/renderkit/TobagoRenderKit.java  |   181 +
 .../tobago/renderkit/css/BootstrapClass.java       |   281 +
 .../css/BootstrapDateTimePickerClass.java          |    42 +
 .../myfaces/tobago/renderkit/css/Classes.java      |   155 +
 .../myfaces/tobago/renderkit/css/CssItem.java      |    30 +
 .../myfaces/tobago/renderkit/css/CustomClass.java  |    87 +
 .../tobago/renderkit/css/CustomClassEditor.java    |    38 +
 .../renderkit/css/FontAwesomeIconEncoder.java      |   101 +
 .../myfaces/tobago/renderkit/css/IconEncoder.java  |    30 +
 .../apache/myfaces/tobago/renderkit/css/Icons.java |    42 +
 .../apache/myfaces/tobago/renderkit/css/Style.java |   679 ++
 .../myfaces/tobago/renderkit/css/TobagoClass.java  |   148 +
 .../myfaces/tobago/renderkit/html/Arias.java       |    58 +
 .../tobago/renderkit/html/DataAttributes.java      |   224 +
 .../tobago/renderkit/html/HtmlAttributes.java      |   141 +
 .../tobago/renderkit/html/HtmlButtonTypes.java     |    38 +
 .../tobago/renderkit/html/HtmlElements.java        |   186 +
 .../tobago/renderkit/html/HtmlInputTypes.java      |    45 +
 .../tobago/renderkit/html/HtmlRoleValues.java      |    44 +
 .../myfaces/tobago/renderkit/html/HtmlTypes.java   |    25 +
 .../renderkit/html/MarkupLanguageAttributes.java   |    25 +
 .../tobago/sanitizer/IgnoringSanitizer.java        |    48 +
 .../myfaces/tobago/sanitizer/JsoupSanitizer.java   |    95 +
 .../myfaces/tobago/sanitizer/SanitizeMode.java     |    28 +
 .../apache/myfaces/tobago/sanitizer/Sanitizer.java |    29 +
 .../tobago/servlet/NonFacesRequestServlet.java     |    98 +
 .../myfaces/tobago/servlet/ResourceServlet.java    |   170 +
 .../org/apache/myfaces/tobago/util/AjaxUtils.java  |    77 +
 .../apache/myfaces/tobago/util/BeanComparator.java |    95 +
 .../apache/myfaces/tobago/util/ComparatorBase.java |   126 +
 .../apache/myfaces/tobago/util/ComponentUtils.java |   859 ++
 .../myfaces/tobago/util/ContextCallback.java       |    28 +
 .../myfaces/tobago/util/CreateComponentUtils.java  |    27 +
 .../myfaces/tobago/util/DebugActionListener.java   |    47 +
 .../tobago/util/DebugNavigationHandler.java        |    58 +
 .../myfaces/tobago/util/DebugPhaseListener.java    |   157 +
 .../org/apache/myfaces/tobago/util/DebugUtils.java |   112 +
 .../apache/myfaces/tobago/util/FacesELUtils.java   |    45 +
 .../apache/myfaces/tobago/util/FacesVersion.java   |   122 +
 .../apache/myfaces/tobago/util/LocaleUtils.java    |    97 +
 .../apache/myfaces/tobago/util/MessageFormat.java  |    76 +
 .../apache/myfaces/tobago/util/MessageUtils.java   |   148 +
 .../tobago/util/ValueBindingComparator.java        |   131 +
 .../tobago/util/ValueExpressionComparator.java     |   128 +
 .../myfaces/tobago/util/VariableResolverUtils.java |    49 +
 .../org/apache/myfaces/tobago/util/XmlUtils.java   |   169 +
 .../validator/ClearValidatorsActionListener.java   |    84 +
 .../tobago/validator/FileItemValidator.java        |   132 +
 .../validator/SubmittedValueLengthValidator.java   |   144 +
 .../tobago/webapp/LogoutActionListener.java        |    64 +
 .../org/apache/myfaces/tobago/webapp/Secret.java   |   126 +
 .../tobago/webapp/SecretSessionListener.java       |    40 +
 .../tobago/webapp/TobagoResponseWriter.java        |   317 +
 .../webapp/TobagoServletContextListener.java       |    86 +
 .../src/main/resources/META-INF/web-fragment.xml   |    43 +
 .../myfaces/tobago/config/tobago-config-1.0.29.dtd |    50 +
 .../myfaces/tobago/config/tobago-config-1.0.30.dtd |    59 +
 .../myfaces/tobago/config/tobago-config-1.0.34.dtd |    63 +
 .../myfaces/tobago/config/tobago-config-1.5.xsd    |   152 +
 .../myfaces/tobago/config/tobago-config-1.6.xsd    |   168 +
 .../myfaces/tobago/config/tobago-config-2.0.6.xsd  |   215 +
 .../myfaces/tobago/config/tobago-config-2.0.xsd    |   201 +
 .../myfaces/tobago/config/tobago-config-3.0.xsd    |   206 +
 .../myfaces/tobago/config/tobago-config_1_0.dtd    |    62 +
 .../myfaces/tobago/context/TobagoMessage.xml       |    43 +
 .../myfaces/tobago/context/TobagoMessage_de.xml    |    47 +
 .../myfaces/tobago/context/TobagoMessage_es.xml    |    44 +
 .../myfaces/tobago/context/TobagoResource.xml      |    91 +
 .../myfaces/tobago/context/TobagoResource_de.xml   |    93 +
 .../myfaces/tobago/context/TobagoResource_es.xml   |    92 +
 .../tobago/component/ClientBehaviorsUnitTest.java  |    32 +
 .../myfaces/tobago/component/FacetsUnitTest.java   |    32 +
 ...OverwritingOfGeneratedUIComponentsUnitTest.java |   155 +
 .../tobago/component/RendererTypesUnitTest.java    |    43 +
 .../myfaces/tobago/component/SorterUnitTest.java   |    57 +
 .../tobago/component/UIMessagesUnitTest.java       |   134 +
 .../myfaces/tobago/component/UISheetUnitTest.java  |   404 +
 .../myfaces/tobago/context/MarkupUnitTest.java     |   148 +
 .../tobago/context/ResourceUtilsUnitTest.java      |    38 +
 .../myfaces/tobago/context/UserAgentUnitTest.java  |   190 +
 .../tobago/convert/DurationConverterUnitTest.java  |    88 +
 .../internal/config/AbstractTobagoTestBase.java    |   116 +
 .../config/TobagoConfigMergingUnitTest.java        |   135 +
 .../config/TobagoConfigParserUnitTest.java         |   190 +
 .../config/TobagoConfigSorterUnitTest.java         |   197 +
 .../internal/context/ThemeParserUnitTest.java      |   102 +
 .../internal/renderkit/CommandUnitTest.java        |    71 +
 .../tobago/internal/layout/GridUnitTest.java       |   233 +
 .../tobago/internal/layout/MathUtilsUnitTest.java  |    97 +
 .../internal/mock/faces/MockRenderersConfig.java   |    41 +
 .../tobago/internal/mock/faces/MockTheme.java      |    97 +
 .../internal/mock/servlet/MockHttpSession.java     |   116 +
 .../mock/servlet/MockServletInputStream.java       |    43 +
 .../tobago/internal/util/JsonUtilsUnitTest.java    |   157 +
 .../internal/util/MimeTypeUtilsUnitTest.java       |    87 +
 .../tobago/internal/util/PartUtilsUnitTest.java    |   108 +
 .../tobago/internal/util/StringUtilsUnitTest.java  |    54 +
 .../myfaces/tobago/layout/AlignItemsUnitTest.java  |    32 +
 .../tobago/layout/ColumnPartitionUnitTest.java     |    59 +
 .../myfaces/tobago/layout/DisplayUnitTest.java     |    31 +
 .../tobago/layout/JustifyContentUnitTest.java      |    31 +
 .../tobago/layout/LayoutTokensUnitTest.java        |    48 +
 .../myfaces/tobago/layout/MeasureUnitTest.java     |    55 +
 .../myfaces/tobago/layout/OrderByUnitTest.java     |    31 +
 .../myfaces/tobago/layout/OrientationUnitTest.java |    31 +
 .../myfaces/tobago/layout/OverflowUnitTest.java    |    31 +
 .../myfaces/tobago/layout/PositionUnitTest.java    |    31 +
 .../tobago/layout/ShowPositionUnitTest.java        |    31 +
 .../myfaces/tobago/layout/TextAlignUnitTest.java   |    31 +
 .../myfaces/tobago/model/CollapseModeUnitTest.java |    31 +
 .../tobago/model/ExpandedStateUnitTest.java        |   339 +
 .../myfaces/tobago/model/SelectableUnitTest.java   |    31 +
 .../tobago/model/SuggestFilterUnitTest.java        |    33 +
 .../myfaces/tobago/model/SwitchTypeUnitTest.java   |    31 +
 .../myfaces/tobago/model/TreePathUnitTest.java     |   110 +
 .../renderkit/LabelWithAccessKeyUnitTest.java      |   124 +
 .../tobago/renderkit/css/ClassesUnitTest.java      |   122 +
 .../tobago/renderkit/css/CustomClassUnitTest.java  |    43 +
 .../tobago/renderkit/css/StyleUnitTest.java        |    99 +
 .../tobago/renderkit/css/TobagoClassUnitTest.java  |    62 +
 .../tobago/renderkit/html/AriasUnitTest.java       |    43 +
 .../renderkit/html/DataAttributesUnitTest.java     |    46 +
 .../renderkit/html/HtmlElementsUnitTest.java       |    58 +
 .../tobago/sanitizer/SanitizeModeUnitTest.java     |    31 +
 .../tobago/util/ComponentUtilsUnitTest.java        |    55 +
 .../apache/myfaces/tobago/util/EnumUnitTest.java   |    62 +
 .../tobago/util/HtmlWriterUtilsUnitTest.java       |   122 +
 .../tobago/util/JavascriptWriterUtilsTest.java     |    58 +
 .../myfaces/tobago/util/LocaleUtilsUnitTest.java   |    60 +
 .../myfaces/tobago/util/RangeParserUnitTest.java   |    60 +
 .../webapp/TobagoResponseWriterUnitTest.java       |   151 +
 .../src/test/resources/logback-test.xml            |    36 +
 .../src/test/resources/theme-config.xml            |    42 +
 .../src/test/resources/theme-config2.xml           |    37 +
 .../src/test/resources/theme-config3.xml           |    33 +
 .../src/test/resources/theme-config4.xml           |    33 +
 .../src/test/resources/tobago-config-1.0.30.xml    |    30 +
 .../src/test/resources/tobago-config-1.5.xml       |    44 +
 .../src/test/resources/tobago-config-2.0.xml       |   102 +
 .../test/resources/tobago-config-fail-1.0.30.xml   |    27 +
 .../src/test/resources/tobago-config-fail-1.5.xml  |    30 +
 .../src/test/resources/tobago-config-fail-2.0.xml  |    29 +
 .../tobago-config-fail-unknown-version.xml         |    26 +
 .../resources/tobago-config-for-unit-tests.xml     |    33 +
 .../src/test/resources/tobago-config-merge-0.xml   |    34 +
 .../src/test/resources/tobago-config-merge-1.xml   |    53 +
 .../src/test/resources/tobago-config-merge-2.xml   |    43 +
 .../test/resources/tobago-config-untidy-2.0.xml    |   186 +
 .../src/test/resources/web-jsptaglibrary_1_2.dtd   |   108 +
 tobago-3.0.x/tobago-example/pom.xml                |   462 +
 .../src/test/jetty/override-mojarra-web.xml        |    35 +
 .../src/test/jetty/override-myfaces-web.xml        |    35 +
 .../src/test/resources/jettykeystore               |   Bin 0 -> 1286 bytes
 .../tobago-example-addressbook/pom.xml             |   402 +
 .../src/main/appended-resources/META-INF/LICENSE   |     4 +
 .../src/main/appended-resources/META-INF/NOTICE    |     2 +
 .../tobago/example/addressbook/Address.java        |   327 +
 .../tobago/example/addressbook/AddressDao.java     |    35 +
 .../DerbyShutdownServletContextListener.java       |    50 +
 .../tobago/example/addressbook/EmailAddress.java   |    75 +
 .../example/addressbook/InMemoryAddressDao.java    |    91 +
 .../tobago/example/addressbook/JpaAddressDao.java  |   102 +
 .../tobago/example/addressbook/KillSession.java    |    50 +
 .../example/addressbook/OpenJpaLoadTimeWeaver.java |    70 +
 .../tobago/example/addressbook/Picture.java        |    67 +
 .../example/addressbook/web/AdminController.java   |    75 +
 .../tobago/example/addressbook/web/Controller.java |   433 +
 .../tobago/example/addressbook/web/Countries.java  |    44 +
 .../addressbook/web/EmailAddressConverter.java     |    55 +
 .../addressbook/web/EmailAddressValidator.java     |    64 +
 .../example/addressbook/web/LocaleConverter.java   |    63 +
 .../example/addressbook/web/MessageUtils.java      |    61 +
 .../example/addressbook/web/PictureServlet.java    |    63 +
 .../addressbook/web/RandomAddressGenerator.java    |    75 +
 .../addressbook/web/SelectItemComparator.java      |    34 +
 .../addressbook/web/StartupPhaseListener.java      |    88 +
 .../src/main/resources/META-INF/persistence.xml    |    39 +
 .../src/main/resources/logback.xml                 |    36 +
 .../src/main/webapp/META-INF/context.xml           |    26 +
 .../src/main/webapp/WEB-INF/beans.xml              |    36 +
 .../src/main/webapp/WEB-INF/faces-config.xml       |    67 +
 .../src/main/webapp/WEB-INF/ibm-web-bnd.xmi        |    27 +
 .../src/main/webapp/WEB-INF/ibm-web-ext.xml        |    30 +
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    45 +
 .../src/main/webapp/WEB-INF/web.xml                |   132 +
 .../html/scarborough/standard/style/tobago.css     |    29 +
 .../html/speyside/standard/style/tobago.css        |    29 +
 .../standard/image/addressbook/icon/flag-de.png    |   Bin 0 -> 545 bytes
 .../standard/image/addressbook/icon/flag-gb.png    |   Bin 0 -> 699 bytes
 .../standard/image/addressbook/icon/flag-us.png    |   Bin 0 -> 609 bytes
 .../standard/standard/image/empty-portrait.png     |   Bin 0 -> 3269 bytes
 .../standard/standard/image/empty-portrait_de.png  |   Bin 0 -> 2860 bytes
 .../categories/preferences-systemDisabled.png      |   Bin 0 -> 521 bytes
 .../categories/preferences-systemDisabled.png      |   Bin 0 -> 1766 bytes
 .../mimetypes/x-office-address-bookDisabled.png    |   Bin 0 -> 1667 bytes
 .../address-book-splash-screen.png                 |   Bin 0 -> 10989 bytes
 .../standard/property/addressbook.properties.xml   |    59 +
 .../property/addressbook_de.properties.xml         |    60 +
 .../standard/property/error/messages.properties    |    27 +
 .../standard/standard/property/resource.properties |    98 +
 .../standard/property/resource_de.properties       |    84 +
 .../standard/property/resource_en_GB.properties    |    22 +
 .../standard/property/resource_en_US.properties    |    17 +
 .../src/main/webapp/addressbook/admin/admin.xhtml  |    40 +
 .../src/main/webapp/addressbook/admin/memory.xhtml |    40 +
 .../src/main/webapp/addressbook/editor.xhtml       |    79 +
 .../src/main/webapp/addressbook/layout/basic.xhtml |   156 +
 .../src/main/webapp/addressbook/list.xhtml         |   133 +
 .../src/main/webapp/addressbook/start.xhtml        |    67 +
 .../src/main/webapp/addressbook/tab/business.xhtml |    49 +
 .../src/main/webapp/addressbook/tab/misc.xhtml     |    32 +
 .../src/main/webapp/addressbook/tab/personal.xhtml |   128 +
 .../src/main/webapp/auth/error.xhtml               |    57 +
 .../src/main/webapp/auth/login.js                  |    45 +
 .../src/main/webapp/auth/login.xhtml               |    79 +
 .../src/main/webapp/auth/logout.js                 |    27 +
 .../src/main/webapp/auth/logout.xhtml              |    56 +
 .../src/main/webapp/error.xhtml                    |    56 +
 .../src/main/webapp/icon/favicon.ico               |   Bin 0 -> 1150 bytes
 .../src/main/webapp/index.html                     |    27 +
 .../src/test/resources/realm.properties            |    20 +
 .../tobago-example/tobago-example-assembly/pom.xml |    91 +
 .../src/main/assembly/dep.xml                      |    44 +
 .../src/main/resources/LICENSE.txt                 |   255 +
 .../src/main/resources/NOTICE.txt                  |    16 +
 .../tobago-example/tobago-example-blank/pom.xml    |    42 +
 .../apache/myfaces/tobago/example/blank/Hello.java |    50 +
 .../src/main/resources/logback.xml                 |    38 +
 .../src/main/webapp/META-INF/context.xml           |    26 +
 .../src/main/webapp/WEB-INF/faces-config.xml       |    36 +
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    35 +
 .../src/main/webapp/WEB-INF/web.xml                |    74 +
 .../src/main/webapp/helloWorld.xhtml               |    34 +
 .../src/main/webapp/index.html                     |    27 +
 .../tobago-example/tobago-example-data/pom.xml     |    37 +
 .../tobago/example/data/CantorInterval.java        |   150 +
 .../myfaces/tobago/example/data/CategoryTree.java  |    88 +
 .../myfaces/tobago/example/data/CommandNode.java   |    51 +
 .../tobago/example/data/CommandNodeFactory.java    |    40 +
 .../myfaces/tobago/example/data/Element.java       |    47 +
 .../myfaces/tobago/example/data/LocaleEntry.java   |    75 +
 .../myfaces/tobago/example/data/LocaleList.java    |    97 +
 .../tobago/example/data/MixedCommandTree.java      |    46 +
 .../myfaces/tobago/example/data/NamedNode.java     |    72 +
 .../apache/myfaces/tobago/example/data/Node.java   |   133 +
 .../apache/myfaces/tobago/example/data/Planet.java |    99 +
 .../myfaces/tobago/example/data/Salutation.java    |    48 +
 .../tobago/example/data/SalutationConverter.java   |    43 +
 .../myfaces/tobago/example/data/SmallTree.java     |    34 +
 .../apache/myfaces/tobago/example/data/Solar.java  |    42 +
 .../myfaces/tobago/example/data/SolarObject.java   |   366 +
 .../resources/META-INF/resources/data/EUR-14.png   |   Bin 0 -> 3274 bytes
 .../main/resources/META-INF/resources/data/EUR.png |   Bin 0 -> 3651 bytes
 .../resources/META-INF/resources/data/JPY-14.png   |   Bin 0 -> 3672 bytes
 .../main/resources/META-INF/resources/data/JPY.png |   Bin 0 -> 3955 bytes
 .../resources/META-INF/resources/data/TTD-14.png   |   Bin 0 -> 3896 bytes
 .../main/resources/META-INF/resources/data/TTD.png |   Bin 0 -> 4358 bytes
 .../resources/META-INF/resources/data/USD-14.png   |   Bin 0 -> 3762 bytes
 .../main/resources/META-INF/resources/data/USD.png |   Bin 0 -> 4285 bytes
 .../META-INF/resources/data/edit-solar.xhtml       |    27 +
 .../resources/data/sun-behind-mountains.jpg        |   Bin 0 -> 14656 bytes
 .../tobago-example/tobago-example-demo/pom.xml     |   785 ++
 .../src/main/appended-resouces/META-INF/LICENSE    |    51 +
 .../src/main/appended-resouces/META-INF/NOTICE     |     9 +
 .../tobago/example/demo/ButtonLinkController.java  |    42 +
 .../tobago/example/demo/CkeditorController.java    |    85 +
 .../example/demo/CollapsibleBoxController.java     |    47 +
 .../tobago/example/demo/CollapsibleController.java |    60 +
 .../example/demo/CollapsiblePanelController.java   |    47 +
 .../example/demo/CollapsiblePopupController.java   |    47 +
 .../example/demo/CollapsibleSectionController.java |    47 +
 .../tobago/example/demo/ConversionController.java  |    39 +
 .../example/demo/CurrentValueController.java       |    84 +
 .../tobago/example/demo/DateController.java        |    79 +
 .../example/demo/DefaultCommandController.java     |    67 +
 .../myfaces/tobago/example/demo/DemoBundle.java    |    42 +
 .../tobago/example/demo/DemoController.java        |   294 +
 .../tobago/example/demo/EventController.java       |   260 +
 .../tobago/example/demo/ExceptionController.java   |    41 +
 .../tobago/example/demo/ExecuteController.java     |   100 +
 .../tobago/example/demo/ForEachController.java     |   114 +
 .../tobago/example/demo/FormAjaxController.java    |    57 +
 .../tobago/example/demo/FormController.java        |    53 +
 .../example/demo/FormRequiredController.java       |    57 +
 .../tobago/example/demo/GroupController.java       |   141 +
 .../myfaces/tobago/example/demo/InController.java  |    48 +
 .../example/demo/InputSuggestController.java       |   194 +
 .../myfaces/tobago/example/demo/Jsr303Bean.java    |    63 +
 .../apache/myfaces/tobago/example/demo/Login.java  |    96 +
 .../myfaces/tobago/example/demo/ManifestEntry.java |    41 +
 .../tobago/example/demo/ManifestReader.java        |    81 +
 .../tobago/example/demo/MessagesController.java    |    84 +
 .../tobago/example/demo/NavigationNode.java        |   117 +
 .../tobago/example/demo/NavigationState.java       |   143 +
 .../tobago/example/demo/NavigationTree.java        |   177 +
 .../tobago/example/demo/ObjectController.java      |    33 +
 .../tobago/example/demo/OnOffConverter.java        |    49 +
 .../myfaces/tobago/example/demo/OutController.java |    33 +
 .../tobago/example/demo/PanelController.java       |    44 +
 .../example/demo/PartialReloadController.java      |   129 +
 .../myfaces/tobago/example/demo/PlanetExample.java |    76 +
 .../tobago/example/demo/PopupController.java       |    66 +
 .../demo/PrettyUrlForMenuNavigationHandler.java    |    61 +
 .../tobago/example/demo/ProgressController.java    |    77 +
 .../tobago/example/demo/ResizeController.java      |    36 +
 .../tobago/example/demo/RoleController.java        |    56 +
 .../demo/SelectBooleanCheckboxController.java      |    88 +
 .../tobago/example/demo/SelectController.java      |    51 +
 .../tobago/example/demo/SelectItemModel.java       |   102 +
 .../example/demo/SelectManyCheckboxController.java |    66 +
 .../example/demo/SelectManyListboxController.java  |    75 +
 .../example/demo/SelectManyShuttleController.java  |    75 +
 .../example/demo/SelectOneChoiceController.java    |    39 +
 .../example/demo/SelectOneListboxController.java   |    65 +
 .../example/demo/SelectOneRadioController.java     |    61 +
 .../myfaces/tobago/example/demo/ServerInfo.java    |   126 +
 .../tobago/example/demo/SeverityController.java    |    53 +
 .../myfaces/tobago/example/demo/SheetConfig.java   |   201 +
 .../tobago/example/demo/SheetController.java       |   162 +
 .../tobago/example/demo/SheetFilterController.java |   308 +
 .../example/demo/SheetSortingController.java       |    93 +
 .../tobago/example/demo/SheetTreeController.java   |    42 +
 .../tobago/example/demo/SolarConverter.java        |    44 +
 .../tobago/example/demo/SourceFileReader.java      |    51 +
 .../tobago/example/demo/SuggestController.java     |    86 +
 .../demo/SynchronizeNavigationPhaseListener.java   |    64 +
 .../myfaces/tobago/example/demo/TabController.java |    97 +
 .../tobago/example/demo/TestController.java        |    53 +
 .../tobago/example/demo/TestExceptionHandler.java  |    74 +
 .../example/demo/TestExceptionHandlerFactory.java  |    40 +
 .../tobago/example/demo/TextareaController.java    |    57 +
 .../tobago/example/demo/ThemeController.java       |    74 +
 .../tobago/example/demo/TinyMceController.java     |    52 +
 .../example/demo/TreeCommandTypesController.java   |    60 +
 .../tobago/example/demo/TreeController.java        |    78 +
 .../tobago/example/demo/TreeEditorController.java  |   217 +
 .../tobago/example/demo/TreeSelectController.java  |    83 +
 .../tobago/example/demo/UniversalLoggingInfo.java  |   253 +
 .../tobago/example/demo/UploadController.java      |   119 +
 .../myfaces/tobago/example/demo/UploadItem.java    |    64 +
 .../tobago/example/demo/ValidationController.java  |    61 +
 .../example/demo/ValidationJsr303Controller.java   |    53 +
 .../actionlistener/SimpleTabChangeListener.java    |    55 +
 .../demo/bestpractice/BestPracticeController.java  |    87 +
 .../demo/bestpractice/ToolBarCustomizer.java       |   102 +
 .../demo/bestpractice/TransitionController.java    |    49 +
 .../demo/clientConfig/ClientConfigController.java  |   195 +
 .../clientConfig/ClientConfigPhaseListener.java    |    54 +
 .../example/demo/formatter/AbstractConverter.java  |   104 +
 .../tobago/example/demo/formatter/Converter.java   |    30 +
 .../example/demo/formatter/JspTagConverter.java    |    97 +
 .../example/demo/formatter/SourceFormatter.java    |    69 +
 .../example/demo/formatter/StringExpression.java   |   111 +
 .../example/demo/formatter/TagConverter.java       |    45 +
 .../myfaces/tobago/example/demo/info/Activity.java |    80 +
 .../tobago/example/demo/info/ActivityList.java     |    78 +
 .../example/demo/info/ActivityPhaseListener.java   |    60 +
 .../example/demo/info/ActivitySessionListener.java |    45 +
 .../example/demo/nonfacesrequest/FishPond.java     |    83 +
 .../myfaces/tobago/example/demo/sudoku/Sudoku.java |   263 +
 .../src/main/resources/logback.xml                 |    36 +
 .../apache/myfaces/tobago/example/demo/Demo.xml    |   429 +
 .../apache/myfaces/tobago/example/demo/Demo_de.xml |   196 +
 .../tobago/example/demo/demo_en.properties.xml     |    24 +
 .../tobago/example/demo/demo_ja.properties.xml     |    24 +
 .../tobago/example/demo/demo_ru.properties.xml     |    24 +
 .../src/main/webapp/META-INF/context.xml           |    26 +
 .../src/main/webapp/WEB-INF/beans.xml              |    32 +
 .../src/main/webapp/WEB-INF/faces-config.xml       |    91 +
 .../src/main/webapp/WEB-INF/sun-web.xml            |    33 +
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    91 +
 .../src/main/webapp/WEB-INF/web.xml                |   198 +
 .../10-intro/30-new+in+3+0/new+in+3+0.xhtml        |   157 +
 .../50-migration/97-migration/migration30.xhtml    |   304 +
 .../50-migration/98-migration/migration20.xhtml    |   192 +
 .../50-migration/99-migration/migration15.xhtml    |   229 +
 .../content/10-intro/50-migration/migration.xhtml  |    32 +
 .../src/main/webapp/content/10-intro/intro.xhtml   |    74 +
 .../20-component/010-input/10-in/in.test.js        |    50 +
 .../content/20-component/010-input/10-in/in.xhtml  |    82 +
 .../010-input/20-suggest/suggest.test.js           |   541 +
 .../010-input/20-suggest/suggest.xhtml             |    86 +
 .../010-input/30-textarea/textarea.xhtml           |    62 +
 .../20-component/010-input/40-date/date.test.js    |   111 +
 .../20-component/010-input/40-date/date.xhtml      |   198 +
 .../010-input/50-input-group/group.test.js         |   108 +
 .../010-input/50-input-group/group.xhtml           |   153 +
 .../content/20-component/010-input/input.xhtml     |    55 +
 .../20-component/020-output/10-out/out.xhtml       |    59 +
 .../20-component/020-output/20-label/label.xhtml   |    58 +
 .../020-output/30-messages/messages.xhtml          |    91 +
 .../20-component/020-output/40-image/image.xhtml   |    52 +
 .../20-component/020-output/45-figure/figure.xhtml |    48 +
 .../020-output/50-progress/progress.xhtml          |    87 +
 .../20-component/020-output/60-object/object.js    |    64 +
 .../20-component/020-output/60-object/object.xhtml |    85 +
 .../content/20-component/020-output/output.xhtml   |    58 +
 .../selectBooleanCheckbox.test.js                  |   164 +
 .../selectBooleanCheckbox.xhtml                    |    77 +
 .../20-selectOneChoice/selectOneChoice.test.js     |   100 +
 .../20-selectOneChoice/selectOneChoice.xhtml       |    92 +
 .../30-selectOneRadio/selectOneRadio.test.js       |   108 +
 .../30-selectOneRadio/selectOneRadio.xhtml         |   118 +
 .../40-selectOneListbox/selectOneListbox.test.js   |   100 +
 .../40-selectOneListbox/selectOneListbox.xhtml     |    96 +
 .../selectManyCheckbox.test.js                     |   132 +
 .../50-selectManyCheckbox/selectManyCheckbox.xhtml |   100 +
 .../60-selectManyListbox/selectManyListbox.xhtml   |    90 +
 .../70-selectManyShuttle/selectManyShuttle.xhtml   |   124 +
 .../content/20-component/030-select/select.xhtml   |    78 +
 .../040-command/00-button+link/button+link.xhtml   |   154 +
 .../040-command/00-button+link/sample.html         |    24 +
 .../040-command/00-button+link/sample_de.html      |    24 +
 .../040-command/10-default/default-command.xhtml   |    78 +
 .../040-command/20-buttons/buttons.xhtml           |    82 +
 .../21-buttons-customizer/buttons-customizer.xhtml |    68 +
 .../x-buttons-item-delete.xhtml                    |    20 +
 .../x-buttons-item-edit.xhtml                      |    20 +
 .../21-buttons-customizer/x-buttons-item-new.xhtml |    20 +
 .../20-component/040-command/25-links/links.xhtml  |    75 +
 .../content/20-component/040-command/command.xhtml |    60 +
 .../20-component/050-container/10-box/box.xhtml    |    63 +
 .../050-container/20-panel/panel.xhtml             |    78 +
 .../050-container/30-separator/separator.xhtml     |    40 +
 .../050-container/40-section/section.xhtml         |    66 +
 .../50-header+footer/header+footer.xhtml           |    45 +
 .../50-header+footer/x-header-footer-example.xhtml |    41 +
 .../20-component/050-container/60-bar/bar.xhtml    |    83 +
 .../20-component/050-container/container.xhtml     |    59 +
 .../content/20-component/060-popup/popup.test.js   |   373 +
 .../content/20-component/060-popup/popup.xhtml     |   145 +
 .../070-tab/00-client/tab-client.xhtml             |    74 +
 .../20-component/070-tab/01-ajax/tab-ajax.xhtml    |   150 +
 .../070-tab/02-server/tab-server.xhtml             |   119 +
 .../webapp/content/20-component/070-tab/tab.xhtml  |    71 +
 .../00-content/sheet-column-content.xhtml          |    68 +
 .../080-sheet/10-sort/sheet-sorting.test.js        |  1182 ++
 .../080-sheet/10-sort/sheet-sorting.xhtml          |    83 +
 .../20-selector/sheet-column-selector.xhtml        |    69 +
 .../080-sheet/30-event/sheet-event.test.js         |   191 +
 .../080-sheet/30-event/sheet-event.xhtml           |   121 +
 .../080-sheet/35-markup/sheet-markup.xhtml         |    66 +
 .../080-sheet/50-filter/sheet-filter.xhtml         |   111 +
 .../55-staticheader/sheet-static-header.xhtml      |   118 +
 .../60-multiheader/sheet-multi-header.xhtml        |   123 +
 .../080-sheet/70-tree/sheet-tree.xhtml             |    69 +
 .../080-sheet/80-editable/sheet-editable.xhtml     |    81 +
 .../content/20-component/080-sheet/sheet.xhtml     |    71 +
 .../20-component/080-sheet/x-sheet-nested.xhtml    |    46 +
 .../090-tree/00-command/tree-command-types.xhtml   |    50 +
 .../090-tree/01-select/tree-select.test.js         |   320 +
 .../090-tree/01-select/tree-select.xhtml           |    66 +
 .../090-tree/02-editor/tree-editor.xhtml           |    79 +
 .../20-component/090-tree/03-menu/tree-menu.xhtml  |    45 +
 .../090-tree/04-listbox/tree-listbox.xhtml         |    39 +
 .../content/20-component/090-tree/tree.xhtml       |   117 +
 .../content/20-component/100-upload/upload.xhtml   |    94 +
 .../20-component/110-wysiwyg/00-tinymce/tinymce.js |    76 +
 .../110-wysiwyg/00-tinymce/tinymce.xhtml           |    65 +
 .../110-wysiwyg/01-ckeditor/ckeditor.xhtml         |    58 +
 .../110-wysiwyg/01-ckeditor/demo-ckeditor.js       |    55 +
 .../20-component/110-wysiwyg/wysiwyg-editor.xhtml  |    68 +
 .../webapp/content/20-component/component.xhtml    |    26 +
 .../06-validation/00/content-validation.test.js    |   254 +
 .../06-validation/00/content-validation.xhtml      |   117 +
 .../06-validation/01/validation-jsr303.test.js     |   106 +
 .../06-validation/01/validation-jsr303.xhtml       |    51 +
 .../30-concept/06-validation/02/severity.xhtml     |    33 +
 .../30-concept/06-validation/validation.xhtml      |    33 +
 .../30-concept/07-conversion/conversion.xhtml      |   108 +
 .../08-form/10-required/form-required.test.js      |   221 +
 .../08-form/10-required/form-required.xhtml        |    80 +
 .../30-concept/08-form/20-ajax/form-ajax.test.js   |   546 +
 .../30-concept/08-form/20-ajax/form-ajax.xhtml     |   116 +
 .../webapp/content/30-concept/08-form/form.test.js |    76 +
 .../webapp/content/30-concept/08-form/form.xhtml   |    62 +
 .../webapp/content/30-concept/10-theme/theme.xhtml |    60 +
 .../content/30-concept/12-browser/browser.xhtml    |    25 +
 .../content/30-concept/14-locale/locale.xhtml      |    48 +
 .../30-concept/16-layout/10-flow/flow-layout.xhtml |    95 +
 .../30-concept/16-layout/20-flex/flex-layout.xhtml |    97 +
 .../16-layout/30-segment/segment-layout.xhtml      |    90 +
 .../16-layout/40-labeled/labeled-layout.xhtml      |    86 +
 .../30-concept/16-layout/50-grid/grid-layout.xhtml |    30 +
 .../content/30-concept/16-layout/layout.xhtml      |    62 +
 .../content/30-concept/20-format/format.xhtml      |    55 +
 .../webapp/content/30-concept/21-error/error.xhtml |    49 +
 .../30-concept/21-error/x-error-in-syntax.xhtml    |    24 +
 .../30-concept/23-transition/transition.xhtml      |    63 +
 .../23-transition/x-transition-after-sleep.xhtml   |    28 +
 .../24-non-faces-response/non-faces-response.xhtml |    49 +
 .../30-concept/24-non-faces-response/x-sample.pdf  |   Bin 0 -> 10723 bytes
 .../30-concept/24-non-faces-response/x-sample.txt  |     1 +
 .../facelets-as-resources.xhtml                    |    34 +
 .../content/30-concept/50-partial/partial.css      |    20 +
 .../content/30-concept/50-partial/partial.xhtml    |   144 +
 .../30-concept/51-for-each/for-each.test.js        |    73 +
 .../content/30-concept/51-for-each/for-each.xhtml  |    81 +
 .../00-collapsible-box/collapsible-box.test.js     |   408 +
 .../00-collapsible-box/collapsible-box.xhtml       |   149 +
 .../10-collapsible-popup/collapsible-popup.test.js |   207 +
 .../10-collapsible-popup/collapsible-popup.xhtml   |    96 +
 .../20-collapsible-panel/collapsible-panel.test.js |   339 +
 .../20-collapsible-panel/collapsible-panel.xhtml   |   123 +
 .../collapsible-section.test.js                    |   340 +
 .../collapsible-section.xhtml                      |   121 +
 .../30-concept/53-collapsible/collapsible.xhtml    |   101 +
 .../30-concept/65-accessKey/accessKey.xhtml        |    92 +
 .../30-concept/70-dataAttribute/dataAttribute.js   |    69 +
 .../70-dataAttribute/dataAttribute.xhtml           |    71 +
 .../content/30-concept/75-resize/resize.xhtml      |    35 +
 .../webapp/content/30-concept/77-focus/focus.xhtml |    45 +
 .../30-concept/80-security/10/sanitize.xhtml       |    33 +
 .../30-concept/80-security/20-roles/roles.xhtml    |    81 +
 .../80-security/content-security-policy.xhtml      |    54 +
 .../90-non-faces-request/non-faces-request.xhtml   |    45 +
 .../90-non-faces-request/x-fish-pond.xhtml         |    46 +
 .../main/webapp/content/30-concept/concept.xhtml   |    26 +
 .../webapp/content/35-deprecated/10-tx/tx.xhtml    |    49 +
 .../15-suggest-method/suggest-method.test.js       |    75 +
 .../15-suggest-method/suggest-method.xhtml         |    53 +
 .../content/35-deprecated/20-toolBar/toolBar.xhtml |   115 +
 .../content/35-deprecated/25-menubar/menubar.xhtml |    68 +
 .../35-deprecated/70-grid-layout/grid-layout.xhtml |   101 +
 .../webapp/content/35-deprecated/deprecated.xhtml  |    25 +
 .../webapp/content/40-test/1040-date/date.test.js  |    33 +
 .../webapp/content/40-test/1040-date/date.xhtml    |    30 +
 .../content/40-test/2000-selectItem/currency.xhtml |    39 +
 .../40-test/2000-selectItem/list-of-objects.xhtml  |    54 +
 .../40-test/2000-selectItem/type-of-literals.xhtml |    58 +
 .../3000-sheet/10-sheet-types/sheet-types.test.js  |   104 +
 .../3000-sheet/10-sheet-types/sheet-types.xhtml    |    70 +
 .../3000-sheet/20-1000-entries/1000-entries.xhtml  |    43 +
 .../webapp/content/40-test/3000-sheet/sheet.xhtml  |    28 +
 .../40-test/4000-button+link/button+link.test.js   |   129 +
 .../40-test/4000-button+link/button+link.xhtml     |    89 +
 .../40-test/4000-button+link/x-action.xhtml        |    27 +
 .../content/40-test/4000-button+link/x-link.xhtml  |    27 +
 .../content/40-test/5000-form/sheet-in-form.xhtml  |    97 +
 .../rendererBase-getCurrentValue.test.js           |    45 +
 .../rendererBase-getCurrentValue.xhtml             |    44 +
 .../20-ajax-execute/ajax-execute.test.js           |   101 +
 .../50000-java/20-ajax-execute/ajax-execute.xhtml  |    65 +
 .../webapp/content/40-test/50000-java/java.xhtml   |    28 +
 .../content/40-test/6000-event/event.test.js       |   364 +
 .../webapp/content/40-test/6000-event/event.xhtml  |   103 +
 .../content/40-test/6000-event/x-event-bar.xhtml   |    27 +
 .../40-test/6000-event/x-event-button.xhtml        |    31 +
 .../6000-event/x-event-component-content.xhtml     |   133 +
 .../content/40-test/6000-event/x-event-in.xhtml    |    31 +
 .../content/40-test/6000-event/x-event-row.xhtml   |   156 +
 .../40-test/6000-event/x-event-textarea.xhtml      |    31 +
 .../4000-button+link/button+link.xhtml             |    73 +
 .../5000-lengthOfInputs/lengthOfInputs.xhtml       |    38 +
 .../content/40-test/60000-manual/manual.xhtml      |    25 +
 .../40-test/7000-layout/markup-spread-flex.xhtml   |    46 +
 .../40-test/7000-layout/markup-spread-grid.xhtml   |    46 +
 .../src/main/webapp/content/40-test/test.xhtml     |    28 +
 .../src/main/webapp/error/404.xhtml                |    27 +
 .../src/main/webapp/error/error.test.js            |    26 +
 .../src/main/webapp/error/exception.xhtml          |    54 +
 .../src/main/webapp/icon/favicon.ico               |   Bin 0 -> 3638 bytes
 .../src/main/webapp/image/alps.png                 |   Bin 0 -> 160353 bytes
 .../webapp/image/charlotteville/theme-photo.jpg    |   Bin 0 -> 84811 bytes
 .../src/main/webapp/image/feather-leaf.png         |   Bin 0 -> 1633 bytes
 .../src/main/webapp/image/feather-open.png         |   Bin 0 -> 1631 bytes
 .../src/main/webapp/image/feather.png              |   Bin 0 -> 1617 bytes
 .../src/main/webapp/image/richmond/theme-photo.jpg |   Bin 0 -> 60609 bytes
 .../src/main/webapp/image/scarborough/country.png  |   Bin 0 -> 3407 bytes
 .../webapp/image/scarborough/country_de_AT.png     |   Bin 0 -> 1503 bytes
 .../webapp/image/scarborough/country_de_CH.png     |   Bin 0 -> 1861 bytes
 .../webapp/image/scarborough/country_de_DE.png     |   Bin 0 -> 2026 bytes
 .../webapp/image/scarborough/country_en_GB.png     |   Bin 0 -> 2107 bytes
 .../webapp/image/scarborough/country_en_US.png     |   Bin 0 -> 1705 bytes
 .../webapp/image/scarborough/country_ja_JP.png     |   Bin 0 -> 1623 bytes
 .../webapp/image/scarborough/country_ru_RU.png     |   Bin 0 -> 1843 bytes
 .../main/webapp/image/scarborough/theme-photo.jpg  |   Bin 0 -> 82245 bytes
 .../src/main/webapp/image/speyside/theme-photo.jpg |   Bin 0 -> 94846 bytes
 .../src/main/webapp/image/standard/theme-photo.jpg |   Bin 0 -> 3776 bytes
 .../src/main/webapp/image/tobago_head.png          |   Bin 0 -> 2484 bytes
 .../tobago-example-demo/src/main/webapp/index.html |    27 +
 .../tobago-example-demo/src/main/webapp/init.xhtml |    39 +
 .../src/main/webapp/logging-info.xhtml             |    84 +
 .../src/main/webapp/login.xhtml                    |    41 +
 .../tobago-example-demo/src/main/webapp/main.xhtml |    79 +
 .../tobago-example-demo/src/main/webapp/menu.xhtml |   140 +
 .../src/main/webapp/navigation.xhtml               |    32 +
 .../src/main/webapp/plain.xhtml                    |    31 +
 .../src/main/webapp/script/demo.js                 |   110 +
 .../src/main/webapp/script/prism.js                |   682 ++
 .../src/main/webapp/script/qunit-1.23.1.js         |  4334 +++++++
 .../src/main/webapp/script/tobago-test.js          |    40 +
 .../src/main/webapp/server-info.xhtml              |    99 +
 .../src/main/webapp/style/demo.css                 |    55 +
 .../src/main/webapp/style/prism.css                |   138 +
 .../src/main/webapp/style/qunit-1.23.1.css         |   305 +
 .../src/main/webapp/style/tobago.css               |    36 +
 .../tobago-example-demo/src/main/webapp/test.xhtml |    36 +
 .../standard/property/demo.properties.xml          |    23 +
 .../richmond/standard/property/demo.properties.xml |    23 +
 .../standard/property/demo.properties.xml          |    23 +
 .../speyside/standard/property/demo.properties.xml |    24 +
 .../src/origin/image/clickImage.psd                |   Bin 0 -> 34787 bytes
 .../src/origin/image/country.psd                   |   Bin 0 -> 54825 bytes
 .../src/origin/image/country_de_AT.psd             |   Bin 0 -> 22119 bytes
 .../src/origin/image/country_de_CH.psd             |   Bin 0 -> 24348 bytes
 .../src/origin/image/country_de_DE.psd             |   Bin 0 -> 26282 bytes
 .../src/origin/image/country_en_GB.psd             |   Bin 0 -> 26279 bytes
 .../src/origin/image/country_en_US.psd             |   Bin 0 -> 23170 bytes
 .../src/origin/image/country_ja_JP.psd             |   Bin 0 -> 23830 bytes
 .../src/origin/image/country_ru_RU.psd             |   Bin 0 -> 24509 bytes
 .../tobago/example/demo/ArquillianTest.java        |   106 +
 .../tobago/example/demo/NavigationUnitTest.java    |    67 +
 .../myfaces/tobago/example/demo/QUnitTests.java    |   429 +
 .../tobago/example/demo/sudoku/SudokuUnitTest.java |    73 +
 .../src/test/resources/arquillian.xml              |     1 +
 .../src/test/resources/realm.properties            |    20 +
 .../src/test/resources/server.xml                  |    39 +
 .../src/test/tomee/conf/tomcat-users.xml           |    25 +
 .../tobago-example/tobago-example-portlet/pom.xml  |    29 +
 .../myfaces/tobago/example/portlet/User.java       |    32 +
 .../src/main/resources/logback.xml                 |    38 +
 .../src/main/webapp/WEB-INF/faces-config.xml       |    50 +
 .../src/main/webapp/WEB-INF/liferay-portlet.xml    |    27 +
 .../src/main/webapp/WEB-INF/portlet.xml            |    41 +
 .../src/main/webapp/WEB-INF/web.xml                |    46 +
 .../src/main/webapp/hello.xhtml                    |    32 +
 .../src/main/webapp/index.xhtml                    |    32 +
 .../tobago-example/tobago-example-test/pom.xml     |   292 +
 .../myfaces/tobago/example/test/Attribute.java     |    56 +
 .../myfaces/tobago/example/test/Bootstrap.java     |    51 +
 .../example/test/ClientConfigController.java       |   156 +
 .../tobago/example/test/DateController.java        |    51 +
 .../tobago/example/test/DirectoryBrowser.java      |   108 +
 .../myfaces/tobago/example/test/DynamicBean.java   |    62 +
 .../myfaces/tobago/example/test/DynamicPanel.java  |    40 +
 .../myfaces/tobago/example/test/DynamicPanel1.java |    33 +
 .../myfaces/tobago/example/test/DynamicPanel2.java |    42 +
 .../myfaces/tobago/example/test/DynamicPanel3.java |    44 +
 .../myfaces/tobago/example/test/ErrorTest.java     |    28 +
 .../tobago/example/test/ErrorTestException.java    |    27 +
 .../apache/myfaces/tobago/example/test/Hidden.java |    56 +
 .../myfaces/tobago/example/test/Immediate.java     |    80 +
 .../apache/myfaces/tobago/example/test/InBean.java |    45 +
 .../example/test/InputSuggestController.java       |    48 +
 .../myfaces/tobago/example/test/KillSession.java   |    40 +
 .../myfaces/tobago/example/test/MeasureBean.java   |    95 +
 .../myfaces/tobago/example/test/Messages.java      |    44 +
 .../myfaces/tobago/example/test/PageItem.java      |    91 +
 .../myfaces/tobago/example/test/Partially.java     |    72 +
 .../myfaces/tobago/example/test/PopupData.java     |    33 +
 .../tobago/example/test/PopupModalAttribute.java   |    31 +
 .../example/test/PopupReferenceController.java     |   110 +
 .../myfaces/tobago/example/test/Progress.java      |    43 +
 .../apache/myfaces/tobago/example/test/Reload.java |    51 +
 .../myfaces/tobago/example/test/ResourceBean.java  |    79 +
 .../myfaces/tobago/example/test/ResourceEntry.java |    97 +
 .../myfaces/tobago/example/test/ResourceType.java  |    25 +
 .../myfaces/tobago/example/test/ScriptEvent.java   |    50 +
 .../tobago/example/test/ScriptEventItem.java       |    47 +
 .../tobago/example/test/ScriptEventServlet.java    |    57 +
 .../example/test/SelectBooleanCheckboxBean.java    |    80 +
 .../tobago/example/test/SelectManyListboxBean.java |   120 +
 .../tobago/example/test/SheetController.java       |    67 +
 .../tobago/example/test/SheetSortController.java   |   141 +
 .../myfaces/tobago/example/test/Shuttle.java       |    47 +
 .../tobago/example/test/TestExceptionHandler.java  |    69 +
 .../example/test/TestExceptionHandlerFactory.java  |    40 +
 .../tobago/example/test/TestPageFilter.java        |   132 +
 .../myfaces/tobago/example/test/Tobago1041.java    |    64 +
 .../tobago/example/test/TreeController.java        |    79 +
 .../tobago/example/test/TrueAndFalseList.java      |    31 +
 .../example/test/UndefinedRowCountDataModel.java   |    36 +
 .../apache/myfaces/tobago/example/test/Upload.java |    60 +
 .../myfaces/tobago/example/test/Version.java       |    63 +
 .../myfaces/tobago/example/test/WaitFilter.java    |    64 +
 .../tobago/example/test/ZIndexController.java      |    44 +
 .../src/main/resources/META-INF/popup.xhtml        |    38 +
 .../META-INF/tobago-example-test.taglib.xml        |    32 +
 .../src/main/resources/logback.xml                 |    36 +
 .../tobago-example-test/src/main/webapp/404.xhtml  |    39 +
 .../tobago-example-test/src/main/webapp/500.xhtml  |    38 +
 .../src/main/webapp/WEB-INF/faces-config.xml       |   262 +
 .../src/main/webapp/WEB-INF/sun-web.xml            |    33 +
 .../src/main/webapp/WEB-INF/tobago-config.xml      |    58 +
 .../src/main/webapp/WEB-INF/web.xml                |   164 +
 .../src/main/webapp/facet/contextMenu/panel.xhtml  |    66 +
 .../src/main/webapp/image/feather-leaf.png         |   Bin 0 -> 1633 bytes
 .../src/main/webapp/image/foo.gif                  |   Bin 0 -> 1579 bytes
 .../src/main/webapp/image/foo.png                  |   Bin 0 -> 247 bytes
 .../src/main/webapp/image/fooDisabled.gif          |   Bin 0 -> 1568 bytes
 .../src/main/webapp/image/fooDisabled.png          |   Bin 0 -> 199 bytes
 .../src/main/webapp/image/wait/cat.jpg             |   Bin 0 -> 5921 bytes
 .../src/main/webapp/immediate.xhtml                |    47 +
 .../tobago-example-test/src/main/webapp/index.html |    27 +
 .../src/main/webapp/meta-test/meta-0-ok.xhtml      |    29 +
 .../src/main/webapp/meta-test/meta-1-fail.xhtml    |    33 +
 .../src/main/webapp/meta-test/meta-2-ok.xhtml      |    29 +
 .../src/main/webapp/meta-test/meta-3-ok.xhtml      |    29 +
 .../main/webapp/meta-test/meta-4-not-tobago.xhtml  |    28 +
 .../webapp/meta-test/meta-5-error-on-server.xhtml  |    30 +
 .../src/main/webapp/navigation.xhtml               |    65 +
 .../src/main/webapp/partially/encoding.xhtml       |    72 +
 .../src/main/webapp/pidgeon-point.jpg              |   Bin 0 -> 15539 bytes
 .../src/main/webapp/pidgeon-pointDisabled.jpg      |   Bin 0 -> 12227 bytes
 .../src/main/webapp/pidgeon-pointHover.jpg         |   Bin 0 -> 12158 bytes
 .../src/main/webapp/resource-manager/image.xhtml   |    42 +
 .../src/main/webapp/resource-manager/script.xhtml  |   100 +
 .../src/main/webapp/script/tobago-assert.js        |   169 +
 .../src/main/webapp/script/tobago.js               |    22 +
 .../src/main/webapp/simple.xhtml                   |    28 +
 .../src/main/webapp/style/tobago.css               |    20 +
 .../webapp/test/accessKey/accessKey-auto-off.xhtml |    39 +
 .../webapp/test/accessKey/accessKey-auto-on.xhtml  |    39 +
 .../src/main/webapp/test/attribute/attribute.xhtml |    80 +
 .../main/webapp/test/attribute/mode-valueIfSet.js  |    39 +
 .../webapp/test/attribute/mode-valueIfSet.xhtml    |   106 +
 .../test/attribute/popup-modal.selenium.html       |   143 +
 .../main/webapp/test/attribute/popup-modal.xhtml   |    39 +
 .../src/main/webapp/test/box/box-box-auto.xhtml    |    62 +
 .../main/webapp/test/box/box-box-relative.xhtml    |    43 +
 .../src/main/webapp/test/box/box.xhtml             |    45 +
 .../webapp/test/button/button-static-layout.xhtml  |    50 +
 .../main/webapp/test/button/defaultCommand.xhtml   |    42 +
 .../test/button/link-attribute.selenium.html       |    77 +
 .../main/webapp/test/button/link-attribute.xhtml   |    34 +
 .../src/main/webapp/test/button/plain.html         |    22 +
 .../src/main/webapp/test/button/plain.xhtml        |    31 +
 .../src/main/webapp/test/button/plain_de.html      |    22 +
 .../src/main/webapp/test/button/plain_de.xhtml     |    31 +
 .../src/main/webapp/test/cell/3x3-center.xhtml     |    45 +
 .../webapp/test/cell/position-4x4-span-steps.xhtml |    73 +
 .../src/main/webapp/test/cell/subview.xhtml        |    51 +
 .../src/main/webapp/test/date/date-layout.xhtml    |    43 +
 .../main/webapp/test/date/date-tobago-1105.xhtml   |    72 +
 .../src/main/webapp/test/date/date.xhtml           |    89 +
 .../src/main/webapp/test/date/datetime.js          |   178 +
 .../src/main/webapp/test/date/datetime.xhtml       |   496 +
 .../main/webapp/test/error/display-exception.xhtml |    39 +
 .../main/webapp/test/error/throw-exception.xhtml   |    47 +
 .../src/main/webapp/test/file/file-markup.xhtml    |    40 +
 .../src/main/webapp/test/file/file.xhtml           |    31 +
 .../test/flexLayout/flexLayout-horizontal.xhtml    |    33 +
 .../webapp/test/flexLayout/flexLayout-simple.xhtml |    29 +
 .../test/flexLayout/flexLayout-vertical.xhtml      |    36 +
 .../test/flowLayout/flowLayout-textAlign.xhtml     |    83 +
 .../src/main/webapp/test/footer/footer-fixed.xhtml |    63 +
 .../src/main/webapp/test/footer/footer.xhtml       |    63 +
 .../main/webapp/test/forEach/dynamic-include.xhtml |    61 +
 .../webapp/test/forEach/panel-one-fragment.xhtml   |    33 +
 .../webapp/test/forEach/panel-three-fragment.xhtml |    34 +
 .../webapp/test/forEach/panel-two-fragment.xhtml   |    34 +
 .../test/gridLayout/auto-vertical-in+in.xhtml      |    41 +
 .../gridLayout/constraints-border+padding.xhtml    |    40 +
 .../test/gridLayout/constraints-border.xhtml       |    38 +
 .../test/gridLayout/constraints-padding.xhtml      |    38 +
 .../gridLayout/current-vs-preferred-in-auto.xhtml  |    41 +
 .../horizontal-600px-asterisk-default.xhtml        |    36 +
 .../horizontal-600px-default-300px.xhtml           |    38 +
 .../horizontal-600px-default-default.xhtml         |    36 +
 .../horizontal-default-default-600px.xhtml         |    38 +
 .../webapp/test/gridLayout/margin-fallback.xhtml   |    36 +
 .../src/main/webapp/test/gridLayout/margin.xhtml   |    39 +
 .../src/main/webapp/test/gridLayout/nested-4.xhtml |    76 +
 .../webapp/test/gridLayout/nested-simple.xhtml     |    44 +
 .../src/main/webapp/test/gridLayout/nested-v.xhtml |    47 +
 .../src/main/webapp/test/gridLayout/nested.xhtml   |    80 +
 .../webapp/test/gridLayout/not-exact-4x4.xhtml     |    68 +
 .../main/webapp/test/gridLayout/not-exact.xhtml    |    39 +
 .../test/gridLayout/position-1+1x1-span.xhtml      |    40 +
 .../test/gridLayout/position-10x10-span.xhtml      |   120 +
 .../webapp/test/gridLayout/position-2x2-out.xhtml  |    42 +
 .../test/gridLayout/position-2x2-span-bottom.xhtml |    43 +
 .../test/gridLayout/position-2x2-span-left.xhtml   |    42 +
 .../test/gridLayout/position-2x2-span-right.xhtml  |    42 +
 .../test/gridLayout/position-2x2-span-top.xhtml    |    43 +
 .../main/webapp/test/gridLayout/position-2x2.xhtml |    42 +
 .../test/gridLayout/position-4x4-span-steps.xhtml  |    68 +
 .../gridLayout/proportion-versus-minimum.xhtml     |    51 +
 .../relative-inside-auto-1-1-cannot-match.xhtml    |    62 +
 .../test/gridLayout/relative-inside-auto-1-1.xhtml |    62 +
 .../test/gridLayout/relative-inside-auto-1-3.xhtml |    62 +
 .../relative-inside-auto-2-columns.xhtml           |    48 +
 .../gridLayout/relative-inside-auto-2-rows.xhtml   |    48 +
 .../gridLayout/rendered-auto-2x2-all-but-1.xhtml   |    49 +
 .../gridLayout/rendered-auto-2x2-all-but-2.xhtml   |    49 +
 .../gridLayout/rendered-auto-2x2-all-but-3.xhtml   |    49 +
 .../gridLayout/rendered-auto-2x2-all-but-4.xhtml   |    49 +
 .../rendered-combinations-3-images-fragment.xhtml  |    43 +
 .../test/gridLayout/rendered-combinations.xhtml    |   284 +
 .../gridLayout/rendered-pixel-2x2-all-but-1.xhtml  |    41 +
 .../gridLayout/rendered-pixel-2x2-all-but-2.xhtml  |    41 +
 .../gridLayout/rendered-pixel-2x2-all-but-3.xhtml  |    41 +
 .../gridLayout/rendered-pixel-2x2-all-but-4.xhtml  |    41 +
 .../gridLayout/rendered-prop-2x2-all-but-1.xhtml   |    42 +
 .../gridLayout/rendered-prop-2x2-all-but-2.xhtml   |    42 +
 .../gridLayout/rendered-prop-2x2-all-but-3.xhtml   |    42 +
 .../gridLayout/rendered-prop-2x2-all-but-4.xhtml   |    42 +
 .../src/main/webapp/test/gridLayout/rigid.xhtml    |   140 +
 .../test/gridLayout/scrolling-2-levels.xhtml       |    60 +
 .../webapp/test/gridLayout/scrolling-box.xhtml     |    52 +
 .../webapp/test/gridLayout/scrolling-page.xhtml    |    49 +
 .../gridLayout/scrolling-panel-with-border.xhtml   |    53 +
 .../webapp/test/gridLayout/scrolling-panel.xhtml   |    52 +
 .../webapp/test/gridLayout/scrolling-tab.xhtml     |    57 +
 .../main/webapp/test/gridLayout/size-auto.xhtml    |    44 +
 .../main/webapp/test/gridLayout/size-maximum.xhtml |    39 +
 .../main/webapp/test/gridLayout/size-minimum.xhtml |    39 +
 .../webapp/test/gridLayout/size-preferred.xhtml    |    39 +
 .../src/main/webapp/test/gridLayout/size-set.xhtml |    36 +
 .../webapp/test/gridLayout/spacing-nested.xhtml    |   125 +
 .../webapp/test/gridLayout/spacing-simple.xhtml    |    52 +
 .../test/gridLayout/tabGroup-auto-auto.xhtml       |    69 +
 .../webapp/test/gridLayout/tabGroup-auto.xhtml     |    69 +
 .../webapp/test/gridLayout/tabGroup-relative.xhtml |    56 +
 .../main/webapp/test/gridLayout/tobago-1239.xhtml  |    43 +
 .../main/webapp/test/gridLayout/tobago-1243.xhtml  |    51 +
 .../gridLayout/too-less-components-empty.xhtml     |    31 +
 .../too-less-components-horizontal-6.xhtml         |    40 +
 .../too-less-components-horizontal.xhtml           |    36 +
 .../too-less-components-vertical-6.xhtml           |    40 +
 .../gridLayout/too-less-components-vertical.xhtml  |    36 +
 .../test/gridLayout/too-much-components.xhtml      |    42 +
 .../transparent-for-layout-fragment.xhtml          |    29 +
 .../test/gridLayout/transparent-for-layout.xhtml   |    54 +
 .../src/main/webapp/test/header/header-fixed.xhtml |    62 +
 .../src/main/webapp/test/header/header.xhtml       |    62 +
 .../src/main/webapp/test/hidden/hidden.xhtml       |    61 +
 .../main/webapp/test/image/alphaBlendingBug.xhtml  |    57 +
 .../src/main/webapp/test/image/disabled.xhtml      |    52 +
 .../src/main/webapp/test/image/image.xhtml         |    38 +
 .../src/main/webapp/test/in/id-and-fieldId.js      |    87 +
 .../src/main/webapp/test/in/id-and-fieldId.xhtml   |   139 +
 .../src/main/webapp/test/in/in-layout.xhtml        |    45 +
 .../src/main/webapp/test/in/in-tx.xhtml            |    41 +
 .../src/main/webapp/test/in/in.xhtml               |    38 +
 .../src/main/webapp/test/label/for-auto.xhtml      |   117 +
 .../src/main/webapp/test/label/label-tx.xhtml      |    39 +
 .../src/main/webapp/test/label/label.xhtml         |    45 +
 .../src/main/webapp/test/link/link-layout.xhtml    |    59 +
 .../webapp/test/markup/tobago-1215.selenium.html   |    59 +
 .../src/main/webapp/test/markup/tobago-1215.xhtml  |    43 +
 .../test/messages/messages-confirmation.xhtml      |    37 +
 .../src/main/webapp/test/messages/messages.xhtml   |    35 +
 .../src/main/webapp/test/object/object-full.xhtml  |    43 +
 .../src/main/webapp/test/page/html.xhtml           |    40 +
 .../src/main/webapp/test/page/page.xhtml           |    28 +
 .../test/popup/popup-bug-tobago-1091.selenium.html |    57 +
 .../webapp/test/popup/popup-bug-tobago-1091.xhtml  |    66 +
 .../test/popup/popup-bug-tobago-1103.selenium.html |   157 +
 .../webapp/test/popup/popup-bug-tobago-1103.xhtml  |    97 +
 ...popup-close-after-submit-and-ajax.selenium.html |    67 +
 .../popup/popup-close-after-submit-and-ajax.xhtml  |    65 +
 .../test/popup/popup-draggable.selenium.html       |    67 +
 .../main/webapp/test/popup/popup-draggable.xhtml   |    48 +
 .../main/webapp/test/popup/popup-in-sheet.xhtml    |   108 +
 .../src/main/webapp/test/popup/z-index.xhtml       |   388 +
 .../test/progress/progress-tobago-1218.xhtml       |    32 +
 .../src/main/webapp/test/progress/progress.xhtml   |    32 +
 .../src/main/webapp/test/reload/tip.xhtml          |    49 +
 .../webapp/test/resource/resource-manager.xhtml    |    51 +
 .../src/main/webapp/test/resource/tobago-694.xhtml |    43 +
 .../src/main/webapp/test/script/script-event.js    |    37 +
 .../src/main/webapp/test/script/script-event.xhtml |    75 +
 .../src/main/webapp/test/section/section.xhtml     |    52 +
 .../test/segmentLayout/buttons-with-image.xhtml    |    98 +
 .../main/webapp/test/segmentLayout/simple-1.xhtml  |    33 +
 .../main/webapp/test/segmentLayout/simple-2.xhtml  |    38 +
 .../main/webapp/test/segmentLayout/simple-3.xhtml  |    43 +
 .../checkbox-bug-tobago-1041.xhtml                 |   181 +
 .../selectBooleanCheckbox-layout.xhtml             |    49 +
 .../selectBooleanCheckbox.xhtml                    |   132 +
 .../selectManyCheckbox-layout.xhtml                |    48 +
 .../selectManyCheckbox/selectManyCheckbox.xhtml    |    96 +
 .../selectManyListbox-layout.xhtml                 |    48 +
 .../selectManyListbox-value.xhtml                  |    76 +
 .../test/selectManyListbox/selectManyListbox.xhtml |    86 +
 .../selectManyShuttle-layout.xhtml                 |    50 +
 .../selectManyShuttle-value.selenium.html          |    80 +
 .../selectManyShuttle-value.xhtml                  |    66 +
 .../test/selectManyShuttle/selectManyShuttle.xhtml |    87 +
 .../selectOneChoice/selectOneChoice-layout.xhtml   |    48 +
 .../test/selectOneChoice/selectOneChoice.xhtml     |    88 +
 .../selectOneListbox/selectOneListbox-layout.xhtml |    48 +
 .../test/selectOneListbox/selectOneListbox.xhtml   |    86 +
 .../selectOneRadio/selectOneRadio-layout.xhtml     |    48 +
 .../test/selectOneRadio/selectOneRadio.xhtml       |    96 +
 .../separator/separator-with-label-facet.xhtml     |    41 +
 .../test/separator/separator-with-label.xhtml      |    37 +
 .../test/separator/separator-without-label.xhtml   |    37 +
 .../sheet/sheet-auto-height-header-footer.xhtml    |   125 +
 .../webapp/test/sheet/sheet-auto-height-rows.xhtml |    98 +
 .../main/webapp/test/sheet/sheet-auto-width.xhtml  |    52 +
 .../test/sheet/sheet-bug-tobago-1090.selenium.html |    89 +
 .../webapp/test/sheet/sheet-bug-tobago-1090.xhtml  |    55 +
 .../src/main/webapp/test/sheet/sheet-large.js      |    34 +
 .../src/main/webapp/test/sheet/sheet-large.xhtml   |    66 +
 .../webapp/test/sheet/sheet-multi-header.xhtml     |   103 +
 .../webapp/test/sheet/sheet-paging-1.selenium.html |    44 +
 .../main/webapp/test/sheet/sheet-paging-1.xhtml    |    36 +
 .../test/sheet/sheet-paging-11.selenium.html       |    44 +
 .../main/webapp/test/sheet/sheet-paging-11.xhtml   |    39 +
 .../test/sheet/sheet-paging-20.selenium.html       |    44 +
 .../main/webapp/test/sheet/sheet-paging-20.xhtml   |    36 +
 .../src/main/webapp/test/sheet/sheet-reload.js     |    38 +
 .../src/main/webapp/test/sheet/sheet-reload.xhtml  |    54 +
 .../webapp/test/sheet/sheet-selector.selenium.html |   354 +
 .../main/webapp/test/sheet/sheet-selector.xhtml    |    78 +
 .../src/main/webapp/test/sheet/sheet-simple.js     |    27 +
 .../src/main/webapp/test/sheet/sheet-simple.xhtml  |    43 +
 .../webapp/test/sheet/sheet-sort.selenium.html     |   219 +
 .../src/main/webapp/test/sheet/sheet-sort.xhtml    |    58 +
 .../src/main/webapp/test/sheet/sheet-tree.xhtml    |    56 +
 .../test/sheet/sheet-unknown-row-count.xhtml       |    40 +
 .../sheet/sheet-without-columns-definition.xhtml   |    34 +
 .../main/webapp/test/suggest/tc-in-suggest.xhtml   |    34 +
 .../main/webapp/test/suggest/tx-in-suggest.xhtml   |    34 +
 .../src/main/webapp/test/tabGroup/client.xhtml     |    56 +
 .../test/tabGroup/selectedIndexWithoutSetter.xhtml |    35 +
 .../src/main/webapp/test/tabGroup/simple.xhtml     |   102 +
 .../test/tabGroup/tabGroup-layout-1164.xhtml       |    46 +
 .../main/webapp/test/text/textarea-layout.xhtml    |    42 +
 .../src/main/webapp/test/time/time.xhtml           |   105 +
 .../src/main/webapp/test/tree/tree-command.xhtml   |    40 +
 .../webapp/test/tree/tree-expanded.selenium.html   |    72 +
 .../src/main/webapp/test/tree/tree-expanded.xhtml  |    41 +
 .../src/main/webapp/test/tree/tree-infinite.xhtml  |    45 +
 .../test/tree/tree-marked-with-model.selenium.html |    98 +
 .../webapp/test/tree/tree-marked-with-model.xhtml  |    61 +
 .../tree/tree-marked-without-model.selenium.html   |    98 +
 .../test/tree/tree-marked-without-model.xhtml      |    59 +
 .../webapp/test/tree/tree-select-via-state.xhtml   |    49 +
 .../webapp/test/tree/tree-select-via-value.xhtml   |    50 +
 .../webapp/test/tree/tree-select.selenium.html     |   113 +
 .../webapp/test/tree/tree-show-attributes.xhtml    |    90 +
 .../webapp/test/tree/tree-simple-with-data.xhtml   |    42 +
 .../src/main/webapp/test/tree/tree-simple.xhtml    |    41 +
 .../main/webapp/test/treeListbox/treeListbox.xhtml |    34 +
 .../webapp/test/treeMenu/treeMenu-command.xhtml    |    39 +
 .../webapp/test/treeMenu/treeMenu-simple.xhtml     |    39 +
 .../test/type/measure-image-with-constraints.xhtml |   142 +
 .../type/measure-image-without-constraints.xhtml   |   112 +
 .../src/main/webapp/test/version/version.js        |    44 +
 .../src/main/webapp/test/version/version.xhtml     |    50 +
 .../html/standard/standard/script/tobago.js        |    22 +
 .../tobago/example/test/AutomaticSeleniumTest.java |   129 +
 .../tobago/example/test/SeleniumScript.java        |   116 +
 .../tobago/example/test/SeleniumScriptItem.java    |    44 +
 .../myfaces/tobago/example/test/SeleniumTest.java  |    57 +
 .../tobago/example/test/SimpleSeleniumTest.java    |    35 +
 .../example/test/TestPageFilterUnitTest.java       |    45 +
 .../example/test/TestTheAutomaticSeleniumTest.java |   130 +
 .../tobago/example/test/TobagoSelenium.java        |    98 +
 tobago-3.0.x/tobago-extension/pom.xml              |    40 +
 .../tobago-extension/tobago-sandbox/pom.xml        |   289 +
 .../tobago-extension/tobago-sandbox/readme.txt     |     6 +
 .../src/main/appended-resources/META-INF/NOTICE    |     3 +
 .../src/main/faces-config/faces-config.xml         |    28 +
 .../internal/component/AbstractUINumberSlider.java |    47 +
 .../internal/component/AbstractUISplitLayout.java  |   135 +
 .../taglib/sandbox/NumberSliderTagDeclaration.java |    64 +
 .../taglib/sandbox/SplitLayoutTagDeclaration.java  |    73 +
 .../internal/taglib/sandbox/package-info.java      |    33 +
 .../sandbox/standard/tag/NumberSliderRenderer.java |   185 +
 .../standard/tag/SplitLayoutRenderer.java          |   166 +
 .../src/main/resources/META-INF/tobago-config.xml  |    47 +
 .../html/scarborough/standard/image/sliderEnd.png  |   Bin 0 -> 71 bytes
 .../scarborough/standard/image/sliderTriangle.png  |   Bin 0 -> 92 bytes
 .../html/scarborough/standard/script/tobago.js     |    81 +
 .../html/scarborough/standard/style/tobago.css     |    63 +
 tobago-3.0.x/tobago-pmd-config.xml                 |    52 +
 tobago-3.0.x/tobago-theme/pom.xml                  |   236 +
 tobago-3.0.x/tobago-theme/rebuild-theme.sh         |    50 +
 .../tobago-theme-charlotteville/pom.xml            |    44 +
 .../src/main/appended-resources/META-INF/NOTICE    |     3 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ++++++++++++
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 +
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 +
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ++++++
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 +
 .../src/main/resources/META-INF/tobago-config.xml  |    55 +
 .../src/main/scss/_custom.scss                     |    26 +
 .../src/main/scss/_tobago.scss                     |   918 ++
 .../tobago-theme/tobago-theme-richmond/pom.xml     |    47 +
 .../src/main/appended-resources/META-INF/NOTICE    |     4 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ++++++++++++
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 +
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 +
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ++++++
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 +
 .../src/main/resources/META-INF/tobago-config.xml  |    55 +
 .../src/main/scss/_custom.scss                     |    33 +
 .../src/main/scss/_tobago.scss                     |   918 ++
 .../tobago-theme/tobago-theme-scarborough/pom.xml  |    45 +
 .../src/main/appended-resources/META-INF/NOTICE    |     3 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ++++++++++++
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 +
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 +
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ++++++
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 +
 .../src/main/resources/META-INF/tobago-config.xml  |    55 +
 .../src/main/scss/_custom.scss                     |    26 +
 .../src/main/scss/_tobago.scss                     |   918 ++
 .../tobago-theme/tobago-theme-speyside/pom.xml     |    46 +
 .../src/main/appended-resources/META-INF/NOTICE    |     3 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ++++++++++++
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 +
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 +
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ++++++
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 +
 .../META-INF/resources/tobago/speyside/image/I.png |   Bin 0 -> 80 bytes
 .../META-INF/resources/tobago/speyside/image/L.png |   Bin 0 -> 84 bytes
 .../resources/tobago/speyside/image/Lminus.png     |   Bin 0 -> 112 bytes
 .../resources/tobago/speyside/image/Lplus.png      |   Bin 0 -> 112 bytes
 .../resources/tobago/speyside/image/MenuArrow.png  |   Bin 0 -> 88 bytes
 .../tobago/speyside/image/MenuCheckmark.png        |   Bin 0 -> 129 bytes
 .../tobago/speyside/image/MenuRadioChecked.png     |   Bin 0 -> 89 bytes
 .../resources/tobago/speyside/image/Rminus.png     |   Bin 0 -> 102 bytes
 .../resources/tobago/speyside/image/Rplus.png      |   Bin 0 -> 112 bytes
 .../META-INF/resources/tobago/speyside/image/T.png |   Bin 0 -> 83 bytes
 .../resources/tobago/speyside/image/Tminus.png     |   Bin 0 -> 112 bytes
 .../resources/tobago/speyside/image/Tplus.png      |   Bin 0 -> 112 bytes
 .../tobago/speyside/image/box-header-bg.png        |   Bin 0 -> 263 bytes
 .../tobago/speyside/image/file-upload.png          |   Bin 0 -> 189 bytes
 .../tobago/speyside/image/label-error-bg.png       |   Bin 0 -> 81 bytes
 .../tobago/speyside/image/label_underline.png      |   Bin 0 -> 68 bytes
 .../resources/tobago/speyside/image/minus.png      |   Bin 0 -> 102 bytes
 .../resources/tobago/speyside/image/nav_bg.png     |   Bin 0 -> 79 bytes
 .../resources/tobago/speyside/image/next.png       |   Bin 0 -> 80 bytes
 .../tobago/speyside/image/nextDisabled.png         |   Bin 0 -> 84 bytes
 .../resources/tobago/speyside/image/plus.png       |   Bin 0 -> 112 bytes
 .../resources/tobago/speyside/image/poweredBy.png  |   Bin 0 -> 1115 bytes
 .../resources/tobago/speyside/image/prev.png       |   Bin 0 -> 80 bytes
 .../tobago/speyside/image/prevDisabled.png         |   Bin 0 -> 84 bytes
 .../resources/tobago/speyside/image/red.png        |   Bin 0 -> 69 bytes
 .../resources/tobago/speyside/image/remove.png     |   Bin 0 -> 108 bytes
 .../speyside/image/tab-header-selected-bg.png      |   Bin 0 -> 659 bytes
 .../speyside/image/tab-header-unselected-bg.png    |   Bin 0 -> 656 bytes
 .../resources/tobago/speyside/image/tabNext.png    |   Bin 0 -> 82 bytes
 .../tobago/speyside/image/tabNextDisabled.png      |   Bin 0 -> 86 bytes
 .../resources/tobago/speyside/image/tabPrev.png    |   Bin 0 -> 82 bytes
 .../tobago/speyside/image/tabPrevDisabled.png      |   Bin 0 -> 87 bytes
 .../tobago/speyside/image/toolbarButtonMenu.png    |   Bin 0 -> 92 bytes
 .../speyside/image/toolbarButtonMenuDisabled.png   |   Bin 0 -> 92 bytes
 .../tobago/speyside/image/treeMenuClose.png        |   Bin 0 -> 99 bytes
 .../tobago/speyside/image/treeMenuOpen.png         |   Bin 0 -> 89 bytes
 .../tobago/speyside/image/treeNode-icon-leaf.png   |   Bin 0 -> 211 bytes
 .../tobago/speyside/image/treeNode-icon-open.png   |   Bin 0 -> 176 bytes
 .../tobago/speyside/image/treeNode-icon.png        |   Bin 0 -> 189 bytes
 .../resources/tobago/speyside/image/unchecked.png  |   Bin 0 -> 85 bytes
 .../tobago/speyside/image/uncheckedDisabled.png    |   Bin 0 -> 86 bytes
 .../resources/tobago/speyside/image/upload.png     |   Bin 0 -> 118 bytes
 .../src/main/resources/META-INF/tobago-config.xml  |    55 +
 .../src/main/scss/_custom.scss                     |    26 +
 .../src/main/scss/_tobago.scss                     |   918 ++
 .../lib/closure-compiler-LICENSE.txt               |   202 +
 .../lib/compiler-20120430.jar                      |   Bin 0 -> 5407463 bytes
 .../tobago-theme/tobago-theme-standard/pom.xml     |   133 +
 .../src/main/appended-resources/META-INF/LICENSE   |   263 +
 .../src/main/appended-resources/META-INF/NOTICE    |    26 +
 .../4.17.37/css/bootstrap-datetimepicker.css       |   373 +
 .../4.17.37/css/bootstrap-datetimepicker.min.css   |     5 +
 .../4.17.37/js/bootstrap-datetimepicker.js         |  2552 ++++
 .../4.17.37/js/bootstrap-datetimepicker.min.js     |     9 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css      |  7681 ++++++++++++
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.css.map  |     1 +
 .../bootstrap/4.0.0-alpha.5/css/bootstrap.min.css  |     7 +
 .../4.0.0-alpha.5/css/bootstrap.min.css.map        |     1 +
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.js        |  3430 ++++++
 .../bootstrap/4.0.0-alpha.5/js/bootstrap.min.js    |     7 +
 .../font-awesome/4.6.1/css/font-awesome.css        |  2178 ++++
 .../font-awesome/4.6.1/css/font-awesome.min.css    |     4 +
 .../font-awesome/4.6.1/fonts/FontAwesome.otf       |   Bin 0 -> 123112 bytes
 .../4.6.1/fonts/fontawesome-webfont.eot            |   Bin 0 -> 75220 bytes
 .../4.6.1/fonts/fontawesome-webfont.svg            |   685 ++
 .../4.6.1/fonts/fontawesome-webfont.ttf            |   Bin 0 -> 150920 bytes
 .../4.6.1/fonts/fontawesome-webfont.woff           |   Bin 0 -> 89076 bytes
 .../4.6.1/fonts/fontawesome-webfont.woff2          |   Bin 0 -> 70728 bytes
 .../standard/jquery-ui/1.12.1.custom/jquery-ui.js  |   748 ++
 .../jquery-ui/1.12.1.custom/jquery-ui.min.js       |     6 +
 .../tobago/standard/jquery/jquery-2.2.4.js         |  9814 +++++++++++++++
 .../tobago/standard/jquery/jquery-2.2.4.min.js     |     4 +
 .../tobago/standard/jquery/jquery-2.2.4.min.map    |     1 +
 .../standard/moment/2.13.0/moment-with-locales.js  | 12051 +++++++++++++++++++
 .../moment/2.13.0/moment-with-locales.min.js       |    76 +
 .../tobago/standard/script/tobago-calendar.js      |   250 +
 .../tobago/standard/script/tobago-console.js       |   306 +
 .../resources/tobago/standard/script/tobago-in.js  |    17 +
 .../resources/tobago/standard/script/tobago-jsf.js |  9510 +++++++++++++++
 .../tobago/standard/script/tobago-layout.js        |   269 +
 .../tobago/standard/script/tobago-overlay.js       |   134 +
 .../tobago/standard/script/tobago-popup.js         |    85 +
 .../tobago/standard/script/tobago-sheet.js         |   730 ++
 .../tobago/standard/script/tobago-suggest.js       |   136 +
 .../resources/tobago/standard/script/tobago-tab.js |    94 +
 .../tobago/standard/script/tobago-tree.js          |   311 +
 .../tobago/standard/script/tobago-utils.js         |   123 +
 .../resources/tobago/standard/script/tobago.js     |  1445 +++
 .../tether/1.1.1/css/tether-theme-arrows-dark.css  |   106 +
 .../1.1.1/css/tether-theme-arrows-dark.min.css     |     1 +
 .../tether/1.1.1/css/tether-theme-arrows.css       |   110 +
 .../tether/1.1.1/css/tether-theme-arrows.min.css   |     1 +
 .../tether/1.1.1/css/tether-theme-basic.css        |    21 +
 .../tether/1.1.1/css/tether-theme-basic.min.css    |     1 +
 .../tobago/standard/tether/1.1.1/css/tether.css    |     8 +
 .../standard/tether/1.1.1/css/tether.min.css       |     1 +
 .../tobago/standard/tether/1.1.1/js/tether.js      |  1715 +++
 .../tobago/standard/tether/1.1.1/js/tether.min.js  |     1 +
 .../0.11.1-patched-with-1212/typeahead.js          |  1540 +++
 .../0.11.1-patched-with-1212/typeahead.min.js      |     7 +
 .../src/main/resources/META-INF/tobago-config.xml  |   400 +
 .../src/main/scss/_custom.scss                     |    19 +
 .../src/main/scss/_tobago.scss                     |   918 ++
 .../renderkit/html/CssClassCompareUnitTest.java    |    94 +
 tobago-3.0.x/tobago-tool/pom.xml                   |    34 +
 .../tobago-tool/tobago-tool-annotation/pom.xml     |    28 +
 .../src/main/appended-resouces/META-INF/NOTICE     |     3 +
 .../myfaces/tobago/apt/annotation/Behavior.java    |    33 +
 .../apt/annotation/BodyContentDescription.java     |    37 +
 .../myfaces/tobago/apt/annotation/Category.java    |    30 +
 .../myfaces/tobago/apt/annotation/Converter.java   |    32 +
 .../tobago/apt/annotation/DynamicExpression.java   |   105 +
 .../tobago/apt/annotation/ExtensionTag.java        |    38 +
 .../myfaces/tobago/apt/annotation/Facet.java       |    44 +
 .../myfaces/tobago/apt/annotation/Preliminary.java |    36 +
 .../myfaces/tobago/apt/annotation/SimpleTag.java   |    28 +
 .../apache/myfaces/tobago/apt/annotation/Tag.java  |    44 +
 .../tobago/apt/annotation/TagAttribute.java        |    43 +
 .../myfaces/tobago/apt/annotation/Taglib.java      |    37 +
 .../tobago/apt/annotation/UIComponentTag.java      |    75 +
 .../apt/annotation/UIComponentTagAttribute.java    |    65 +
 .../myfaces/tobago/apt/annotation/Validator.java   |    32 +
 .../tobago/apt/annotation/ValidatorTag.java        |    29 +
 tobago-3.0.x/tobago-tool/tobago-tool-apt/pom.xml   |   119 +
 .../src/main/appended-resouces/META-INF/NOTICE     |     3 +
 .../apache/myfaces/tobago/apt/AnnotationUtils.java |    45 +
 .../myfaces/tobago/apt/generate/ClassInfo.java     |    92 +
 .../myfaces/tobago/apt/generate/ClassUtils.java    |    71 +
 .../myfaces/tobago/apt/generate/ComponentInfo.java |   127 +
 .../tobago/apt/generate/ComponentPropertyInfo.java |    61 +
 .../myfaces/tobago/apt/generate/Imports.java       |    67 +
 .../myfaces/tobago/apt/generate/PropertyInfo.java  |   262 +
 .../myfaces/tobago/apt/generate/RendererInfo.java  |    40 +
 .../myfaces/tobago/apt/generate/TagInfo.java       |    95 +
 .../tobago/apt/processor/AbstractGenerator.java    |   125 +
 .../apt/processor/CheckstyleConfigGenerator.java   |   350 +
 .../tobago/apt/processor/ClassesGenerator.java     |   283 +
 .../tobago/apt/processor/FacesConfigGenerator.java |   648 +
 .../tobago/apt/processor/TaglibGenerator.java      |   523 +
 .../org/apache/myfaces/tobago/apt/component.stg    |   587 +
 .../CheckstyleConfigGeneratorUnitTest.java         |    53 +
 1699 files changed, 242315 insertions(+)

diff --git a/tobago-3.0.x/build-site.sh b/tobago-3.0.x/build-site.sh
new file mode 100755
index 0000000..ad96ded
--- /dev/null
+++ b/tobago-3.0.x/build-site.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+usage()
+{
+  echo "Usage: $0"
+  exit 1
+}
+
+if [ -r ./settings ]
+then
+  source ./settings
+fi
+
+##############################################################################
+# Do some checks of the enviroment
+##############################################################################
+
+if [ -z "$JAVA_HOME" ]
+then
+  echo "JAVA_HOME must be set."
+fi
+
+if [ -z "`which java`" ]
+then
+  echo "Could not find 'java' in the path."
+  echo "PATH: $PATH"
+  exit 1
+fi
+
+
+##############################################################################
+# Build
+##############################################################################
+
+
+echo "Building tobago site."
+mvn clean
+mvn install javancss:report jxr:jxr jxr:test-jxr clirr:clirr -Daggregate=false --batch-mode
+mvn site:site -Daggregate=true --batch-mode
+mvn dashboard:dashboard
+mvn site:deploy -e -Daggregate=true --batch-mode
diff --git a/tobago-3.0.x/pom.xml b/tobago-3.0.x/pom.xml
new file mode 100644
index 0000000..9221caf
--- /dev/null
+++ b/tobago-3.0.x/pom.xml
@@ -0,0 +1,1365 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces</groupId>
+    <artifactId>myfaces</artifactId>
+    <version>16</version>
+  </parent>
+  <groupId>org.apache.myfaces.tobago</groupId>
+  <artifactId>tobago</artifactId>
+  <packaging>pom</packaging>
+  <name>Apache Tobago</name>
+  <version>3.0.3</version>
+  <description>The goal of Tobago is to provide the community with a well designed set of user interface components based on JSF and run on MyFaces.</description>
+  <prerequisites>
+    <maven>3.0.4</maven>
+  </prerequisites>
+  <url>http://myfaces.apache.org/tobago</url>
+  <inceptionYear>2002</inceptionYear>
+
+  <properties>
+    <myfaces20.version>2.0.24</myfaces20.version>
+    <myfaces21.version>2.1.18</myfaces21.version>
+    <myfaces22.version>2.2.11</myfaces22.version>
+    <mojarra20.version>2.0.11-04</mojarra20.version>
+    <mojarra21.version>2.1.29-08</mojarra21.version>
+    <mojarra22.version>2.2.14</mojarra22.version>
+    <slf4j.version>1.7.22</slf4j.version>
+    <logback.version>1.1.8</logback.version>
+    <commons-collection.version>3.2.2</commons-collection.version>
+    <maven.compile.source>1.6</maven.compile.source>
+    <maven.compile.target>1.6</maven.compile.target>
+    <maven.compile.encoding>UTF-8</maven.compile.encoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <required.maven.version>3.0.4</required.maven.version>
+  </properties>
+
+  <issueManagement>
+    <system>jira</system>
+    <url>https://issues.apache.org/jira/browse/TOBAGO</url>
+  </issueManagement>
+  <ciManagement>
+    <system>jenkins</system>
+    <url>https://builds.apache.org/</url>
+    <notifiers>
+      <notifier>
+        <type>mail</type>
+        <configuration>
+          <address>commits@myfaces.apache.org</address>
+        </configuration>
+      </notifier>
+    </notifiers>
+  </ciManagement>
+  <mailingLists>
+    <mailingList>
+      <name>Myfaces User List (use [Tobago] prefix)</name>
+      <subscribe>users-subscribe@myfaces.apache.org</subscribe>
+      <unsubscribe>users-unsubscribe@myfaces.apache.org</unsubscribe>
+      <post>List for posting questions about how to use myfaces projects. Subscribe to this list before posting</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/myfaces-users</archive>
+      <otherArchives>
+        <otherArchive>http://www.mail-archive.com/users@myfaces.apache.org/</otherArchive>
+        <otherArchive>http://myfaces.10567.n7.nabble.com/MyFaces-Users-f57691.html</otherArchive>
+        <otherArchive>http://myfaces.markmail.org/search/?q=#query:list%3Aorg.apache.myfaces.users</otherArchive>
+      </otherArchives>
+    </mailingList>
+    <mailingList>
+      <name>Myfaces Developer List (use [Tobago] prefix)</name>
+      <subscribe>dev-subscribe@myfaces.apache.org</subscribe>
+      <unsubscribe>dev-unsubscribe@myfaces.apache.org</unsubscribe>
+      <post>List for posting patches and discussing internal code implementation issues. Subscribe to this list before posting</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/myfaces-dev</archive>
+      <otherArchives>
+        <otherArchive>http://www.mail-archive.com/dev@myfaces.apache.org/</otherArchive>
+        <otherArchive>http://myfaces.10567.n7.nabble.com/My-Faces-Dev-f3.html</otherArchive>
+        <otherArchive>http://myfaces.markmail.org/search/?q=#query:list%3Aorg.apache.myfaces.dev</otherArchive>
+      </otherArchives>
+    </mailingList>
+    <mailingList>
+      <name>Myfaces Commits List</name>
+      <subscribe>commits-subscribe@myfaces.apache.org</subscribe>
+      <unsubscribe>commits-unsubscribe@myfaces.apache.org</unsubscribe>
+      <post>do not post</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/myfaces-commits</archive>
+      <otherArchives>
+        <otherArchive>http://myfaces.markmail.org/search/?q=#query:list%3Aorg.apache.myfaces.commits</otherArchive>
+      </otherArchives>
+    </mailingList>
+    <mailingList>
+      <name>Myfaces Notifications List</name>
+      <subscribe>notifications-subscribe@myfaces.apache.org</subscribe>
+      <unsubscribe>notifications-unsubscribe@myfaces.apache.org</unsubscribe>
+      <post>do not post</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/myfaces-notifications</archive>
+      <otherArchives>
+        <otherArchive>http://myfaces.markmail.org/search/?q=#query:list%3Aorg.apache.myfaces.notifications</otherArchive>
+      </otherArchives>
+    </mailingList>
+    <mailingList>
+      <name>Myfaces Announcements List</name>
+      <subscribe>announce-subscribe@myfaces.apache.org</subscribe>
+      <unsubscribe>announce-unsubscribe@myfaces.apache.org</unsubscribe>
+      <post>do not post</post>
+      <archive>http://mail-archives.apache.org/mod_mbox/myfaces-announce</archive>
+      <otherArchives>
+        <otherArchive>http://myfaces.markmail.org/search/?q=#query:list%3Aorg.apache.myfaces.announce</otherArchive>
+      </otherArchives>
+    </mailingList>
+    <mailingList>
+      <name>Myfaces Private (PMC) List</name>
+      <subscribe>only for MyFaces PMC members</subscribe>
+      <unsubscribe>private-unsubscribe@myfaces.apache.org</unsubscribe>
+      <post>do not post unless you need to contact PMC on issues not meant for public</post>
+    </mailingList>
+  </mailingLists>
+
+  <reporting>
+    <excludeDefaults>true</excludeDefaults>
+    <plugins>
+
+      <!--<plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>simian-report-maven-plugin</artifactId>
+        <version>1.0-SNAPSHOT</version>
+        <configuration>
+          <minimumThreshold>2</minimumThreshold>
+        </configuration>
+      </plugin>
+      -->
+      <!--plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>cobertura-maven-plugin</artifactId>
+        <version>2.2</version>
+      </plugin-->
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>taglist-maven-plugin</artifactId>
+        <version>2.4</version>
+        <configuration>
+          <tags>
+            <tag>TODO</tag>
+            <tag>FIXME</tag>
+            <tag>XXX</tag>
+            <tag>TBD</tag>
+            <tag>@deprecated</tag>
+          </tags>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jxr-plugin</artifactId>
+        <version>2.5</version>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>2.9.1</version><!-- before update MYFACES-3995 needs to be fixed -->
+        <configuration>
+          <configLocation>tobago/checkstyle.xml</configLocation>
+          <headerLocation>default/myfaces-header.txt</headerLocation>
+          <xrefLocation>xref</xrefLocation>
+          <excludes>**/package-info.java</excludes>
+          <indentSize>2</indentSize>
+          <includeTestSourceDirectory>true</includeTestSourceDirectory>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>2.8</version>
+        <configuration>
+          <linksource>true</linksource>
+          <breakiterator>true</breakiterator>
+          <quiet>true</quiet>
+          <verbose>false</verbose>
+          <source>${maven.compile.source}</source>
+          <charset>${maven.compile.encoding}</charset>
+          <links>
+            <link>http://docs.oracle.com/javase/6/docs/api/</link>
+            <link>http://docs.oracle.com/javaee/6/api/</link>
+            <link>http://jakarta.apache.org/commons/collections/api-${commons-collection.version}/</link>
+            <link>http://www.slf4j.org/apidocs</link>
+            <link>http://junit.sourceforge.net/javadoc/</link>
+            <link>http://logback.qos.ch/apidocs/</link>
+          </links>
+          <excludePackageNames>org.apache.myfaces.tobago.internal.*</excludePackageNames>
+          <docletArtifact>
+            <groupId>com.google.doclava</groupId>
+            <artifactId>doclava</artifactId>
+            <version>1.0.6</version>
+          </docletArtifact>
+          <doclet>com.google.doclava.Doclava</doclet>
+          <!--
+            | bootclasspath required by Sun's JVM
+          -->
+          <bootclasspath>${sun.boot.class.path}</bootclasspath>
+          <additionalparam>
+             -quiet
+             -federate JDK http://download.oracle.com/javase/6/docs/api/index.html?
+             -federationxml JDK http://doclava.googlecode.com/svn/static/api/openjdk-6.xml
+             -hdf project.name "${project.name}"
+             -d ${project.build.directory}/apidocs
+          </additionalparam>
+          <useStandardDocletOptions>false</useStandardDocletOptions>
+          <!--
+            | Apple's JVM sometimes requires more memory
+          -->
+          <additionalJOption>-J-Xmx1024m</additionalJOption>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-report-plugin</artifactId>
+        <version>2.18.1</version>
+        <configuration>
+          <aggregate>true</aggregate>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-project-info-reports-plugin</artifactId>
+        <version>2.9</version>
+      </plugin>
+
+      <!--plugin>
+        <inherited>false</inherited>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changes-plugin</artifactId>
+        <version>2.7.1</version>
+        <reportSets>
+          <reportSet>
+            <configuration>
+              <statusIds>Open,In Progress,Reopened</statusIds>
+            </configuration>
+            <reports>
+              <report>jira-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin-->
+
+      <plugin>
+        <inherited>false</inherited>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-changelog-plugin</artifactId>
+        <version>2.3</version>
+        <configuration>
+          <basedir>${basedir}</basedir>
+        </configuration>
+      </plugin>
+
+      <!--
+            <plugin>
+              <inherited>false</inherited>
+              <groupId>org.apache.maven.plugins</groupId>
+              <artifactId>maven-doap-plugin</artifactId>
+              <configuration>
+                <category>web-framework</category>
+                <language>Java</language>
+                <shortdesc>Set of user interface components based on JSF.</shortdesc>
+                <pmc>http://myfaces.apache.org</pmc>
+              </configuration>
+            </plugin>
+      -->
+
+      <!--plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>clirr-maven-plugin</artifactId>
+        <configuration>
+          <minSeverity>info</minSeverity>
+          <excludes>
+            <exclude>org/apache/myfaces/tobago/example/**</exclude>
+            <exclude>org/apache/myfaces/tobago/ant/**</exclude>
+            <exclude>org/apache/myfaces/tobago/apt/**</exclude>
+          </excludes>
+        </configuration>
+      </plugin-->
+
+      <!-- pmd has problems with annotations -->
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <version>3.4</version>
+        <configuration>
+          <rulesets>
+            <!-- FIXME: currently only possible to build in project build -->
+            <ruleset>${basedir}/tobago-pmd-config.xml</ruleset>
+          </rulesets>
+          <linkXRef>true</linkXRef>
+          <targetJdk>${maven.compile.source}</targetJdk>
+          <aggregate>true</aggregate>
+        </configuration>
+      </plugin>                              
+
+      <!-- TODO test dashboard plugin  -->
+      <!--plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>dashboard-maven-plugin</artifactId>
+        <version>1.0.0-beta-1</version>
+      </plugin-->
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>findbugs-maven-plugin</artifactId>
+        <version>3.0.1</version>
+        <configuration>
+          <threshold>Low</threshold>
+          <effort>Max</effort>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>jdepend-maven-plugin</artifactId>
+        <version>2.0</version>
+      </plugin>
+
+      <!-- http://jira.codehaus.org/browse/MJNCSS-4
+           JavaNCSS still has problems with annotations for local variables -->
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>javancss-maven-plugin</artifactId>
+        <version>2.1</version>
+        <configuration>
+          <excludes>
+            <exclude>org/apache/myfaces/tobago/internal/layout/Grid.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+        <version>0.11</version>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <version>2.10</version>
+        <reportSets>
+          <reportSet>
+            <reports>
+              <report>analyze-report</report>
+            </reports>
+          </reportSet>
+        </reportSets>
+      </plugin>
+
+      <!--plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-linkcheck-plugin</artifactId>
+        <version>1.0.1</version>
+      </plugin-->
+
+    </plugins>
+
+  </reporting>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.apache.myfaces.core</groupId>
+        <artifactId>myfaces-api</artifactId>
+        <version>${myfaces20.version}</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.myfaces.core</groupId>
+        <artifactId>myfaces-impl</artifactId>
+        <version>${myfaces20.version}</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-servlet_3.0_spec</artifactId>
+        <version>1.0</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-el_2.2_spec</artifactId>
+        <version>1.0.4</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.slf4j</groupId>
+        <artifactId>slf4j-api</artifactId>
+        <version>${slf4j.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>ch.qos.logback</groupId>
+        <artifactId>logback-classic</artifactId>
+        <version>${logback.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>ch.qos.logback</groupId>
+        <artifactId>logback-core</artifactId>
+        <version>${logback.version}</version>
+      </dependency>
+      <!-- only needed to build Tobago and for some examples, but not for runtime -->
+      <dependency>
+        <groupId>commons-io</groupId>
+        <artifactId>commons-io</artifactId>
+        <version>2.4</version>
+      </dependency>
+      <!-- only needed to build Tobago and for some examples, but not for runtime -->
+      <dependency>
+        <groupId>commons-lang</groupId>
+        <artifactId>commons-lang</artifactId>
+        <version>2.6</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-beanutils</groupId>
+        <artifactId>commons-beanutils</artifactId>
+        <version>1.9.2</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-collections</groupId>
+        <artifactId>commons-collections</artifactId>
+        <version>${commons-collection.version}</version>
+      </dependency>
+      <dependency>
+        <groupId>commons-codec</groupId>
+        <artifactId>commons-codec</artifactId>
+        <version>1.10</version>
+      </dependency>
+      <dependency>
+        <groupId>junit</groupId>
+        <artifactId>junit</artifactId>
+        <version>4.12</version>
+        <scope>test</scope>
+      </dependency>
+      <dependency>
+        <groupId>javax.portlet</groupId>
+        <artifactId>portlet-api</artifactId>
+        <version>2.0</version>
+        <scope>provided</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-annotation_1.0_spec</artifactId>
+        <version>1.1.1</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+        <version>1.0</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.geronimo.specs</groupId>
+        <artifactId>geronimo-atinject_1.0_spec</artifactId>
+        <version>1.0</version>
+        <optional>true</optional>
+      </dependency>
+      <dependency>
+        <!-- jsoup HTML parser library -->
+        <groupId>org.jsoup</groupId>
+        <artifactId>jsoup</artifactId>
+        <version>1.8.2</version>
+      </dependency>
+      <dependency>
+        <groupId>org.apache.myfaces.test</groupId>
+        <artifactId>myfaces-test20</artifactId>
+        <version>1.0.7</version>
+        <scope>test</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-servlet_3.0_spec</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-el_2.2_spec</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>javax.portlet</groupId>
+      <artifactId>portlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+
+    <!-- you may want to add this for debugging -->
+<!--
+    <dependency>
+    	<groupId>org.jboss.portletbridge</groupId>
+    	<artifactId>portletbridge-api</artifactId>
+    	<version>3.2.1.Final</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+    	<groupId>org.jboss.portletbridge</groupId>
+    	<artifactId>portletbridge-impl</artifactId>
+    	<version>3.2.1.Final</version>
+      <scope>provided</scope>
+    </dependency>
+-->
+
+  </dependencies>
+
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/myfaces/tobago/tags/tobago-3.0.3</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/myfaces/tobago/tags/tobago-3.0.3</developerConnection>
+    <url>http://svn.eu.apache.org/viewvc/myfaces/tobago/tags/tobago-3.0.3</url>
+  </scm>
+
+  <build>
+    <defaultGoal>install</defaultGoal>
+    <plugins>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-pmd-plugin</artifactId>
+        <version>3.4</version>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-checkstyle-plugin</artifactId>
+        <version>2.9.1</version><!-- before update MYFACES-3995 needs to be fixed -->
+        <executions>
+          <execution>
+            <id>verify-style</id>
+            <phase>none</phase>
+          </execution>
+        </executions>
+        <configuration>
+          <configLocation>tobago/checkstyle.xml</configLocation>
+          <headerLocation>default/myfaces-header.txt</headerLocation>
+          <xrefLocation>xref</xrefLocation>
+          <excludes>**/package-info.java</excludes>
+          <indentSize>2</indentSize>
+          <includeTestSourceDirectory>true</includeTestSourceDirectory>
+        </configuration>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.myfaces.buildtools</groupId>
+            <artifactId>checkstyle-rules</artifactId>
+            <version>6</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-enforcer-plugin</artifactId>
+        <version>1.4.1</version>
+        <executions>
+          <execution>
+            <id>enforce</id>
+            <phase>validate</phase>
+            <goals>
+              <goal>enforce</goal>
+            </goals>
+            <configuration>
+              <rules>
+                <requireMavenVersion>
+                  <!-- 3.3.1 is only required for a release, for a normal build 3.0.4 should be okay -->
+                  <version>${required.maven.version}</version>
+                </requireMavenVersion>
+                <requirePluginVersions>
+                  <message>Best Practice is to always define plugin versions!</message>
+                  <banLatest>true</banLatest>
+                  <banRelease>true</banRelease>
+                  <unCheckedPlugins>
+                    <unCheckedPlugin>org.apache.maven.plugins:maven-eclipse-plugin</unCheckedPlugin>
+                  </unCheckedPlugins>
+                </requirePluginVersions>
+                <requireJavaVersion>
+                  <message>Tobago must be compiled with Java 8 or higher</message>
+                  <version>[1.8,)</version>
+                </requireJavaVersion>
+              </rules>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <!--<plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>cobertura-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>clean</id>
+            <goals>
+              <goal>clean</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>-->
+      <plugin>
+        <groupId>org.apache.rat</groupId>
+        <artifactId>apache-rat-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <artifactId>maven-remote-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>process</goal>
+            </goals>
+            <configuration>
+              <resourceBundles>
+                <resourceBundle>org.apache:apache-jar-resource-bundle:1.4</resourceBundle>
+              </resourceBundles>
+              <properties>
+                <addLicense>true</addLicense>
+              </properties>
+              <excludeScope>provided</excludeScope>
+              <excludeArtifactIds>servlet-api,jstl</excludeArtifactIds>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+        <configuration>
+          <signature>
+            <groupId>org.codehaus.mojo.signature</groupId>
+            <artifactId>java16</artifactId>
+            <version>1.1</version>
+          </signature>
+        </configuration>
+      </plugin>
+<!--
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        &lt;!&ndash; XXX better use antrun? &ndash;&gt;
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-config-schema</id>
+&lt;!&ndash; XXX why it is not possible to use the site phase here? &ndash;&gt;
+            &lt;!&ndash;<phase>site</phase>&ndash;&gt;
+            <phase>package</phase>
+            <goals>
+              <goal>copy-resources</goal>
+            </goals>
+            <configuration>
+              <outputDirectory>${project.build.directory}/site</outputDirectory>
+              <resources>
+                <resource>
+                  <directory>tobago-core/src/main/resources/org/apache/myfaces/tobago/config</directory>
+                  <includes>
+                    <include>**/*.xsd</include>
+                    <include>**/*.dtd</include>
+                  </includes>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+-->
+    </plugins>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-pmd-plugin</artifactId>
+          <version>3.4</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>build-helper-maven-plugin</artifactId>
+          <version>1.9.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-checkstyle-plugin</artifactId>
+          <version>2.9.1</version><!-- before update MYFACES-3995 needs to be fixed -->
+          <configuration>
+            <configLocation>tobago/checkstyle.xml</configLocation>
+            <headerLocation>default/myfaces-header.txt</headerLocation>
+            <xrefLocation>xref</xrefLocation>
+            <excludes>**/package-info.java</excludes>
+            <indentSize>2</indentSize>
+            <includeTestSourceDirectory>true</includeTestSourceDirectory>
+          </configuration>
+          <dependencies>
+            <dependency>
+              <groupId>org.apache.myfaces.buildtools</groupId>
+              <artifactId>checkstyle-rules</artifactId>
+              <version>6</version>
+            </dependency>
+          </dependencies>
+        </plugin>
+        <plugin>
+          <artifactId>maven-remote-resources-plugin</artifactId>
+          <version>1.5</version>
+          <executions>
+            <execution>
+              <goals>
+                <goal>process</goal>
+              </goals>
+              <configuration>
+                <resourceBundles>
+                  <resourceBundle>org.apache:apache-jar-resource-bundle:1.4</resourceBundle>
+                </resourceBundles>
+                <properties>
+                  <addLicense>true</addLicense>
+                </properties>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-jar-plugin</artifactId>
+          <version>2.6</version>
+          <configuration>
+            <archive>
+              <manifest>
+                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+              </manifest>
+              <manifestEntries>
+                <Revision>${scm.revision}</Revision>
+              </manifestEntries>
+              <manifestSections>
+                <manifestSection>
+                  <name>${project.artifactId}</name>
+                  <manifestEntries>
+                    <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                    <Implementation-Version>${project.version}</Implementation-Version>
+                  </manifestEntries>
+                </manifestSection>
+              </manifestSections>
+            </archive>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.cargo</groupId>
+          <artifactId>cargo-maven2-plugin</artifactId>
+          <version>1.4.13</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-compiler-plugin</artifactId>
+          <version>3.5.1</version>
+          <configuration>
+            <source>${maven.compile.source}</source>
+            <target>${maven.compile.target}</target>
+            <encoding>${maven.compile.encoding}</encoding>
+            <showWarnings>true</showWarnings>
+            <useIncrementalCompilation>false</useIncrementalCompilation><!-- see MCOMPILER-209 -->
+            <!--fork>true</fork-->
+            <!-- <compilerArgument>-Xlint:all,-serial,-fallthrough</compilerArgument>-->
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-dependency-plugin</artifactId>
+          <version>2.10</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-surefire-plugin</artifactId>
+          <version>2.19.1</version>
+          <configuration>
+            <argLine>-Duser.language=en -Duser.region=US</argLine>
+            <!--
+            <childDelegation>false</childDelegation>
+            <forkMode>perTest</forkMode>
+            -->
+<!--
+            <argLine>-Xdebug -Xnoagent -Djava.compiler=NONE
+            -Xrunjdwp:transport=dt_socket,address=5005,server=y,suspend=y</argLine>
+-->
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-failsafe-plugin</artifactId>
+          <version>2.19.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-javadoc-plugin</artifactId>
+          <version>2.10.3</version>
+          <configuration>
+            <!-- switched off check in Java 8 -->
+            <additionalparam>
+                -Xdoclint:accessibility
+                -Xdoclint:html
+                -Xdoclint:reference
+                -Xdoclint:syntax
+            </additionalparam>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-deploy-plugin</artifactId>
+          <version>2.8.2</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>clirr-maven-plugin</artifactId>
+          <version>2.6.1</version>
+          <configuration>
+            <failOnError>false</failOnError>
+            <minSeverity>info</minSeverity>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-war-plugin</artifactId>
+          <version>2.6</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-resources-plugin</artifactId>
+          <version>2.7</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-clean-plugin</artifactId>
+          <version>2.6.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-source-plugin</artifactId>
+          <version>2.4</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-install-plugin</artifactId>
+          <version>2.5.2</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-scm-plugin</artifactId>
+          <version>1.9.5</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-antrun-plugin</artifactId>
+          <version>1.8</version>
+        </plugin>
+        <plugin>
+          <groupId>com.github.matinh.vdldoc</groupId>
+          <artifactId>vdldoc-maven-plugin</artifactId>
+          <version>1.0</version>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.rat</groupId>
+          <artifactId>apache-rat-plugin</artifactId>
+          <version>0.11</version>
+          <configuration>
+            <excludes>
+              <!-- This file is created during a release and needs no licensing text -->
+              <exclude>DEPENDENCIES</exclude>
+
+              <!-- bootstrap -->
+              <exclude>**/tobago/*/bootstrap/**/bootstrap*.*</exclude>
+
+              <!-- bootstrap datetimepicker -->
+              <exclude>**/tobago/standard/bootstrap-datetimepicker/**/bootstrap*.*</exclude>
+
+              <!-- font-awesome -->
+              <exclude>**/tobago/standard/font-awesome/**/font*awesome*.*</exclude>
+
+              <!-- jQuery -->
+              <exclude>**/tobago/standard/jquery/**/jquery*.*</exclude>
+
+              <!-- jQuery UI -->
+              <exclude>**/tobago/standard/jquery-ui/**/jquery*.*</exclude>
+
+              <!-- moment -->
+              <exclude>**/tobago/standard/moment/**/moment*.*</exclude>
+
+              <!-- tether -->
+              <exclude>**/tobago/standard/tether/**/tether*.*</exclude>
+
+              <!-- typeahead -->
+              <exclude>**/tobago/standard/typeahead/**/typeahead*.*</exclude>
+
+              <!-- prism (tobago-example-demo) -->
+              <exclude>**/src/main/webapp/script/prism*.*</exclude>
+              <exclude>**/src/main/webapp/style/prism*.*</exclude>
+
+              <!-- qunit (tobago-example-demo) -->
+              <exclude>**/src/main/webapp/script/qunit*.*</exclude>
+              <exclude>**/src/main/webapp/style/qunit*.*</exclude>
+
+              <!-- log files -->
+              <exclude>**/*.log</exclude>
+
+              <!-- maven -->
+              <exclude>**/target/**/*</exclude>
+
+              <!-- idea -->
+              <exclude>.idea/**/*</exclude>
+              <exclude>**/*.iml</exclude>
+              <exclude>**/*.ipr</exclude>
+              <exclude>**/*.iws</exclude>
+
+              <!-- photo shop -->
+              <exclude>**/*.psd</exclude>
+
+              <!-- sample -->
+              <exclude>**/x-sample.txt</exclude>
+            </excludes>
+          </configuration>
+        </plugin>
+
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-assembly-plugin</artifactId>
+          <version>2.5.5</version>
+        </plugin>
+
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-release-plugin</artifactId>
+          <version>2.5.2</version>
+          <configuration>
+            <tagBase>https://svn.apache.org/repos/asf/myfaces/tobago/tags</tagBase>
+            <preparationGoals>clean install</preparationGoals>
+            <remoteTagging>true</remoteTagging>
+            <autoVersionSubmodules>true</autoVersionSubmodules>
+            <waitBeforeTagging>20</waitBeforeTagging>
+            <useReleaseProfile>false</useReleaseProfile>
+            <goals>deploy</goals>
+            <arguments>-Papache-release,generate-assembly ${arguments}</arguments>
+          </configuration>
+        </plugin>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-site-plugin</artifactId>
+          <version>3.5.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>animal-sniffer-maven-plugin</artifactId>
+          <version>1.14</version>
+        </plugin>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>versions-maven-plugin</artifactId>
+          <version>2.1</version>
+        </plugin>
+        <plugin>
+          <groupId>org.owasp</groupId>
+          <artifactId>dependency-check-maven</artifactId>
+          <version>1.4.5</version>
+          <configuration>
+            <!-- TBD: check which score can be accepted -->
+            <failBuildOnCVSS>3</failBuildOnCVSS>
+          </configuration>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <licenses>
+    <license>
+      <name>The Apache Software License, Version 2.0</name>
+      <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+
+  <modules>
+    <module>tobago-tool</module>
+    <module>tobago-core</module>
+    <module>tobago-theme</module>
+    <module>tobago-extension</module>
+    <module>tobago-example</module>
+    <module>tobago-assembly</module>
+  </modules>
+
+  <distributionManagement>
+    <repository>
+      <id>apache.releases.https</id>
+      <name>Apache Release Distribution Repository</name>
+      <url>https://repository.apache.org/service/local/staging/deploy/maven2</url>
+    </repository>
+    <snapshotRepository>
+      <uniqueVersion>false</uniqueVersion>
+      <id>apache.snapshots.https</id>
+      <name>${distMgmtSnapshotsName}</name>
+      <url>${distMgmtSnapshotsUrl}</url>
+    </snapshotRepository>
+    <site>
+      <id>apache-site</id>
+      <url>scpexe://minotaur.apache.org/www/myfaces.apache.org/tobago/</url>
+    </site>
+  </distributionManagement>
+
+  <!-- Use this to include the staging repository for testing a new unreleased myfaces core.
+  Change the number 1085 for that. -->
+<!--
+  <repositories>
+    <repository>
+      <id>myfaces-staging</id>
+      <url>https://repository.apache.org/content/repositories/orgapachemyfaces-1085/</url>
+    </repository>
+  </repositories>
+-->
+
+  <profiles>
+    <profile>
+      <id>apache-release</id>
+      <!--
+      NOTE: To use you need to enable this profile and pass in the passphrase:
+           mvn -Papache-release -Dpassphrase=thephrase
+
+           with the release plugin add following profile to your settings.xml
+           <profile>
+             <id>apache-release</id>
+             <properties>
+               <gpg.passphrase>thephrase</gpg.passphrase>
+             </properties>
+           </profile>
+       -->
+      <properties>
+        <required.maven.version>3.3.1</required.maven.version>
+      </properties>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>buildnumber-maven-plugin</artifactId>
+            <version>1.3</version>
+            <executions>
+              <execution>
+                <phase>validate</phase>
+                <goals>
+                  <goal>create</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <doCheck>false</doCheck>
+              <doUpdate>false</doUpdate>
+              <getRevisionOnlyOnce>true</getRevisionOnlyOnce>
+              <buildNumberPropertyName>scm.revision</buildNumberPropertyName>
+              <revisionOnScmFailure>unknown</revisionOnScmFailure>
+            </configuration>
+          </plugin>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>animal-sniffer-maven-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>test</phase>
+                <goals>
+                  <goal>check</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+
+          <plugin>
+            <groupId>org.owasp</groupId>
+            <artifactId>dependency-check-maven</artifactId>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>aggregate</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+
+          <plugin>
+            <artifactId>maven-source-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-sources</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-javadocs</id>
+                <goals>
+                  <goal>jar</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <profile>
+      <id>generate-assembly</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>buildnumber-maven-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>validate</phase>
+                <goals>
+                  <goal>create</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <doCheck>false</doCheck>
+              <doUpdate>false</doUpdate>
+              <getRevisionOnlyOnce>true</getRevisionOnlyOnce>
+              <buildNumberPropertyName>scm.revision</buildNumberPropertyName>
+              <revisionOnScmFailure>unknown</revisionOnScmFailure>
+            </configuration>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-javadoc-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-javadoc</id>
+                <goals><goal>jar</goal></goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-source</id>
+                <goals><goal>jar</goal></goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <dependencies>
+              <dependency>
+                <groupId>org.apache.apache.resources</groupId>
+                <artifactId>apache-source-release-assembly-descriptor</artifactId>
+                <version>1.0.2</version>
+              </dependency>
+            </dependencies>
+            <executions>
+              <execution>
+                <id>source-release-assembly</id>
+                <phase>package</phase>
+                <goals>
+                  <goal>single</goal>
+                </goals>
+                <configuration>
+                  <runOnlyAtExecutionRoot>true</runOnlyAtExecutionRoot>
+                  <descriptorRefs>
+                    <descriptorRef>${sourceReleaseAssemblyDescriptor}</descriptorRef>
+                  </descriptorRefs>
+                  <tarLongFileMode>gnu</tarLongFileMode>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+<!--
+    Attention: The next profiles should only be changed by a clean build.
+    They define the JSF version which are generally incompatible.
+    They also define the JSF implementation used to compile and for runtime.
+    
+    Usage for a standard build (jsf-2.0):
+    mvn 
+    
+    Usage for specific build:
+    mvn -Pjsf-2.1
+    mvn -Pjsf-2.2
+
+-->
+
+    <profile>
+      <id>jsf-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.1</value>
+        </property>
+      </activation>
+      <properties>
+        <jsf.target>2.0</jsf.target>
+      </properties>
+      <dependencyManagement>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.myfaces.core</groupId>
+            <artifactId>myfaces-api</artifactId>
+            <version>${myfaces21.version}</version>
+            <optional>true</optional>
+          </dependency>
+          <dependency>
+            <groupId>org.apache.myfaces.core</groupId>
+            <artifactId>myfaces-impl</artifactId>
+            <version>${myfaces21.version}</version>
+            <optional>true</optional>
+          </dependency>
+        </dependencies>
+      </dependencyManagement>
+    </profile>
+
+    <profile>
+      <id>jsf-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.2</value>
+        </property>
+      </activation>
+      <dependencyManagement>
+        <dependencies>
+          <dependency>
+            <groupId>org.apache.myfaces.core</groupId>
+            <artifactId>myfaces-api</artifactId>
+            <version>${myfaces22.version}</version>
+            <optional>true</optional>
+          </dependency>
+          <dependency>
+            <groupId>org.apache.myfaces.core</groupId>
+            <artifactId>myfaces-impl</artifactId>
+            <version>${myfaces22.version}</version>
+            <optional>true</optional>
+          </dependency>
+        </dependencies>
+      </dependencyManagement>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.0</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.0</value>
+        </property>
+      </activation>
+      <dependencyManagement>
+        <dependencies>
+          <dependency>
+            <groupId>com.sun.faces</groupId>
+            <artifactId>jsf-api</artifactId>
+            <version>${mojarra20.version}</version>
+            <optional>true</optional>
+          </dependency>
+          <dependency>
+            <groupId>com.sun.faces</groupId>
+            <artifactId>jsf-impl</artifactId>
+            <version>${mojarra20.version}</version>
+            <optional>true</optional>
+          </dependency>
+        </dependencies>
+      </dependencyManagement>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.1</value>
+        </property>
+      </activation>
+      <dependencyManagement>
+        <dependencies>
+          <dependency>
+            <groupId>com.sun.faces</groupId>
+            <artifactId>jsf-api</artifactId>
+            <version>${mojarra21.version}</version>
+            <optional>true</optional>
+          </dependency>
+          <dependency>
+            <groupId>com.sun.faces</groupId>
+            <artifactId>jsf-impl</artifactId>
+            <version>${mojarra21.version}</version>
+            <optional>true</optional>
+          </dependency>
+        </dependencies>
+      </dependencyManagement>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.2</value>
+        </property>
+      </activation>
+      <dependencyManagement>
+        <dependencies>
+          <dependency>
+            <groupId>com.sun.faces</groupId>
+            <artifactId>jsf-api</artifactId>
+            <version>${mojarra22.version}</version>
+            <optional>true</optional>
+          </dependency>
+          <dependency>
+            <groupId>com.sun.faces</groupId>
+            <artifactId>jsf-impl</artifactId>
+            <version>${mojarra22.version}</version>
+            <optional>true</optional>
+          </dependency>
+        </dependencies>
+      </dependencyManagement>
+    </profile>
+
+  </profiles>
+
+  <contributors>
+    <contributor>
+      <name>Helmut Swaczinna</name>
+      <email>swaczinna@wlp-systems.de</email>
+      <organization>WLP Systems GmbH</organization>
+      <organizationUrl>http://www.wlp-systems.de/</organizationUrl>
+      <timezone>+1</timezone>
+    </contributor>
+  </contributors>
+
+</project>
diff --git a/tobago-3.0.x/readme.txt b/tobago-3.0.x/readme.txt
new file mode 100644
index 0000000..a7feabc
--- /dev/null
+++ b/tobago-3.0.x/readme.txt
@@ -0,0 +1,17 @@
+Building
+--------
+You need Maven 3 (at least 3.0.4) and Java 6, 7 or 8 to build Tobago.
+
+In the main directory you can use
+
+  mvn install
+
+to run the install target on all sub projects. This will
+put all necessary artifacts into your local repository.
+
+Demo
+----
+
+In the directory tobago-example/tobago-example-demo
+
+mvn jetty:run
diff --git a/tobago-3.0.x/settings-example.xml b/tobago-3.0.x/settings-example.xml
new file mode 100644
index 0000000..1de495e
--- /dev/null
+++ b/tobago-3.0.x/settings-example.xml
@@ -0,0 +1,41 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<settings>
+  <servers>
+
+   <server> 
+      <!-- example tomcat configuration -->
+      <username>tomcat</username>
+      <password>tomcat</password>
+      <id>tomcat</id>
+    </server>
+
+  </servers>
+
+  <!--
+  <mirrors>
+    <mirror>
+       <id>planetmirror</id>
+       <name>Mirror of http://www.ibiblio.org/maven2/</name>
+       <url>http://public.planetmirror.com/maven2</url>
+       <mirrorOf>ibiblio</mirrorOf>
+     </mirror>
+   </mirrors>
+  -->
+
+</settings>
diff --git a/tobago-3.0.x/src/changes/changes.xml b/tobago-3.0.x/src/changes/changes.xml
new file mode 100644
index 0000000..2422167
--- /dev/null
+++ b/tobago-3.0.x/src/changes/changes.xml
@@ -0,0 +1,138 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<document>
+  <properties>
+    <title>Changes Tobago</title>
+    <author email="bernd.bohmann@atanion.com">bommel</author>
+    <author email="udo@schnurpfeil.de">lofwyr</author>
+  </properties>
+  <body>
+
+    <release version="1.0.7" date="in SVN">
+      <action dev="bommel" type="update">
+        Sheet supports paging in DataModel if getRowCount() returns -1
+      </action>
+      <action dev="lofwyr,bommel" type="update" issue="TOBAGO-20">
+        Simplify theme handling
+      </action>
+      <action dev="bommel" type="update">
+        Changed the Public identifier in tobago-config.xml from "-//Atanion GmbH//DTD Tobago Config 1.0//EN"
+        to "-//The Apache Software Foundation//DTD Tobago Config 1.0//EN"
+      </action>
+      <action dev="lofwyr" type="update">
+        build system changed to maven2
+      </action>
+      <action dev="lofwyr" type="update">
+        refactor TobagoConstants changed from interface -> class (using static import)
+      </action>
+      <action dev="lofwyr" type="update">
+        ResourceMananger supports XML properties now
+      </action>
+      <action dev="lofwyr" type="update">
+        siblingLeafOnly mode for t:treeListbox
+      </action>
+      <action dev="lofwyr" type="update">
+        rename property "selected" to "selectedRows" in SheetState which is now
+        a List&lt;Integer&gt;
+      </action>
+      <action dev="lofwyr" type="update">
+        add "p" option to openPopup()
+      </action>
+    </release>
+
+    <release version="1.0.6" date="2005-09-02">
+      <action dev="lofwyr" type="update">
+        refactor ResourceManager
+      </action>
+      <action dev="lofwyr" type="fix">
+        bugfix in UIData -> selection
+      </action>
+      <action dev="lofwyr" type="update">
+        change package names to org.apache.myfaces.tobago
+      </action>
+    </release>
+
+    <release version="1.0.5" date="2005-08-10">
+      <action dev="lofwyr" type="update">
+        last atanion release
+      </action>
+      <action dev="lofwyr" type="update">
+        many refatoring in the tag-names and attribute-names
+      </action>
+      <action dev="lofwyr" type="update">
+        enhanced performance
+      </action>
+    </release>
+
+    <release version="1.0.4" date="2005-02-24">
+      <action dev="lofwyr" type="fix">
+        bugfix: direct input of page or row
+      </action>
+    </release>
+
+    <release version="1.0.3" date="2005-02-23">
+      <action dev="lofwyr" type="update">
+        refator: rename many tags and tag-attributes to have a consitent scheme
+      </action>
+      <action dev="lofwyr" type="update">
+        sheet paging: direct input of page or row
+      </action>
+      <action dev="lofwyr" type="update">
+        make UIForm tranparent for layouting.
+      </action>
+      <action dev="lofwyr" type="update">
+        refactor UISelectMany removed: workaround is no longer needed.
+      </action>
+      <action dev="lofwyr" type="update">
+        refactor Don't everwrite JSF component-types in faces-config.xml to prevent error messages.
+      </action>
+      <action dev="lofwyr" type="update">
+        refactor Color16 removed, will be replaced in later version with enhanced ColorSelect
+      </action>
+      <action dev="lofwyr" type="update">
+        refactor ViewHandlerImpl: using base RI Impl
+      </action>
+      <action dev="lofwyr" type="update">
+        refactor TobagoServletMapping: removed
+      </action>
+    </release>
+
+    <release version="1.0.2" date="2004-12-15">
+      <action dev="lofwyr" type="fix">
+        submit button in IE makes double submit
+      </action>
+      <action dev="lofwyr" type="fix">
+        NullPointerException with unknown browsers
+      </action>
+    </release>
+
+    <release version="1.0.1" date="2004-12-15">
+      <action dev="lofwyr" type="update">
+        eleminate "SNAPSHOT" dependencies
+      </action>
+    </release>
+
+    <release version="1.0.0" date="2004-12-15">
+      <action dev="lofwyr" type="add">
+        first release
+      </action>
+    </release>
+
+</body>
+</document>
+
diff --git a/tobago-3.0.x/src/docbook/resources/basic-controls.png b/tobago-3.0.x/src/docbook/resources/basic-controls.png
new file mode 100644
index 0000000..815230d
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/basic-controls.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/editor-simple.png b/tobago-3.0.x/src/docbook/resources/editor-simple.png
new file mode 100644
index 0000000..eadd808
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/editor-simple.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/editor.png b/tobago-3.0.x/src/docbook/resources/editor.png
new file mode 100644
index 0000000..3f2ab74
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/editor.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/list.png b/tobago-3.0.x/src/docbook/resources/list.png
new file mode 100644
index 0000000..03e2a98
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/list.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/progress.png b/tobago-3.0.x/src/docbook/resources/progress.png
new file mode 100644
index 0000000..4f3e5df
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/progress.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/slider.png b/tobago-3.0.x/src/docbook/resources/slider.png
new file mode 100644
index 0000000..2e7895d
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/slider.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/theme-charlotteville.png b/tobago-3.0.x/src/docbook/resources/theme-charlotteville.png
new file mode 100644
index 0000000..e8db6fb
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/theme-charlotteville.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/theme-richmond.png b/tobago-3.0.x/src/docbook/resources/theme-richmond.png
new file mode 100644
index 0000000..59b2eb5
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/theme-richmond.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/theme-scarborough.png b/tobago-3.0.x/src/docbook/resources/theme-scarborough.png
new file mode 100644
index 0000000..2407578
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/theme-scarborough.png differ
diff --git a/tobago-3.0.x/src/docbook/resources/theme-speyside.png b/tobago-3.0.x/src/docbook/resources/theme-speyside.png
new file mode 100644
index 0000000..317d0c6
Binary files /dev/null and b/tobago-3.0.x/src/docbook/resources/theme-speyside.png differ
diff --git a/tobago-3.0.x/src/docbook/tobago-tutorial.xml b/tobago-3.0.x/src/docbook/tobago-tutorial.xml
new file mode 100644
index 0000000..abd4732
--- /dev/null
+++ b/tobago-3.0.x/src/docbook/tobago-tutorial.xml
@@ -0,0 +1,1515 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!-- XXX check rendering of ulink with content and markup; replace footnotes and literal when appropiate -->
+<!DOCTYPE article PUBLIC
+    "-//OASIS//DTD DocBook XML V4.5//EN"
+    "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
+<article lang="en-US">
+  <title>Apache Tobago Tutorial</title>
+
+  <sect1>
+    <title>Introduction</title>
+
+    <para>Tobago aids developers in creating web applications with a
+    consistent look and feel. Therefore it provides the developer with a
+    collection of comfortable high-level components, which can be positioned
+    with a layout manager. The goal is to approximate the appearance of
+    classical desktop applications. Tobago is based on a strict separation of
+    structure and design. The developer describes the structure of a page and
+    which controls it contains, the representation of the page and its style
+    is handled by Tobago. The developer can customize the design and style
+    through themes. Currently Tobago only contains themes for HTML clients. To
+    achieve output independence, the views should be developed without any
+    HTML, CSS, or JavaScript. A Tobago page normally contains only JSF and
+    Tobago tags. Features, styling and design via HTML, CSS, or JavaScript are
+    handled by the theme.</para>
+
+    <para>The development of Tobago started in 2002. With the introduction of
+    the JSF standard it was decided to base Tobago on JSF. By 2005, Tobago was
+    released as an open-source project and became a sub project of Apache
+    MyFaces in 2006.</para>
+
+    <para>We will be referencing a simple address book application throughout
+    this chapter to demonstrate the various features of Tobago.</para>
+
+    <sect2>
+      <title>Participation</title>
+
+      <para>Tobago is a constantly maturing project with rich potential to
+      fill a unique niche in the MyFaces family — feel free to sign up on the
+      MyFaces mailing lists<footnote><para>See <ulink url="http://myfaces.apache.org/tobago/mail-lists.html"/></para></footnote>
+      or sign up to the JIRA<footnote><para>See <ulink url="http://issues.apache.org/jira/browse/TOBAGO"/></para></footnote> and participate in the
+      process. Additionally, you can also check out the MyFaces project
+      website to find out about future releases.</para>
+    </sect2>
+  </sect1>
+
+  <sect1 id="sec-getting-started">
+    <title>Getting Started</title>
+
+    <para>The Tobago project contains several examples like the demo, the
+    address book and the blank example. The demo example demonstrates many of
+    the important features of Tobago and acts as the online documentation. The
+    address book example is a small self-contained web application. Finally,
+    there is the blank example, which is a minimal Tobago application that can
+    act as a starting point for a new application. The Tobago download page
+    links to the example archive, which contains a precompiled web application
+    archive (WAR) for the blank example and the demo. The source for the blank
+    example can be obtained from the Subversion repository. Checking out the
+    blank example for Tobago is achieved by entering the following
+    command in the shell:</para>
+
+    <programlisting>svn checkout \
+  http://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-example/tobago-example-blank/ \
+  blank</programlisting>
+
+    <para>For building the blank example Java 5 and Maven 2 (at least 2.0.6)
+    are needed. Running Tobago applications in a Java 1.4 environment is
+    supported, too (Tobago 1.0.x). The Tobago distribution contains bytecode transformed
+    jars, which were generated with Retrotranslator.</para>
+
+    <para>A Tobago application is a standard web application and needs a web
+    application descriptor (<filename>WEB-INF/web.xml</filename>). As a JSF application the <literal>web.xml</literal>
+    file has to include a servlet definition for the <classname>FacesServlet</classname> and a
+    corresponding servlet mapping. During development it is convenient to
+    serve the resources for Tobago like images, scripts, and style sheets
+    directly out of the theme jars. To accomplish this, the <filename>web.xml</filename> file needs
+    to contain the definition for the Tobago <classname>ResourceServlet</classname> and the
+    corresponding servlet mapping. For a production environment it is advised
+    to extract the theme resources and let the servlet container or web server
+    serve these resources directly — see <xref linkend="sec-advanced-assembly"/>.</para>
+
+    <para>The JSF specific configuration for Tobago is contained in the
+    <filename>faces-config.xml</filename> file inside the Tobago core jar. To make the
+    configuration available for JSF the <filename>tobago-core.jar</filename> has to be placed into
+    the web application. The Tobago specific configuration is defined in the
+    <filename>WEB-INF/tobago-config.xml</filename> file. A minimal configuration should at least
+    specify the default theme for the Tobago application.</para>
+
+    <programlisting role="XML">&lt;tobago-config&gt;
+  &lt;theme-config&gt;
+    &lt;default-theme&gt;speyside&lt;/default-theme&gt;
+  &lt;/theme-config&gt;
+&lt;/tobago-config&gt;</programlisting>
+
+    <para>A Tobago web application needs to package some libraries. First of
+    all, the Tobago core jar and theme jars should be made available in the
+    application. Some themes depend on each other, for example to be able to
+    use the Speyside theme the Scarborough theme and Standard theme have to be
+    included as well. These dependencies are defined in the
+    <filename>META-INF/tobago-config.xml</filename> files inside the theme jars.</para>
+
+    <para>Tobago depends on several Jakarta Commons libraries:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>commons-beanutils</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-collections</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-digester (only Tobago 1.x)</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-fileupload</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-io</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-lang</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-logging</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Additionally a JSF implementation has to be selected. For MyFaces
+    the following additional libraries have to be included:</para>
+
+    <itemizedlist>
+      <listitem>
+        <para>myfaces-api</para>
+      </listitem>
+
+      <listitem>
+        <para>myfaces-impl</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-codec</para>
+      </listitem>
+
+      <listitem>
+        <para>commons-el</para>
+      </listitem>
+
+      <listitem>
+        <para>jstl</para>
+      </listitem>
+    </itemizedlist>
+
+    <para>Finally, a logging mechanism has to be selected. All Tobago examples
+    use log4j as a default.</para>
+
+    <sect2>
+      <title>Basic Tobago Page</title>
+
+      <para>To use JSP as a rendering technology Tobago provides two tag
+      libraries which contain the definition of available JSP tags — the
+      Tobago core library and the extension library. The tag library
+      definitions (TLD) for these libraries contain documentation for the tags
+      and define the available required and optional attributes. IDEs can
+      leverage this information to help the developer construct JSP
+      pages.</para>
+
+      <para>A basic Tobago page looks like this:</para>
+
+      <programlisting role="XML">&lt;%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %&gt;
+&lt;%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %&gt;
+&lt;%@ taglib uri="http://myfaces.apache.org/tobago/extension" prefix="tx" %&gt;
+&lt;%@ page contentType="text/html;charset=UTF-8" language="java" %&gt;
+&lt;f:view&gt;
+  &lt;tc:page&gt;
+    &lt;f:facet name="layout"&gt;
+      &lt;tc:gridLayout/&gt;
+    &lt;/f:facet&gt;
+    &lt;tc:out value="Hello World"/&gt;
+  &lt;/tc:page&gt;
+&lt;/f:view&gt;</programlisting>
+    </sect2>
+
+    <sect2>
+      <title>Building and Deploying with Maven</title>
+
+      <para>The Tobago project leverages Maven for all build management and
+      Maven is the easiest way to build a web application with Tobago. The
+      project descriptor (<filename>pom.xml</filename>) or project object model (POM) of Tobago
+      defines all necessary dependencies and the Maven repository server and
+      its mirrors provide the appropriate jars. For more information on Maven
+      see the Maven web site<footnote><para>See <ulink url="http://maven.apache.org/"/></para></footnote>
+      and the book <citetitle>Better builds with Maven</citetitle><footnote><para>See <ulink url="http://www.devzuz.com/web/guest/products/resources#BBWM"/></para></footnote>.</para>
+
+      <para>The POM for the blank example specifies the packaging of the
+      project as <literal>"war"</literal>. The dependencies for the web application are managed
+      by the <literal>&lt;dependencies&gt;</literal> element in the POM Maven automatically takes
+      care of the dependencies through its transitivity mechanism. The POM
+      comprises all necessary information needed to compile and package a web
+      application archive. Use the following command in the shell:</para>
+
+      <programlisting>mvn package</programlisting>
+
+      <para>This results in a WAR archive in the target directory, where Maven
+      stores its build artifacts and intermediary files. Moreover Maven can be
+      used to deploy the WAR on an application server as well. The Tobago
+      example POM, which is the parent POM of the blank example, contains the
+      necessary information to deploy a WAR on an embedded Jetty server. By
+      executing</para>
+
+      <para><programlisting>mvn jetty:run-exploded</programlisting></para>
+
+      <para>a Jetty server is started via Maven and the WAR is deployed on
+      this servlet container. The server listens on the port 8080 and the web
+      application can accessed under the URL
+      <literal>http://localhost:8080/tobago-example-blank/</literal>.</para>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Controls</title>
+
+    <para>Tobago makes use of the extensibility of JSF to achieve its
+    decoupling from the rendering tier. It provides its own tag library,
+    components and render kit. Besides the JSP tag library, an alternative
+    rendering technology called Facelets can be used, too. The
+    <emphasis>extension</emphasis> folder
+    in the Tobago repository contains the support library to use Facelets
+    instead of JSP.</para>
+
+    <para>Because of the strict separation between structure and design, it is
+    possible to use an application with different themes. This allows the
+    developer to execute applications that can render different corporate
+    designs for different portals while keeping the view source unchanged.
+    This mechanism is easier than adapting plain CSS in the sense that various
+    stylesheet themes/skins have to be referenced and loaded based on
+    environmental parameters.</para>
+
+    <para>Besides the basic input controls HTML provides, Tobago offers
+    additional high level controls, which a traditional desktop application
+    developers would recognize. These controls will be described in the
+    following sections.</para>
+
+    <para>Tobago also contains a deprecated tree control. The API of this tree
+    control does not really fit to the other controls. But the sandbox already
+    contains a version of the future tree control, which will be introduced
+    in Tobago 1.5.</para>
+
+    <sect2>
+      <title>Basic Controls</title>
+
+      <para>HTML offers a large set of input controls which form the basis of
+      Tobago's controls. This base includes single line text input fields,
+      text areas, labels, radio buttons, check boxes, links, buttons, and so
+      on. The Tobago demo shows these controls in action. A precompiled WAR
+      for the demo is part of the example distribution and the Tobago web site
+      links to a server with a live version. See <xref linkend="fig-basic-controls"/>:</para>
+
+      <para><figure id="fig-basic-controls">
+          <title>Basic controls</title>
+
+          <graphic fileref="resources/basic-controls.png" />
+        </figure></para>
+
+      <sect3>
+        <title>Input Control</title>
+
+        <para>A single line input control can be rendered with the
+        <literal>&lt;tc:in&gt;</literal> tag. The extended version can be accessed with
+        <literal>&lt;tx:in&gt;</literal>. In general the extension library, which is usually
+        referenced by the tx prefix, provides convenience variants of
+        controls. For the <literal>&lt;tc:in&gt;</literal> control the extended version
+        &lt;tx:in&gt; contains boilerplate code for rendering labels. For form
+        like input views nearly every input control has a corresponding label.
+        The label is connected to the input control. If the label is clicked
+        the input control gains focus.</para>
+
+        <programlisting role="XML">&lt;tx:in
+    label="#{bundle.name}"
+    value="#{address.name}"
+    required="false" readonly="false"
+    disabled="false" rendered="true" /&gt;</programlisting>
+
+        <para>The <literal>label</literal> attribute determines the textual description for the
+        control. It is laid out with a grid layout manager. The theme
+        specifies the default label width, but it can be overwritten with the
+        <literal>labelWidth</literal> attribute. If the label contains an underscore character
+        the following character will become an access key. This is visualized
+        by underlining the access key character. If the access key is pressed
+        together with the <keycap>Alt</keycap> key the corresponding input field gains focus.
+        The <literal>value</literal> attribute contains the content of the input control. The
+        <literal>required</literal> attribute controls validation and allows the theme to render
+        a special marker for required input. The required feature is rendered
+        as a small box with a check mark inside the input field to inform the
+        user to enter information into this field. Read-only controls do not
+        allow the user to modify the value of the input control. A disabled
+        control cannot gain focus, the label is rendered in a fashion to
+        highlight the disabled nature of the input control and the user cannot
+        copy content from the input control. The <literal>rendered</literal> attribute manages if
+        the control is rendered at all. If the control is not rendered the
+        layout manager can distribute the resulting space to other controls.
+        For password fields the respective attribute can be set to <constant>true</constant>. If a
+        page contains multiple input controls the first control will be
+        focused by default. This behavior can be overwritten by setting the
+        <literal>focus</literal> attribute of an input control to <constant>true</constant>.</para>
+
+        <para><figure id="fig-editor">
+            <title>Address editor</title>
+
+            <graphic fileref="resources/editor.png" />
+          </figure></para>
+      </sect3>
+
+      <sect3>
+        <title>Commands</title>
+
+        <para>Tobago supports different ways to use commands. The basic
+        versions are <literal>&lt;tc:button&gt;</literal> and <literal>&lt;tc:link&gt;</literal>; others include
+        toolbars and menus, which are described in later sections.</para>
+
+        <programlisting role="XML">&lt;tc:button label="Delete" action="#{controller.delete}"
+    image="image/delete.png" defaultCommand="false"&gt;
+  &lt;f:facet name="confirmation"&gt;
+    &lt;tc:out value="Do you want to delete it?" /&gt;
+  &lt;/f:facet&gt;
+&lt;/tc:button&gt;</programlisting>
+
+        <para>The <literal>label</literal> attribute defines the text on the button. The <literal>action</literal>
+        attribute points to a method which is executed if the button is
+        pressed. By means of the <literal>image</literal> attribute the button can be decorated
+        with an icon. The image can be placed relatively to the root of the
+        web application or the resource manager can be used to locate the
+        image — see <xref linkend="sec-resource-management"/>. The <literal>&lt;tc:button&gt;</literal>
+        control supports the confirmation facet, which generates a message
+        dialog. Only if the confirmation question is answered with OK, the
+        action is executed. If the <literal>defaultCommand</literal> attribute is set to true the
+        button will be activated as soon as the <keycap>Enter</keycap> key is pressed.</para>
+
+        <para>Tobago includes a double request prevention mechanism. After a
+        button or link is clicked in the client, the page is blocked to avoid
+        duplicate clicks. If the server request takes longer than expected a
+        transitioning effect is shown. First the page is faded out and later a
+        progress animation is presented. To turn this effect off the
+        <literal>transition</literal> attribute can be set to <constant>false</constant>.</para>
+
+        <para>A generic <literal>&lt;tc:command&gt;</literal> control can be used for event
+        facets for select controls like <literal>&lt;tc:selectBooleanCheckbox&gt;</literal>,
+        <literal>&lt;tc:selectOneRadio&gt;</literal>, <literal>&lt;tc:selectManyCheckbox&gt;</literal>, and
+        <literal>&lt;tc:selectOneChoice&gt;</literal>. This is how the theme changing in the
+        footer of the address book example is realized. If a new theme is
+        selected, a change event is triggered, the page is submitted, and the
+        action of the <literal>&lt;tc:command&gt;</literal> inside the <literal>change</literal> facet is called:</para>
+
+        <programlisting role="XML">&lt;tx:selectOneChoice label="#{bundle.footerTheme}" value="#{controller.theme}"&gt;
+  &lt;f:selectItems value="#{controller.themeItems}" /&gt;
+  &lt;f:facet name="change"&gt;
+    &lt;tc:command action="#{controller.themeChanged}"/&gt;
+  &lt;/f:facet&gt;
+&lt;/tx:selectOneChoice&gt;</programlisting>
+
+        <para>Besides the change event select controls also support the click
+        event. The click event is triggered if someone clicks on the control.
+        The actual value does not need to change to trigger the event.</para>
+      </sect3>
+    </sect2>
+
+    <sect2>
+      <title>Sheet Control</title>
+
+      <para>The <literal>&lt;tc:sheet&gt;</literal> component allows to display tabular data. The
+      address book uses it to provide an overview of all stored
+      addresses.</para>
+
+      <programlisting role="XML">&lt;tc:sheet columns="1*;1*;1*" value="#{controller.currentAddressList}"
+    var="address" state="#{controller.selectedAddresses}"
+    sortActionListener="#{controller.sheetSorter}" rows="25"
+    showRowRange="left" showPageRange="right" showDirectLinks="center"&gt;
+  &lt;tc:column id="firstName" label="#{bundle.listFirstName}" sortable="true"
+      rendered="#{controller.renderFirstName}"&gt;
+    &lt;tc:out value="#{address.firstName}" /&gt;
+  &lt;/tc:column&gt;
+  &lt;tc:column id="lastName" label="#{bundle.listLastName}" sortable="true"
+      rendered="#{controller.renderLastName}"&gt;
+    &lt;tc:out value="#{address.lastName}" /&gt;
+  &lt;/tc:column&gt;
+  &lt;tc:column id="dayOfBirth" label="Birthday" sortable="true"
+      rendered="#{controller.renderDayOfBirth}"&gt;
+    &lt;tc:out value="#{address.dayOfBirth}"&gt;
+      &lt;f:convertDateTime pattern="#{bundle.editorDatePattern}" /&gt;
+    &lt;/tc:out&gt;
+  &lt;/tc:column&gt;
+&lt;/tc:sheet&gt;</programlisting>
+
+      <para>The value attribute links to a list model in the controller
+      providing the data for the sheet. The <literal>&lt;tc:sheet&gt;</literal> contains three
+      <literal>&lt;tc:column&gt;</literal> tags which describe the columns of the sheet. The
+      label of the column is rendered as a header cell. The <literal>var</literal> attribute
+      inside <literal>&lt;tc:sheet&gt;</literal> defines a local variable <literal>address</literal>, which refers
+      to a row in the data model and can be used in the definition of the
+      columns.</para>
+
+      <para><figure id="fig-list">
+          <title>Address list</title>
+
+          <graphic fileref="resources/list.png" />
+        </figure></para>
+
+      <para>In the example, each column uses a <literal>&lt;tc:out&gt;</literal> tag to render
+      the data for the sheet cell by accessing the appropriate property of the
+      row object. Instead of <literal>&lt;tc:out&gt;</literal> arbitrary input controls can be
+      used like <literal>&lt;tc:in&gt;</literal>, <literal>&lt;tc:selectBooleanCheckbox&gt;</literal>, or
+      <literal>&lt;tc:selectOneChoice&gt;</literal>.</para>
+
+      <para>The various attributes of the sheet which start with 'show'
+      configure the navigational elements of the sheet — <literal>showDirectLinks</literal> for
+      example allows the user to directly jump to the desired page of the
+      sheet.</para>
+
+      <para>The <literal>state</literal> attribute refers to a <classname>SheetState</classname> object. Tobago binds
+      information about the state of the sheet to this object — like which
+      rows are selected. This allows the developer to react on the selection
+      inside the business logic. In the address book example there is a
+      toolbar above the sheet. The toolbar contains a delete action among
+      others. This delete action is dependent on the selected rows in the
+      sheet. The attribute <literal>selectable</literal> of the sheet controls the selection mode
+      for the sheet. Possible values are <literal>none</literal>, <literal>single</literal>, and <literal>multi</literal>. The default
+      value is <literal>multi</literal> and allows multiple rows to be selected. The following
+      code fragment show the method bound to the delete button and describes
+      how to access the selected rows:</para>
+
+      <programlisting role="JAVA">public String deleteAddresses() {
+  List&lt;Integer&gt; selection = selectedAddresses.getSelectedRows();
+  if (selection.size() &lt; 1) {
+    FacesMessage error 
+        = new FacesMessage("Please select at least one address.");
+    FacesContext.getCurrentInstance().addMessage(null, error);
+    return null;
+  }
+  for (int i = selection.size() - 1; i &gt;= 0; i--) {
+    Address address = currentAddressList.get(selection.get(i));
+    addressDao.removeAddress(address);
+  }
+  // ...
+  return OUTCOME_LIST;
+}</programlisting>
+
+      <para>The <literal>sortable</literal> attribute of the <literal>&lt;tc:column&gt;</literal> activates sorting
+      for the related column. If the data for the sheet is a List or an array
+      the data can be sorted implicitly. The <literal>sortActionListener</literal> attribute
+      allows implementation of sorting in the business logic. The respective
+      method binding has to point to a public action listener method which
+      takes an <classname>ActionEvent</classname> as a parameter and returns <literal>void</literal>. The method will
+      receive a <classname>SortActionEvent</classname>, which denotes the column triggering the sort
+      event. However, information about the sort direction is contained in the
+      <classname>SheetState</classname>.</para>
+    </sect2>
+
+    <sect2>
+      <title>Tab Group Control</title>
+
+      <para>The <literal>&lt;tc:tabGroup&gt;</literal> control renders different content on the
+      same area of the view via tab panels. The switching behavior of the
+      panels can be controlled with the <literal>switchType</literal> attribute. The panels can
+      be switched on the client or the server. If the switching is performed
+      on the server, Tobago can be instructed to only partially exchange the
+      content of the page making use of Ajax. If the switching is done on the
+      client it is faster, but the content of the page is bigger, because the
+      rendering information of all tab panels has to be transferred to the
+      client at once.</para>
+
+      <programlisting role="XML">&lt;tc:tabGroup switchType="reloadTab" immediate="true"&gt;
+  &lt;tc:tab label="#{bundle.editorTabPersonal}"&gt;
+    &lt;jsp:include page="tab/personal.jsp"/&gt;
+  &lt;/tc:tab&gt;
+
+  &lt;tc:tab label="#{bundle.editorTabBusiness}" rendered="#{!controller.simple}"&gt;
+    &lt;jsp:include page="tab/business.jsp"/&gt;
+  &lt;/tc:tab&gt;
+
+  &lt;tc:tab label="#{bundle.editorTabMisc}" rendered="#{!controller.simple}"&gt;
+    &lt;jsp:include page="tab/misc.jsp"/&gt;
+  &lt;/tc:tab&gt;
+&lt;/tc:tabGroup&gt;</programlisting>
+
+      <para>In the example application, two of the tab panels are only
+      rendered if a certain condition is met in the controller. These
+      particular tab panels are only rendered if the application is in the
+      <emphasis>expert</emphasis> mode.</para>
+    </sect2>
+
+    <sect2>
+      <title>Menu Control</title>
+
+      <para>To mimic the appearance of a desktop application it is common to
+      place a menu bar at the top of the page. This can be done with the
+      <literal>&lt;tc:menuBar&gt;</literal> tag inside the <literal>menuBar</literal> facet of the <literal>&lt;tc:page&gt;</literal>.
+      A menu bar can contain <literal>&lt;tc:menu&gt;</literal> tags, which can be nested to
+      produce sub menus. Actions can be bound with method bindings to
+      <literal>&lt;tc:menuCommand&gt;</literal> tags. A menu item can be disabled and can
+      encapsulate icons. An underscore in the label marks the following
+      character as an access key, which can be activated together with the <keycap>Alt</keycap> key.</para>
+
+      <para>In the address book example the settings menu contains single
+      selections created by <literal>&lt;tx:menuRadio&gt;</literal> to choose the current theme
+      and language. Additionally it demonstrates how to use a check box menu
+      item <literal>&lt;tx:menuCheckbox&gt;</literal> to change the mode of the
+      application.</para>
+
+      <programlisting role="XML">&lt;tc:menuBar id="menuBar"&gt;
+  &lt;tc:menu label="_File"&gt;
+    &lt;tc:menuCommand label="_New" action="#{controller.createAddress}" image
+        ="image/org/tango-project/tango-icon-theme/16x16/actions/contact-new.png"/&gt;
+    &lt;tc:menuCommand label="_Add Dummy Addresses"
+        action="#{controller.addDummyAddresses}"/&gt;
+    &lt;tc:menuSeparator/&gt;
+    &lt;tc:menuCommand label="_Logout" image
+        ="image/org/tango-project/tango-icon-theme/16x16/actions/system-log-out.png"/&gt;
+  &lt;/tc:menu&gt;
+
+  &lt;tc:menu label="_Settings"&gt;
+    ...
+    &lt;tc:menu label="_Theme"&gt;
+      &lt;tx:menuRadio action="#{controller.themeChanged}"
+          value="#{controller.theme}"&gt;
+        &lt;f:selectItems value="#{controller.themeItems}"/&gt;
+      &lt;/tx:menuRadio&gt;
+    &lt;/tc:menu&gt;
+    &lt;tx:menuCheckbox label="Simple _Mode" value="#{controller.simple}"/&gt;
+  &lt;/tc:menu&gt;
+  ...
+&lt;/tc:menuBar&gt;</programlisting>
+    </sect2>
+
+    <sect2>
+      <title>Tool Bar Control</title>
+
+      <para>The <literal>&lt;tc:toolBar&gt;</literal> tag renders a group of buttons. The tool
+      bar can be configured to render a textual description of the action or
+      an icon in different standard sizes. The buttons are created with the
+      <literal>&lt;tc:toolBarCommand&gt;</literal> tag, which is a slightly limited version of
+      the standard button tag.</para>
+
+      <programlisting role="XML">&lt;tc:toolBar iconSize="big"&gt;
+  &lt;tc:toolBarCommand label="#{bundle.toolbarAddressList}" 
+      action="#{controller.search}" immediate="true" image=
+ "image/org/tango-project/tango-icon-theme/32x32/mimetypes/x-office-address-book.png"
+      disabled="#{facesContext.viewRoot.viewId == '/application/list.jsp'}"/&gt;
+  ...
+&lt;/tc:toolBar&gt;</programlisting>
+
+      <para>In the address book example the first toolbar button navigates to
+      the address list. If the address list is already the current view the
+      button is disabled. There is a naming convention to provide disabled
+      versions for image resources by adding an additional <literal>Disabled</literal> before the
+      file extension. The disabled version has to reside in the same folder as
+      the original image. In the example the resource manager can find a black
+      and white icon <filename>x-office-address-bookDisabled.png</filename> as a disabled version
+      of the normal address book icon.</para>
+    </sect2>
+
+    <sect2>
+      <title>Popups</title>
+
+      <para>A popup is a small modal dialog, which is displayed in the context
+      of the current page. A general use case for a popup is entering new data
+      and confirming or canceling the new data. Popups can be activated by
+      adding a <literal>popup</literal> facet to commands. Alternatively a popup can be activated
+      programmatically by setting the <literal>rendered</literal> attribute to <constant>true</constant>. In this way
+      you can use a popup as a message box.</para>
+
+      <para>In the address book example the displayed columns for the address
+      list can be controlled via a popup. This popup is bound to a button in
+      the toolbar for the sheet.</para>
+
+      <programlisting role="XML">&lt;tc:button label="Open Popup"&gt;
+  &lt;f:facet name="popup"&gt;
+    &lt;tc:popup width="300" height="270"&gt;
+      &lt;tc:box label="Popup Title"&gt;
+        ...
+        &lt;tc:panel&gt;
+          &lt;f:facet name="layout"&gt;
+            &lt;tc:gridLayout columns="*;fixed;fixed"/&gt;
+          &lt;/f:facet&gt;
+          &lt;tc:panel/&gt;
+          &lt;tc:button label="OK"&gt;
+            <emphasis role="bold">&lt;tc:attribute name="popupClose" value="afterSubmit"/&gt;</emphasis>
+          &lt;/tc:button&gt;
+          &lt;tc:button label="Cancel"&gt;
+            <emphasis role="bold">&lt;tc:attribute name="popupClose" value="immediate"/&gt;</emphasis>
+          &lt;/tc:button&gt;
+        &lt;/tc:panel&gt;
+      &lt;/tc:box&gt;
+    &lt;/tc:popup&gt;
+  &lt;/f:facet&gt;
+&lt;/tc:button&gt;</programlisting>
+
+      <para>The typical semantics of the <emphasis>confirmation</emphasis>
+        and <emphasis>cancel</emphasis> button can be
+      controlled via a <literal>&lt;tc:attribute&gt;</literal> with the name <literal>popupClose</literal>. This
+      attribute can have two different values: <literal>afterSubmit</literal> or <literal>immediate</literal>. Both
+      buttons close the popup, but only the <literal>afterSubmit</literal> variant stores the
+      entered data into the model.</para>
+    </sect2>
+
+    <sect2>
+      <title>File Upload</title>
+
+      <para>A file select control can be created with <literal>&lt;tc:file&gt;</literal>. The
+      uploaded file is stored inside a <classname>FileItem</classname> object bound to the value
+      attribute. The class <classname>FileItem</classname> is provided by <literal>commons-fileupload</literal>.</para>
+
+      <para>The address book allows the user to store photographs associated
+      with the contacts. The user can click on an empty image placeholder to
+      open a popup with the file select control which is created by the
+      following code fragment:</para>
+
+      <programlisting role="XML">&lt;tc:file value="#{controller.uploadedFile}" required="true"&gt;
+  &lt;tc:validateFileItem contentType="image/*"/&gt;
+&lt;/tc:file&gt;</programlisting>
+
+      <para>With the validator <literal>&lt;tc:validateFileItem&gt;</literal> the content type or
+      maximum size of the uploaded file can be restricted. For security
+      reasons the style of an HTML file select control (input field of type
+      <literal>file</literal>) can only be customized in a very limited way. Therefore the input
+      control for the file name and the upload button may not optimally fit to
+      the theme.</para>
+
+      <para>To handle multipart form data requests from the browser either the
+      <classname>TobagoMultipartFormdataFilter</classname> servlet filter has to be configured in the
+      <filename>web.xml</filename> or the <filename>tobago-fileupload.jar</filename> has to be added to the classpath.
+      The address book demo uses the latter approach, which is based on a
+      <classname>FacesContextFactory</classname> defined in the included <filename>faces-config.xml</filename> of the jar.
+      The context factory can be configured with two different
+      <literal>&lt;env-entry&gt;</literal> tags in the <filename>web.xml</filename> to control maximum upload limit
+      and the directory for uploaded files. See the Javadoc of
+      <classname>FileUploadFacesContextFactoryImpl</classname> for more information.</para>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Layout Management</title>
+
+    <para>The placement of components on a page is done with the help of a
+    layout manager. The functionality of a layout manager is similar to those
+    found in Swing. The standard layout manager for Tobago is
+    <literal>&lt;tc:gridLayout&gt;</literal>. It can be bound to a container tag with a layout
+    facet.</para>
+
+    <para>The grid layout manager divides the area of the page into a
+    rectangular grid. This grid can be controlled with the <literal>rows</literal> and <literal>columns</literal>
+    attributes of the <literal>&lt;tc:gridLayout&gt;</literal> tag. The syntax is similar to the
+    multi-length notation known from HTML<footnote><para>See <ulink url="http://www.w3.org/TR/html401/types.html#type-multi-length"/></para></footnote> and consists of a semicolon
+    separated list of layout tokens.</para>
+
+    <para>A layout token may be an absolute length in pixels like 100px, a
+    percentage length like 50%, a relative length like 2* or * as a shorthand
+    for 1*, or the value <literal>fixed</literal>. Relative lengths are served by the layout manager
+    from the remaining available space, which is distributed proportionally
+    based on the number before the *.</para>
+
+    <para>If the layout manager has 400 pixels to lay out the columns with the
+    following layout tokens 2*;*;100px, it first claims 100px for the third
+    column and distributes the remaining 300 pixels in the ratio 2:1, ending
+    up in 200 pixel for the first column and 100 pixels for the second column.
+    The layout token <literal>fixed</literal> instructs the layout manager to take the required
+    pixel size of the contained control. A <literal>&lt;tx:in&gt;</literal> control normally has
+    a fixed height. To place multiple <literal>&lt;tx:in&gt;</literal> controls one below the
+    other without superfluous spacing the layout manager can be instructed
+    with <literal>fixed</literal> layout tokens to use exactly the required vertical space for a
+    <literal>&lt;tx:in&gt;</literal>. For a more concrete example see the following code fragment
+    based on the editor view of the address book:</para>
+
+    <programlisting role="XML">&lt;tc:panel&gt;
+  &lt;f:facet name="layout"&gt;
+    &lt;tc:gridLayout columns="*" rows="fixed;fixed;fixed;*"/&gt;
+  &lt;/f:facet&gt;
+  &lt;tf:in ... /&gt;
+  &lt;tf:in ... /&gt;
+  &lt;tf:in rendered="#{! controller.simple}" ... /&gt;
+  &lt;tf:textarea ... /&gt;
+&lt;/tc:panel&gt;</programlisting>
+
+    <para>The grid consists of one column and four rows. The first three rows
+    use a fixed height which is implied by the theme and contained controls.
+    The fourth row takes the remaining vertical space.</para>
+
+    <para>One of the main reasons to use a layout manager is its ability to
+    optimally manage the available space. The layout manager knows, for
+    example, if controls have a fixed height and which can grow if there is
+    enough space.</para>
+
+    <para>Since the layout manager is targeted specifically at JSF it can
+    flexibly react on the <literal>rendered</literal> attribute of components. If the address
+    book application is in simple mode some of the components are not
+    rendered. The layout manager automatically distributes the newly available
+    space to the remaining dynamic components, which are laid out with
+    relative or percentage lengths.</para>
+
+    <para>If a control should utilize multiple adjacent grid cells, it can be
+    wrapped with a <literal>&lt;tc:cell&gt;</literal> tag. With the <literal>spanX</literal> and <literal>spanY</literal> attributes of
+    a <literal>&lt;tc:cell&gt;</literal> control the layout manager can be instructed to make the
+    contained control span multiple cells in X and Y direction.</para>
+
+    <para><figure id="fig-editor-simple">
+        <title>Address editor in simple mode</title>
+
+        <graphic fileref="resources/editor-simple.png" />
+      </figure></para>
+  </sect1>
+
+  <sect1>
+    <title>Themes</title>
+
+    <para>Tobago allows the developer to specify the structure of a page.
+    Additionally, the look of a page is controlled by the selected theme. A
+    theme defines the colors, dimensions, behavior, and graphics of controls.
+    Tobago comes with a selection of themes. These are Scarborough, Speyside,
+    Charlotteville, and Richmond — named after settlements on Tobago.
+    Scarborough is the basic theme which tries to directly rely on the
+    standard features of HTML. Speyside is the main theme, where most
+    development focus is targeted at. You will want to use this theme to start
+    a new web application with. The remaining themes Charlotteville and
+    Richmond are mainly variations of Speyside.</para>
+
+    <informaltable frame="none" colsep="0" rowsep="0">
+      <tgroup cols="2">
+        <colspec colname="c1" colwidth="1*"/>
+        <colspec colname="c2" colwidth="1*"/>        
+        <tbody>
+          <row>
+            <entry><para><figure id="fig-theme-speyside">
+                <title>Theme Speyside</title>
+
+                <graphic fileref="resources/theme-speyside.png" />
+              </figure></para></entry>
+
+            <entry><para><figure id="fig-theme-richmond">
+                <title>Theme Richmond</title>
+
+                <graphic fileref="resources/theme-richmond.png" />
+              </figure></para></entry>
+          </row>
+
+          <row>
+            <entry><para><figure id="fig-theme-charlotteville">
+                <title>Theme Charlotteville</title>
+
+                <graphic fileref="resources/theme-charlotteville.png" />
+              </figure></para></entry>
+
+            <entry><para><figure id="fig-theme-scarborough">
+                <title>Theme Scarborough</title>
+
+                <graphic fileref="resources/theme-scarborough.png" />
+              </figure></para></entry>
+          </row>
+        </tbody>
+      </tgroup>
+    </informaltable>
+
+    <para>Themes can be used to make an application follow the corporate
+    design of a company or give the user the ability to change the look and
+    feel of an application to their preferences. The address book example
+    demonstrates how to make the theme selectable by the user. A select box
+    displays the available themes, which are configured in the
+    <filename>tobago-config.xml</filename> file, and a button triggers an action in the controller
+    to set the theme in the Tobago <classname>ClientProperties</classname> object:</para>
+
+    <programlisting role="JAVA">public String themeChanged() {
+  FacesContext facesContext = FacesContext.getCurrentInstance();
+  ClientProperties client 
+      = VariableResolverUtil.resolveClientProperties(facesContext);
+  client.setTheme(theme);
+  return null;
+}</programlisting>
+
+    <sect2 id="sec-resource-management">
+      <title>Resource Management</title>
+
+      <para>For Tobago, resources are images, style sheets, scripts, and
+      string resources. These resources can be dependent on the locale,
+      browser, or the theme. The resource manager collects all resource
+      locations. When a resource is requested, the resource manager determines
+      the inclusion order. A resource can be available in different themes and
+      multiple locales. The resource manager first looks under the selected
+      theme with the used browser and locale. If the resource is not found,
+      the fallback locale is used to continue the search. After all fallback
+      locales are examined the fallback for the browser is used and the
+      locales are searched again. After all fallback browsers are searched the
+      fallback for the theme is used and the search starts again with the
+      locales until all fallback themes are processed. The result is cached
+      for later reuse.</para>
+
+      <para>For resources such as images, the resource manager stops with the
+      first match. For style sheets and scripts the resource manager returns a
+      list of resources in the order they were found. This establishes a
+      powerful defaulting mechanism.</para>
+
+      <para>By relying on the resource manager the developer can provide
+      localized images with different text values for a button. The locale of
+      the view is used to determine the correct language version of the image.
+      The resource manager supports the XML format for property files, easing
+      the use of special characters in string resources. The evaluation of the
+      theme in inclusion order can be used to support different corporate
+      wordings. If each client has its own theme string resources for the
+      different themes can arrange the words in different ways — for example:
+      email, e-mail, or eMail.</para>
+
+      <para>In the <filename>tobago-config.xml</filename> file, additional paths can be specified
+      for inclusion by the resource manager. In this way you can add your own
+      resources or even overwrite or extend existing resources. But changing
+      existing themes this way may result in compatibility issues when
+      switching to a newer version of Tobago, since the theme files are not
+      stable yet and do not count as an official external API.</para>
+
+      <programlisting role="XML">&lt;tobago-config&gt;
+  &lt;theme-config&gt;
+    &lt;default-theme&gt;speyside&lt;/default-theme&gt;
+  &lt;/theme-config&gt;
+  <emphasis role="bold">&lt;resource-dir&gt;tobago-resource&lt;/resource-dir&gt;</emphasis>
+&lt;/tobago-config&gt;</programlisting>
+
+      <para>The resource directory denotes a folder inside the WAR relative to
+      the root. Paths for resources have to follow this pattern:</para>
+
+      <programlisting>&lt;content-type&gt;/&lt;theme&gt;/&lt;browser&gt;/&lt;directory&gt;/&lt;resource-name&gt;(_&lt;locale&gt;)?.&lt;extension&gt;</programlisting>
+
+      <para>Currently only <literal>html</literal> is supported as a content type, although the
+      sandbox contains the beginnings for WML support. For the address book
+      example there are two variants of an empty portrait with instructions
+      how to upload a real portrait.</para>
+
+      <programlisting>tobago-resource/html/standard/standard/image/empty-portrait.png
+tobago-resource/html/standard/standard/image/empty-portrait_de.png</programlisting>
+
+      <para>The first image is the default image with instructions in English.
+      In the second image the instructions are localized in German. The first
+      <literal>standard</literal> in the path denotes the fallback theme and the second <literal>standard</literal>
+      represents the fallback browser. The <literal>directory</literal> part in the pattern
+      stands for an arbitrary sub-path — in this example for the folder
+      <literal>image</literal>.</para>
+    </sect2>
+
+    <sect2>
+      <title>Adding Markup</title>
+
+      <para>Several controls like <literal>&lt;tc:in&gt;</literal>, <literal>&lt;tc:panel&gt;</literal>, or
+      <literal>&lt;tc:column&gt;</literal> support the markup attribute. It allows the developer
+      to apply logical styles to a control. Which markup values are supported
+      is defined per theme in the <filename>theme-config.xml</filename> file. If a theme does not
+      define supported markup for a renderer, it inherits the markup from the
+      fallback theme. The Standard theme defines <literal>number</literal> for <literal>&lt;tc:in&gt;</literal> and
+      <literal>&lt;tc:out&gt;</literal>, and <literal>strong</literal> and <literal>deleted</literal> for <literal>&lt;tc:out&gt;</literal>. The markup
+      <literal>number</literal> is usually used to format numbers right aligned, <literal>strong</literal> is used
+      to emphasize content, and <literal>deleted</literal> marks text as no longer available
+      normally by crossing it out. The visual representation of markup is up
+      to the theme and therefore it will fit to the overall look and feel of
+      the theme.</para>
+
+      <para>To add new markup you can write your own theme. Choose the theme
+      you want to extend and specify the selected theme as fallback theme. The
+      Example theme extends Speyside and adds markup for columns.</para>
+
+      <programlisting role="XML">&lt;tobago-theme&gt;
+  &lt;name&gt;example&lt;/name&gt;
+  &lt;resource-path&gt;org/apache/myfaces/tobago/renderkit&lt;/resource-path&gt;
+  <emphasis role="bold">&lt;fallback&gt;speyside&lt;/fallback&gt;</emphasis>
+  &lt;renderers&gt;
+    &lt;renderer&gt;
+      <emphasis role="bold">&lt;name&gt;Column&lt;/name&gt;
+      &lt;supported-markup&gt;
+        &lt;markup&gt;new&lt;/markup&gt;
+      &lt;/supported-markup&gt;</emphasis>
+    &lt;/renderer&gt;
+  &lt;/renderers&gt;
+&lt;/tobago-theme&gt;</programlisting>
+
+      <para>To realize the visualization of the markup Tobago will add certain
+      CSS style classes into the generated HTML for the marked control. The
+      theme has to provide the styling information. The style class name
+      results from the following naming rule "tobago-" +
+      <literal>rendererName.toLower()</literal> + "-markup-" + <literal>markupName</literal>:</para>
+
+      <programlisting>.tobago-sheet-cell-markup-new {
+  background-color: yellow;
+}</programlisting>
+
+      <para>For the Example theme it was decided to render a new column (sheet-cell) with a
+      yellow background.</para>
+
+      <para>The address book example uses a different way to add markup. In
+      this case three markup values — <literal>ok</literal>, <literal>warn</literal>, and <literal>error</literal> — are defined for
+      the <literal>&lt;tc:progress&gt;</literal> control directly in the <filename>tobago-config.xml</filename> file.
+      The administration area contains a progress bar to visualize the memory
+      utilization of the virtual machine. Depending on the percentage value of
+      the memory usage the business logic assigns different markup values for
+      the progress bar to classify the state of the memory utilization.</para>
+
+      <para><figure id="fig-progress">
+          <title>Progress control with markup</title>
+
+          <graphic fileref="resources/progress.png" />
+        </figure></para>
+
+      <para>The resource directory contains style sheets for visualizing the
+      markup values as different background colors — green for <literal>ok</literal>, yellow for
+      <literal>warn</literal>, and red for <literal>error</literal>. The Speyside theme for example is extended by
+      the <filename>html/speyside/standard/style/style.css</filename> file.</para>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Creating your own Tobago Control</title>
+
+    <para>The ideal place to start when you want to create your own Tobago
+    control is the sandbox. To access the sandbox you have to check it
+    out:</para>
+
+    <programlisting>svn checkout \ 
+    http://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-sandbox \
+    tobago-sandbox</programlisting>
+
+    <para>Alternatively if you have checked out the complete Tobago source
+    tree you can find the sandbox directory right under the root directory. In
+    this section we will create an HTML control in the sandbox as an example.
+    The new control will be a slider for entering integer numbers.</para>
+
+    <para>This control consists of a slider bar with an attached number input
+    field. If you move the slider the number field is changed accordingly and
+    vice versa. <xref linkend="fig-slider"/> shows a preview of the control. You can find the
+    complete code in the Tobago sandbox.</para>
+
+    <para><figure id="fig-slider">
+        <title>Slider control for entering numbers</title>
+
+        <graphic fileref="resources/slider.png" />
+      </figure></para>
+
+    <sect2>
+      <title>The UI Component</title>
+
+      <para>We are starting with the user interface component of the control
+      and will name it:
+      <classname>UINumberSlider</classname><footnote><para>See <ulink url="http://svn.apache.org/viewvc/myfaces/tobago/trunk/sandbox/src/main/java/org/apache/myfaces/tobago/component/UINumberSlider.java?view=markup"/></para></footnote>. Like all JSF
+      components, Tobago components must extend
+      <classname>UIComponent</classname><footnote><para>See <ulink url="http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIComponent.html"/></para></footnote>. Because we want to create an input
+      component we can extend <classname>UIInput</classname><footnote><para>See <ulink url="http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIInput.html"/></para></footnote> which is a (non
+      direct) subclass of <classname>UIComponent</classname>. The class <classname>UIInput</classname>
+      is already an implementation of
+      <classname>EditableValueHolder</classname><footnote><para>See <ulink url="http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/api/javax/faces/component/EditableValueHolder.html"/></para></footnote> which saves us a lot of
+      work.</para>
+
+      <para>The JSF runtime environment needs the component type as an
+      identifier for creating instances of components. Tobago components need
+      to store this information in the component itself in the constant
+      <constant>COMPONENT_TYPE</constant>. This constant is processed by the Tobago annotation
+      visitor that is used in the build process to create the <filename>faces-config.xml</filename>
+      file.</para>
+
+      <para>We also implement some additional properties into our component:
+      <literal>min</literal>, <literal>max</literal>, <literal>readonly</literal> and <literal>disabled</literal>. The property <literal>min</literal> specifies the smallest
+      and the property <literal>max</literal> the largest number that can be entered. With the
+      property <literal>readonly</literal> set the user cannot modify the value of the slider.
+      The same is true for the property <literal>disabled</literal>. But in this case the
+      complete control appears deactivated. All properties should be value
+      binding enabled which makes their getters a little bit more complicated.
+      To ensure that our component state is saved between requests we have to
+      override the state holder methods of <classname>UIInput</classname>.</para>
+
+      <para>The following code shows some parts of our component class:</para>
+
+      <programlisting role="JAVA">public class UINumberSlider extends javax.faces.component.UIInput {
+
+  public static final String COMPONENT_TYPE
+      = "org.apache.myfaces.tobago.NumberSlider";
+
+  private Boolean readonly;
+  private Boolean disabled;
+  private Integer min;
+  private Integer max;
+
+  public Boolean isReadonly() {
+    if (readonly != null) {
+      return readonly;
+    }
+    ValueBinding vb = getValueBinding(Attributes.READONLY);
+    if (vb == null) {
+      return false;
+    } else {
+      return (Boolean.TRUE.equals(vb.getValue(getFacesContext())));
+    }
+  }
+
+  public void setReadonly(Boolean readonly) {
+    this.readonly = readonly;
+  }
+  ...
+  public void restoreState(FacesContext context, Object state) {...}
+  public Object saveState(FacesContext context) {...}
+}</programlisting>
+    </sect2>
+
+    <sect2>
+      <title>The Renderer</title>
+
+      <para>There are two ways in JSF to render a component. The first one is
+      to implement the encoding and decoding between UI component and the view
+      in the UI component directly. This is called the direct implementation
+      programming model. The second method is to delegate the task to an
+      appropriate renderer which is called the delegating programming model.
+      The delegated programming model keeps your components independent from
+      the view technology and is preferred for Tobago components.</para>
+
+      <para>A renderer in JSF must be a subclass of type
+      <classname>Renderer</classname><footnote><para>See <ulink url="http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/api/javax/faces/render/Renderer.html"/></para></footnote>. For Tobago components this is different:
+      their renderers must also implement the interface
+      <classname>LayoutInformationProvider</classname><footnote><para>See <ulink url="http://myfaces.apache.org/tobago/apidocs/org/apache/myfaces/tobago/renderkit/LayoutInformationProvider.html"/></para></footnote> to get the
+      renderer to work with the Tobago layout management. With this interface
+      Tobago renderers provide the layout manager with certain information
+      about the sizing of the component that is rendered. The required methods
+      have a default implementation in the class
+      <classname>LayoutableRendererBase</classname><footnote><para>See <ulink url="http://myfaces.apache.org/tobago/apidocs/org/apache/myfaces/tobago/renderkit/LayoutableRendererBase.html"/></para></footnote> which uses properties
+      that are provided by the theme configuration of the used theme
+      (<filename>tobago-theme-config.properties</filename>). We name our renderer
+      <classname>NumberSliderRenderer</classname> and extend from <classname>LayoutableRendererBase</classname>. Following the
+      Tobago naming convention the renderer must end with "Renderer".</para>
+
+      <para>When using the <classname>LayoutableRendererBase</classname> the theme configuration is a good
+      place to provide the information needed for the layout. The
+      implementation searches the configuration for properties with the
+      following pattern: <literal>renderer name without "Renderer"</literal> + "." + <literal>key</literal>. All
+      values are interpreted as pixels. <xref linkend="table-rendererbase"/> specifies some of the
+      recognized keys.</para>
+
+      <table frame="none" id="table-rendererbase" colsep="0" rowsep="0">
+        <title>Recognized keys for LayoutableRendererBase</title>
+        <tgroup cols="2">
+          <colspec colname="c1" colwidth="18pc"/>
+          <colspec colname="c2" colwidth="18pc"/>
+          <thead>
+            <row rowsep="1">
+              <entry>Key</entry>
+              <entry>Description</entry>
+            </row>
+          </thead>
+          <tbody>
+            <row>
+              <entry><literal>fixedWidth</literal>, <literal>fixedHeight</literal></entry>
+              <entry><para>This is the preferred and normal size of a
+      control. It is used if the value fixed is specified within the layout
+      properties of a layout manager.</para></entry>
+            </row>
+            <row>
+              <entry><literal>paddingWidth</literal>, <literal>paddingHeight</literal></entry>
+              <entry>The padding attributes add empty space
+      between the control and its surroundings.</entry>
+            </row>
+            <row>
+              <entry><literal>headerHeight</literal></entry>
+              <entry>Some controls like the &lt;tc:box&gt; control use this
+      property to specify extra space for their header.</entry>
+            </row>
+          </tbody>
+        </tgroup>
+      </table>
+
+      <para>If <classname>LayoutableRendererBase</classname> does not find a value for a renderer it searches
+      for default properties: "Tobago." + <literal>key</literal>. We could (but will not)
+      specify a width padding of five pixels for our control by adding the
+      property <literal>NumberSlider.paddingWidth=5</literal> in the theme configuration of
+      the sandbox theme. Please note that the resource location mechanism as
+      described in <xref linkend="sec-resource-management"/> is used to find a
+      property.</para>
+
+      <para>The Tobago theme configuration is not only used by <classname>RendererBase</classname>,
+      but properties of own renderers can be specified there. For example we
+      define the percentage of the width of the slider of our control in the
+      <filename>tobago-theme-config.xml</filename>: <literal>NumberSlider.sliderWidthPercent=66</literal>. This
+      means the slider gets 66 percent of the width of our control and the
+      input field 34 percent. The value can be accessed in the renderer with
+      the following line of code:</para>
+
+      <para><programlisting role="JAVA">int sliderWidthPercent
+    = ThemeConfig.getValue(facesContext, component, "sliderWidthPercent");</programlisting></para>
+
+      <para>The Tobago theming mechanism locates renderers by their location
+      in the package structure. Normally all Tobago renderers are located
+      under the root package <literal>org.apache.myfaces.tobago.renderkit</literal>. Below this,
+      the location depends on the output technology, the theme and
+      browser.</para>
+
+      <para>We use the sub package <literal>html.sandbox.standard.tag</literal> because we are
+      writing an HTML control for the sandbox theme. Package <literal>standard</literal> means
+      that all browsers (Mozilla, Internet Explorer etc.) will be served by
+      this renderer. The last package <literal>tag</literal> is obligatory for historical
+      reasons.</para>
+
+      <para>The code for encoding/decoding in the renderer is quite long so
+      only some interesting fragments are shown in code snippet. All encoding
+      is done in the method <literal>encodeEnd</literal>. First the properties of the component
+      are retrieved. Then the response writer is used to generate the HTML
+      input field of our control. The response writer for Tobago components is
+      the <classname>TobagoResponseWriter</classname><footnote><para>See <ulink url="http://myfaces.apache.org/tobago/apidocs/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.html"/></para></footnote> which is
+      created by the Tobago render kit. It provides the component developer
+      with additional convenience methods and handles escaping. The decoding
+      is done in the method <literal>decode</literal> and retrieves the value of the input field
+      back from the HTTP request.</para>
+
+      <example><title>Renderer for the slider bar control</title>
+      <programlisting role="JAVA">package org.apache.myfaces.tobago.renderkit.html.sandbox.standard.tag;
+
+public class NumberSliderRenderer extends LayoutableRendererBase {
+
+  public void encodeEnd(FacesContext facesContext, UIComponent component)
+      throws IOException {
+    String currentValue = getCurrentValue(facesContext, component);
+    boolean readonly
+        = ComponentUtil.getBooleanAttribute(component, Attributes.READONLY);
+    boolean disabled
+        = ComponentUtil.getBooleanAttribute(component, Attributes.DISABLED);
+    TobagoResponseWriter writer
+        = HtmlRendererUtil.getTobagoResponseWriter(facesContext);
+    ...
+    writer.startElement(HtmlElements.INPUT);
+    String inputIdAndName = getIdForInputField(facesContext, component);
+    writer.writeNameAttribute(inputIdAndName);
+    writer.writeIdAttribute(inputIdAndName);
+    if (currentValue != null) {
+      writer.writeAttribute(HtmlAttributes.VALUE, currentValue, false);
+    }
+    writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.endElement(HtmlElements.INPUT);
+    ...
+  }
+
+  public void decode(FacesContext context, UIComponent component) {
+    UIInput uiInput = (UIInput) component;
+    ...
+    String inputId = getIdForInputField(context, component);
+    Map requestParameterMap
+        = context.getExternalContext().getRequestParameterMap();
+    if (requestParameterMap.containsKey(inputId)) {
+      String newValue = (String) requestParameterMap.get(inputId);
+      uiInput.setSubmittedValue(newValue);
+    }
+  }
+
+  private String getIdForInputField(
+        FacesContext context, UIComponent component) {...}
+}</programlisting></example>
+
+      <para>When the HTML output in the renderer is generated the question how
+      to size the elements arises. It is not a good idea to hard code static
+      width or height information because the layout manager determines how
+      much space the control should occupy. But how can a renderer know how
+      much space it should use?</para>
+
+      <para>Tobago creates a "style map" for each component and adds it to the
+      components attributes. This style map contains values for the width and
+      the height of the control determined by the layout manager. In the
+      renderer this map can be accessed and the values can be taken into
+      account when creating HTML elements. The following source snippet
+      demonstrates the usage of the style map.</para>
+
+      <programlisting role="JAVA">HtmlStyleMap style = (HtmlStyleMap) component.getAttributes().get("style");
+Measure width = style.getWidth();</programlisting>
+    </sect2>
+
+    <sect2>
+      <title>The Tag and the Tag Declaration</title>
+
+      <para>All JSF implementations must support JSP as page description
+      language for JSF pages. This is also standard for writing Tobago pages.
+      A different view technology that does not depend on JSP is also
+      available — Facelets. To allow an author to use our control we need to
+      define a JSP tag — a custom action. This is done by writing one class
+      and one interface: the tag class itself and a tag declaration interface
+      which is Tobago specific.</para>
+
+      <para>We start with the tag class. All JSP custom actions in JSF that
+      correspond to a UI component in the component tree must either subclass
+      <classname>UIComponentTag</classname><footnote><para>See <ulink url="http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/api/javax/faces/webapp/UIComponentTag.html"/></para></footnote> or
+      <classname>UIComponentBodyTag</classname><footnote><para>See <ulink url="http://java.sun.com/javaee/javaserverfaces/1.1_01/docs/api/javax/faces/webapp/UIComponentBodyTag.html"/></para></footnote> depending on whether they need
+      support for body content functionality or not. Our action has no body
+      content so we want to subclass <classname>UIComponentTag</classname>. Again there is an
+      opportunity to save some effort if we extend from
+      <classname>TobagoTag</classname><footnote><para>See <ulink url="http://myfaces.apache.org/tobago/apidocs/org/apache/myfaces/tobago/internal/taglib/component/TobagoTag.html"/></para></footnote> which extends from
+      <classname>UIComponentTag</classname>. This class already implements the handling for the
+      properties <literal>readonly</literal> and <literal>disabled</literal>.</para>
+
+      <para>Our tag is named
+      <classname>NumberSliderTag</classname><footnote><para>See <ulink url="http://svn.apache.org/viewvc/myfaces/tobago/trunk/sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/NumberSliderTag.java?view=markup"/></para></footnote> and
+      consists of four new properties (<literal>min</literal>, <literal>max</literal>, <literal>value</literal> and
+      <literal>valueChangeListener</literal>) with their getter/setters, an implementation of
+      <literal>getComponentType</literal>, a <literal>release</literal> method and a <literal>setProperties</literal> method.</para>
+
+      <para>Tag classes in Tobago are dumb gateways between the view
+      technology (JSP) and the render independent UI component. No output
+      should be generated in the JSP tag directly. This is done only in
+      appropriate renderers. The advantage with this approach is that we can
+      use a different view technology like Facelets without changing our
+      code.</para>
+
+      <para>Next thing is the declaration of the tag. Therefore it implements
+      an interface
+      <classname>NumberSliderTagDeclaration</classname><footnote><para>See <ulink url="http://svn.apache.org/viewvc/myfaces/tobago/trunk/sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/NumberSliderTagDeclaration.java?view=markup"/></para></footnote>.
+      This interface describes our tag and its attributes with annotations.
+      Tobago's build process uses this declaration to generate a
+      <filename>faces-config.xml</filename> and a tag library description (TLD) for our component
+      with the help of the annotation processing tool (apt). The interface is
+      annotated with a <classname>@Tag</classname> annotation with a name attribute. The specified
+      value "numberSlider" is the name of the JSP tag. The next annotation
+      <classname>@UIComponentTag</classname> makes it clear that the tag belongs to a component with
+      an associated renderer. The attributes <literal>rendererType</literal> and <literal>uiComponent</literal>
+      specify the type of the renderer and the class of the UI component.
+      Please note that the Tobago render kit will add the suffix "Renderer" to
+      the renderer type to find a matching renderer class.</para>
+
+      <para>After the interface, the properties that are defined for the tag
+      are annotated. By convention, the setter of the property is used. The
+      <classname>@TagAttribute</classname> annotation describes a property that is part of the JSP
+      tag. The <classname>@UIComponentTagAttribute</classname> annotation specifies a component
+      property. Our properties appear in both the tag and the component. With
+      the additional annotation attribute <literal>type</literal> we define the type of the
+      properties.</para>
+
+      <para>Tobago has many predefined tag attribute declarations. We make use
+      of them by extending the needed interfaces like <classname>IsReadonly</classname> or
+      <classname>HasValue</classname>:</para>
+
+    <example><title>Tag declaration for the slider bar tag</title>
+      <programlisting role="JAVA">@Tag(name = "numberSlider")
+@UIComponentTag(rendererType = "NumberSlider",
+    uiComponent = "org.apache.myfaces.tobago.component.UINumberSlider")
+public interface NumberSliderTagDeclaration extends
+  HasIdBindingAndRendered, IsReadonly, IsDisabled,
+  HasValue, HasValueChangeListener {
+  
+  @TagAttribute()
+  @UIComponentTagAttribute(type="java.lang.Integer", defaultValue="0")
+  void setMin(String min);
+
+  @TagAttribute()
+  @UIComponentTagAttribute(type="java.lang.Integer", defaultValue="100")
+  void setMax(String max);
+}</programlisting></example>
+    </sect2>
+
+    <sect2>
+      <title>Building and Using the Control</title>
+
+      <para>After performing all four steps that are needed to create a Tobago
+      control (UI component, renderer, tag and tag declaration) we are ready
+      to build. This is done with a simple mvn install in the <emphasis>sandbox</emphasis>
+      directory; the classes are compiled, the <filename>faces-config.xml</filename> and the tag
+      library description is generated, everything is packaged and stored in
+      the target directory. Depending on the Tobago version the package is
+      called something like <filename>tobago-sandbox-i.j.k.jar</filename>. When this jar file is
+      put into the classpath of a web application, the control can be used on
+      a JSP page. It is important to switch to the Sandbox theme in the Tobago
+      configuration.</para>
+
+      <programlisting role="XML">&lt;%@ taglib uri="http://myfaces.apache.org/tobago/sandbox" prefix="tcs" %&gt;
+&lt;%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %&gt;
+&lt;f:view&gt;
+  ...
+  &lt;tcs:numberSlider value="#{controller.value}" min="0" max="200"/&gt;
+  ...
+&lt;/f:view&gt;</programlisting>
+    </sect2>
+
+    <sect2>
+      <title>Things under the Hood</title>
+
+      <para>We have not talked about the HTML layout of the control. There is
+      a significant amount of work required for layouts when creating new
+      Tobago controls, particularly with regard to browser compatibility and
+      using Ajax. Additionally — there is also individual coding for every new
+      control. Everything covered so far deals with aspects that are common to
+      all Tobago component development.</para>
+
+      <para>The Tobago theming mechanism is not the only aspect that locates
+      renderers with a predefined pattern. Almost everything (styles, images,
+      scripts and properties) is organized within a tree structure and located
+      in a similar way.</para>
+    </sect2>
+  </sect1>
+
+  <sect1>
+    <title>Security</title>
+
+    <para>To enable security for a Tobago application you can either write
+    your own login mechanism or use the standard way provided by the servlet
+    specification. The later way has a small drawback because the name
+    attribute for an HTML input control normally cannot be controlled via JSF
+    or Tobago. For form based authentication the servlet specification
+    requires the input fields of a login dialog to have the names <literal>j_username</literal>
+    and <literal>j_password</literal>, respectively. Since we cannot influence the names of
+    <literal>&lt;tc:in&gt;</literal> controls directly we have to resort to a hack. We
+    subsequently change the rendered field names with JavaScript inside the
+    browser.</para>
+
+    <programlisting role="XML">&lt;tx:in id="j_username" label="Username"/&gt;
+&lt;tx:in id="j_password" password="true" label="Password"/&gt;
+
+...
+
+&lt;tc:script onload="initLoginForm();"&gt;
+  function initLoginForm() {
+    var user = document.getElementById("page:j_username");
+    user.name = "j_username";
+    var pass = document.getElementById("page:j_password");
+    pass.name = "j_password";
+    var form = document.getElementById("page::form");
+    form.action 
+        = "${pageContext.request.contextPath}/j_security_check";
+  }
+&lt;/tc:script&gt;</programlisting>
+
+    <para>The <literal>onload</literal> attribute instructs Tobago to execute the passed
+    JavaScript function after the HTML page was loaded.</para>
+
+    <para>Tobago provides an extension package <literal>tobago-security</literal> to secure
+    method bindings with annotations. Currently it is not sufficient to
+    include the jar in the classpath, since the order in which the
+    <filename>faces-config.xml</filename> files from libraries in the classpath are evaluated is
+    depending on the JSF implementation. The <filename>faces-config.xml</filename> file of
+    <literal>tobago-security</literal> defines alternatives for command components with security
+    handling. The easiest way is to copy the component redefinitions into the
+    <filename>faces-config.xml</filename> file of the web application.</para>
+
+    <para>With the <literal>tobago-security</literal> package a method can be marked with
+    <classname>@RolesAllowed</classname> to designate the necessary roles for a business
+    functionality. The method binding will only be evaluated if the user has
+    the appropriate role. Likewise the class can be marked with <classname>@RolesAllowed</classname>
+    to secure all methods. In the address book example the <emphasis>Admin</emphasis> toolbar
+    button points to a method in the <classname>AdminController</classname>. This method is annotated
+    with the required role <emphasis>admin</emphasis>:</para>
+
+    <programlisting role="JAVA">@RolesAllowed("admin")
+public String admin() {
+  return OUTCOME_ADMIN;
+}</programlisting>
+
+    <para>If the user of the application has not the role <emphasis>admin</emphasis> the button is
+    disabled and the method binding will not be evaluated. Additionally the
+    annotations <classname>@DenyAll</classname> and <classname>@PermitAll</classname> are supported. These security
+    annotations are part of the Common Annotations specification
+    (JSR250.)</para>
+  </sect1>
+
+  <sect1>
+    <title>Virtual Forms</title>
+
+    <para>The <literal>&lt;tc:page&gt;</literal> tag acts as a global form. Therefore, for simple
+    pages without control dependencies no explicit form has to be used. The
+    <literal>&lt;tc:form&gt;</literal> control allows nesting of forms and creates dependencies
+    between controls.</para>
+
+    <para>If a form is submitted only the contained model references are
+    updated, other values are temporarily stored. With <literal>&lt;tc:form&gt;</literal> partial
+    validation can be realized, because validation is limited to controls
+    inside a <literal>&lt;tc:form&gt;</literal>. As a result sub forms provide an alternative to
+    <literal>immediate</literal> for input controls. In the address book example changes to the
+    theme and the language are isolated to sub forms to avoid conflicts with
+    validations elsewhere on the page:</para>
+
+    <programlisting role="XML">&lt;tc:form&gt;
+  &lt;tx:selectOneChoice label="Theme" value="#{controller.theme}"&gt;
+  &lt;f:selectItems value="#{controller.themeItems}" /&gt;
+    &lt;f:facet name="change"&gt;
+      &lt;tc:command action="#{controller.themeChanged}"/&gt;
+    &lt;/f:facet&gt;
+  &lt;/tx:selectOneChoice&gt;
+&lt;/tc:form&gt;</programlisting>
+  </sect1>
+
+  <sect1>
+    <title>Partial Rendering</title>
+
+    <para>To avoid the reloading of complete pages, Tobago has a
+    <literal>renderedPartially</literal> attribute to update only parts of the page. For
+    <literal>&lt;tc:tabGroup&gt;</literal> controls this can be achieved by configuring the
+    switching type to <literal>reloadTab</literal>. Tobago also supports a more generic way to
+    update container controls like <literal>&lt;tc:panel&gt;</literal>, <literal>&lt;tc:box&gt;</literal>,
+    <literal>&lt;tc:popup&gt;</literal>, or <literal>&lt;tc:sheet&gt;</literal> using <literal>&lt;tc:attribute&gt;</literal> with the
+    name <literal>renderedPartially</literal> and a value with a comma separated list of
+    identifier paths of the respective containers. An identifier path is a
+    colon separated list of ids of nested naming containers. An absolute path
+    of ids has to begin with a colon character followed by the id of the
+    <literal>&lt;tc:page&gt;</literal> control. If the path does not start with a colon it is a
+    relative path from the current naming container. By using multiple colon
+    characters at the beginning of the path parent naming containers can be
+    accessed. The action of the command has to return null as an outcome,
+    because the current view has to be used again. Only a sub-tree of the view
+    is updated.</para>
+
+    <para>The following code fragment shows a simple example where an input
+    control is enabled depending on the state of a checkbox.</para>
+
+    <programlisting role="XML">&lt;tc:page id="page"&gt;
+  &lt;tc:box label="Container" id="box"&gt;
+    &lt;tx:selectBooleanCheckbox label="Enable" 
+        value="#{controller.miscEnabled}"&gt;
+      &lt;f:facet name="change"&gt;
+        &lt;tc:command&gt;
+          <emphasis role="bold">&lt;tc:attribute name="renderedPartially" value=":page:box"/&gt;</emphasis>
+        &lt;/tc:command&gt;
+      &lt;/f:facet&gt;
+    &lt;/tx:selectBooleanCheckbox&gt;
+
+    &lt;tx:in label="Misc." disabled="#{!controller.miscEnabled}"/&gt;
+  &lt;/tc:box
+&lt;/tc:page&gt;</programlisting>
+
+    <para>Instead of reloading the whole page, only the surrounding container
+    <literal>&lt;tc:box&gt;</literal> of the <literal>&lt;tx:in&gt;</literal> control is updated, if the value of
+    the checkbox changes. The absolute id path of the box, which should be
+    updated, is set as <literal>renderedPartially</literal> attribute of the command.</para>
+
+    <para>Additionally, <literal>&lt;tc:panel&gt;</literal> controls can be reloaded on a regular
+    basis to be able to display changes over time. To accomplish this, the
+    panel has to be provided with a <literal>reload</literal> facet. This facet has to contain a
+    <literal>&lt;tc:reload&gt;</literal> tag to specify the frequency for the reload in
+    milliseconds.</para>
+
+    <programlisting role="XML">&lt;tc:panel&gt;
+  &lt;f:facet name="reload"&gt;
+    <emphasis role="bold">&lt;tc:reload frequency="5000"/&gt;</emphasis>
+  &lt;/f:facet&gt;
+  ...
+&lt;/tc:panel&gt;</programlisting>
+
+    <para>The address book uses the reload facility on an administration page
+    to regularly display the memory utilization of the virtual machine.</para>
+  </sect1>
+
+  <sect1 id="sec-advanced-assembly">
+    <title>Advanced Assembly</title>
+
+    <para>As described in the <xref linkend="sec-getting-started"/>, themes can be served
+    directly out of the theme jars with the help of a special servlet.
+    Generally streaming static resources poses a slight overhead, but using
+    the servlet also provides a simple way to define HTTP expire headers for
+    the static resources. The expiration period can be specified in seconds as
+    an <literal>init-param</literal> for the servlet.</para>
+
+    <programlisting role="XML">&lt;servlet&gt;
+  &lt;servlet-name&gt;ResourceServlet&lt;/servlet-name&gt;
+  &lt;servlet-class&gt;
+     org.apache.myfaces.tobago.servlet.ResourceServlet&lt;/servlet-class&gt;
+  &lt;init-param&gt;
+    <emphasis role="bold">&lt;param-name&gt;expires&lt;/param-name&gt;
+    &lt;param-value&gt;14400&lt;/param-value&gt;</emphasis>
+  &lt;/init-param&gt;
+&lt;/servlet&gt;</programlisting>
+
+    <para>Instead of streaming the resources with a servlet they can be
+    unpacked and supplied by the servlet container directly. Alternatively a
+    web server like the Apache HTTP server can be set up in front of the
+    servlet container. The web server can intercept the URLs for the static
+    resources and serve them instead of the servlet container. If the themes
+    are unpacked, only the resources should be unpacked not the class files or
+    property files. But the jars still have to be put into the classpath in
+    order to provide the necessary implementation files for the theme.</para>
+
+    <para>Besides the MyFaces JSF implementation Tobago also works with other
+    JSF implementations like the reference implementation (RI) from Sun. The
+    POM for the address book example provides three profiles for different JSF
+    implementations. The default is MyFaces. There is an additional profile
+    for the SUN RI. The third profile assumes that the container provides an
+    implementation for JSF.</para>
+  </sect1>
+
+  <sect1>
+    <title>Summary</title>
+
+    <para>Tobago allows developing rich web applications with a rich set of
+    controls. The development is easy and independent of the view technology.
+    Nevertheless the web application makes use of technologies like Ajax
+    without making any effort. The ease of development enables Tobago to be
+    used for rapid prototyping, because the views can be designed without the
+    need to program any lines of Java code.</para>
+
+    <para>In the near future the tree from the sandbox will become part of the
+    standard Tobago distribution and you can expect more useful controls to
+    follow. With MyFaces focusing on fulfilling the JSF specification 1.2
+    Tobago will aim for JSF 1.2 compatibility as well. Another goal is to
+    attain a form of integration with other component sets like Tomahawk.
+    Currently adding such controls to a Tobago application works only limited,
+    partly because there is no way to add the necessary layout and theming
+    information for external controls.</para>
+  </sect1>
+</article>
diff --git a/tobago-3.0.x/src/site/apt/api.apt b/tobago-3.0.x/src/site/apt/api.apt
new file mode 100644
index 0000000..03088a0
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/api.apt
@@ -0,0 +1,293 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+ Tobago API Documentation
+ ------
+
+Tobago API Documentation
+
+  Documentation of the Java classes and the tags.
+
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+|| Version      || JavaDoc API Documentation                                                    || Tag Library Documentation (TLD)                                                                                                        |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.1         | {{{./doc/3.0.1/api/index.html}3.0.1 API Documentation}}                       | {{{./doc/3.0.1/tld/index.html}3.0.1 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.10        | {{{./doc/2.0.10/api/index.html}2.0.10 API Documentation}}                     | {{{./doc/2.0.10/tld/index.html}2.0.10 TLD Documentation}} \                                                                             |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.13        | {{{./doc/1.5.13/api/index.html}1.5.13 API Documentation}}                     | {{{./doc/1.5.13/tld/index.html}1.5.13 TLD Documentation of \<tc:\>}} \                                                                  |
+|               |                                                                               | {{{./doc/1.5.13/tld-tx/index.html}1.5.13 TLD Documentation of \<tx:\>}}                                                                 |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.42        | {{{./doc/1.0.42/api/index.html}1.0.42 API Documentation}}                     | {{{./doc/1.0.42/tld/index.html}1.0.42 TLD Documentation}} \                                                                             |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+
+Tobago API Documentation of the old Releases
+
+  Documentation of the Java classes and the tags.
+
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+|| Version      || JavaDoc API Documentation                                                    || Tag Library Documentation (TLD)                                                                                                        |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0         | {{{./doc/3.0.0/api/index.html}3.0.0 API Documentation}}                       | {{{./doc/3.0.0/tld/index.html}3.0.0 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-beta-1  | {{{./doc/3.0.0-beta-1/api/index.html}3.0.0-beta-1 API Documentation}}         | {{{./doc/3.0.0-beta-1/tld/index.html}3.0.0-beta-1 TLD Documentation}} \                                                                 |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-alpha-7 | {{{./doc/3.0.0-alpha-7/api/index.html}3.0.0-alpha-7 API Documentation}}       | {{{./doc/3.0.0-alpha-7/tld/index.html}3.0.0-alpha-7 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-alpha-6 | {{{./doc/3.0.0-alpha-6/api/index.html}3.0.0-alpha-6 API Documentation}}       | {{{./doc/3.0.0-alpha-6/tld/index.html}3.0.0-alpha-6 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-alpha-5 | {{{./doc/3.0.0-alpha-5/api/index.html}3.0.0-alpha-5 API Documentation}}       | {{{./doc/3.0.0-alpha-5/tld/index.html}3.0.0-alpha-5 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-alpha-4 | {{{./doc/3.0.0-alpha-4/api/index.html}3.0.0-alpha-4 API Documentation}}       | {{{./doc/3.0.0-alpha-4/tld/index.html}3.0.0-alpha-4 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-alpha-3 | {{{./doc/3.0.0-alpha-3/api/index.html}3.0.0-alpha-3 API Documentation}}       | {{{./doc/3.0.0-alpha-3/tld/index.html}3.0.0-alpha-3 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-alpha-2 | {{{./doc/3.0.0-alpha-2/api/index.html}3.0.0-alpha-2 API Documentation}}       | {{{./doc/3.0.0-alpha-2/tld/index.html}3.0.0-alpha-2 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 3.0.0-alpha-1 | {{{./doc/3.0.0-alpha-1/api/index.html}3.0.0-alpha-1 API Documentation}}       | {{{./doc/3.0.0-alpha-1/tld/index.html}3.0.0-alpha-1 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.9         | {{{./doc/2.0.9/api/index.html}2.0.9 API Documentation}}                       | {{{./doc/2.0.9/tld/index.html}2.0.9 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.8         | {{{./doc/2.0.8/api/index.html}2.0.8 API Documentation}}                       | {{{./doc/2.0.8/tld/index.html}2.0.8 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.7         | {{{./doc/2.0.7/api/index.html}2.0.7 API Documentation}}                       | {{{./doc/2.0.7/tld/index.html}2.0.7 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.6         | {{{./doc/2.0.6/api/index.html}2.0.6 API Documentation}}                       | {{{./doc/2.0.6/tld/index.html}2.0.6 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.5         | {{{./doc/2.0.5/api/index.html}2.0.5 API Documentation}}                       | {{{./doc/2.0.5/tld/index.html}2.0.5 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.4         | {{{./doc/2.0.4/api/index.html}2.0.4 API Documentation}}                       | {{{./doc/2.0.4/tld/index.html}2.0.4 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.3         | {{{./doc/2.0.3/api/index.html}2.0.3 API Documentation}}                       | {{{./doc/2.0.3/tld/index.html}2.0.3 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.2         | {{{./doc/2.0.2/api/index.html}2.0.2 API Documentation}}                       | {{{./doc/2.0.2/tld/index.html}2.0.2 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.1         | {{{./doc/2.0.1/api/index.html}2.0.1 API Documentation}}                       | {{{./doc/2.0.1/tld/index.html}2.0.1 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0         | {{{./doc/2.0.0/api/index.html}2.0.0 API Documentation}}                       | {{{./doc/2.0.0/tld/index.html}2.0.0 TLD Documentation}} \                                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0-beta-4  | {{{./doc/2.0.0-beta-4/api/index.html}2.0.0-beta-4 API Documentation}}         | {{{./doc/2.0.0-beta-4/tld/index.html}2.0.0-beta-4 TLD Documentation}} \                                                                 |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0-beta-3  | {{{./doc/2.0.0-beta-3/api/index.html}2.0.0-beta-3 API Documentation}}         | {{{./doc/2.0.0-beta-3/tld/index.html}2.0.0-beta-3 TLD Documentation}} \                                                                 |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0-beta-2  | {{{./doc/2.0.0-beta-2/api/index.html}2.0.0-beta-2 API Documentation}}         | {{{./doc/2.0.0-beta-2/tld/index.html}2.0.0-beta-2 TLD Documentation}} \                                                                 |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0-beta-1  | {{{./doc/2.0.0-beta-1/api/index.html}2.0.0-beta-1 API Documentation}}         | {{{./doc/2.0.0-beta-1/tld/index.html}2.0.0-beta-1 TLD Documentation}} \                                                                 |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0-alpha-3 | {{{./doc/2.0.0-alpha-3/api/index.html}2.0.0-alpha-3 API Documentation}}       | {{{./doc/2.0.0-alpha-3/tld/index.html}2.0.0-alpha-3 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0-alpha-2 | {{{./doc/2.0.0-alpha-2/api/index.html}2.0.0-alpha-2 API Documentation}}       | {{{./doc/2.0.0-alpha-2/tld/index.html}2.0.0-alpha-2 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 2.0.0-alpha-1 | {{{./doc/2.0.0-alpha-1/api/index.html}2.0.0-alpha-1 API Documentation}}       | {{{./doc/2.0.0-alpha-1/tld/index.html}2.0.0-alpha-1 TLD Documentation}} \                                                               |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.6.0-beta-2  | {{{./doc/1.6.0-beta-2/api/index.html}1.6.0-beta-2 API Documentation}}         | {{{./doc/1.6.0-beta-2/tld/index.html}1.6.0-beta-2 TLD Documentation of \<tc:\>}} \                                           |
+|               |                                                                               | {{{./doc/1.6.0-beta-2/tld-tx/index.html}1.6.0-beta-2 TLD Documentation of \<tx:\>}}                |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.6.0-beta-1  | {{{./doc/1.6.0-beta-1/api/index.html}1.6.0-beta-1 API Documentation}}         | {{{./doc/1.6.0-beta-1/tld/index.html}1.6.0-beta-1 TLD Documentation of \<tc:\>}} \                                           |
+|               |                                                                               | {{{./doc/1.6.0-beta-1/tld-tx/index.html}1.6.0-beta-1 TLD Documentation of \<tx:\>}}                |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.12        | {{{./doc/1.5.12/api/index.html}1.5.12 API Documentation}}                     | {{{./doc/1.5.12/tld/index.html}1.5.12 TLD Documentation of \<tc:\>}} \                                                       |
+|               |                                                                               | {{{./doc/1.5.12/tld-tx/index.html}1.5.12 TLD Documentation of \<tx:\>}}                            |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.11        | {{{./doc/1.5.11/api/index.html}1.5.11 API Documentation}}                     | {{{./doc/1.5.11/tld/index.html}1.5.11 TLD Documentation of \<tc:\>}} \                                                       |
+|               |                                                                               | {{{./doc/1.5.11/tld-tx/index.html}1.5.11 TLD Documentation of \<tx:\>}}                            |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.10        | {{{./doc/1.5.10/api/index.html}1.5.10 API Documentation}}                     | {{{./doc/1.5.10/tld/index.html}1.5.10 TLD Documentation of \<tc:\>}} \                                                       |
+|               |                                                                               | {{{./doc/1.5.10/tld-tx/index.html}1.5.10 TLD Documentation of \<tx:\>}}                            |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.9         | {{{./doc/1.5.9/api/index.html}1.5.9 API Documentation}}                       | {{{./doc/1.5.9/tld/index.html}1.5.9 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.9/tld-tx/index.html}1.5.9 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.8         | {{{./doc/1.5.8/api/index.html}1.5.8 API Documentation}}                       | {{{./doc/1.5.8/tld/index.html}1.5.8 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.8/tld-tx/index.html}1.5.8 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.7         | {{{./doc/1.5.7/api/index.html}1.5.7 API Documentation}}                       | {{{./doc/1.5.7/tld/index.html}1.5.7 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.7/tld-tx/index.html}1.5.7 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.6         | {{{./doc/1.5.6/api/index.html}1.5.6 API Documentation}}                       | {{{./doc/1.5.6/tld/index.html}1.5.6 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.6/tld-tx/index.html}1.5.6 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.5         | {{{./doc/1.5.5/api/index.html}1.5.5 API Documentation}}                       | {{{./doc/1.5.5/tld/index.html}1.5.5 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.5/tld-tx/index.html}1.5.5 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.4         | {{{./doc/1.5.4/api/index.html}1.5.4 API Documentation}}                       | {{{./doc/1.5.4/tld/index.html}1.5.4 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.4/tld-tx/index.html}1.5.4 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.3         | {{{./doc/1.5.3/api/index.html}1.5.3 API Documentation}}                       | {{{./doc/1.5.3/tld/index.html}1.5.3 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.3/tld-tx/index.html}1.5.3 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.2         | {{{./doc/1.5.2/api/index.html}1.5.2 API Documentation}}                       | {{{./doc/1.5.2/tld/index.html}1.5.2 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.2/tld-tx/index.html}1.5.2 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.1         | {{{./doc/1.5.1/api/index.html}1.5.1 API Documentation}}                       | {{{./doc/1.5.1/tld/index.html}1.5.1 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.1/tld-tx/index.html}1.5.1 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.5.0         | {{{./doc/1.5.0/api/index.html}1.5.0 API Documentation}}                       | {{{./doc/1.5.0/tld/index.html}1.5.0 TLD Documentation of \<tc:\>}} \                                                         |
+|               |                                                                               | {{{./doc/1.5.0/tld-tx/index.html}1.5.0 TLD Documentation of \<tx:\>}}                              |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.41        | {{{./doc/1.0.41/api/index.html}1.0.41 API Documentation}}                     | {{{./doc/1.0.41/tld/index.html}1.0.41 TLD Documentation}} \                                                                             |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.40        | {{{./doc/1.0.40/api/index.html}1.0.40 API Documentation}}                     | {{{./doc/1.0.40/tld/index.html}1.0.40 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.39        | {{{./doc/1.0.39/api/index.html}1.0.39 API Documentation}}                     | {{{./doc/1.0.39/tld/index.html}1.0.39 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.38        | {{{./doc/1.0.38/api/index.html}1.0.38 API Documentation}}                     | {{{./doc/1.0.38/tld/index.html}1.0.38 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.37        | {{{./doc/1.0.37/api/index.html}1.0.37 API Documentation}}                     | {{{./doc/1.0.37/tld/index.html}1.0.37 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.36        | {{{./doc/1.0.36/api/index.html}1.0.36 API Documentation}}                     | {{{./doc/1.0.36/tld/index.html}1.0.36 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.35        | {{{./doc/1.0.35/api/index.html}1.0.35 API Documentation}}                     | {{{./doc/1.0.35/tld/index.html}1.0.35 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.34        | {{{./doc/1.0.34/api/index.html}1.0.34 API Documentation}}                     | {{{./doc/1.0.34/tld/index.html}1.0.34 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.33        | {{{./doc/1.0.33/api/index.html}1.0.33 API Documentation}}                     | {{{./doc/1.0.33/tld/index.html}1.0.33 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.32        | {{{./doc/1.0.32/api/index.html}1.0.32 API Documentation}}                     | {{{./doc/1.0.32/tld/index.html}1.0.32 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.31        | {{{./doc/1.0.31/api/index.html}1.0.31 API Documentation}}                     | {{{./doc/1.0.31/tld/index.html}1.0.31 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.30        | {{{./doc/1.0.30/api/index.html}1.0.30 API Documentation}}                     | {{{./doc/1.0.30/tld/index.html}1.0.30 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.29        | {{{./doc/1.0.29/api/index.html}1.0.29 API Documentation}}                     | {{{./doc/1.0.29/tld/index.html}1.0.29 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.28        | {{{./doc/1.0.28/api/index.html}1.0.28 API Documentation}}                     | {{{./doc/1.0.28/tld/index.html}1.0.28 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.27        | {{{./doc/1.0.27/api/index.html}1.0.27 API Documentation}}                     | {{{./doc/1.0.27/tld/index.html}1.0.27 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.26        | {{{./doc/1.0.26/api/index.html}1.0.26 API Documentation}}                     | {{{./doc/1.0.26/tld/index.html}1.0.26 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.25        | {{{./doc/1.0.25/api/index.html}1.0.25 API Documentation}}                     | {{{./doc/1.0.25/tld/index.html}1.0.25 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.24        | {{{./doc/1.0.24/api/index.html}1.0.24 API Documentation}}                     | {{{./doc/1.0.24/tld/index.html}1.0.24 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.23        | {{{./doc/1.0.23/api/index.html}1.0.23 API Documentation}}                     | {{{./doc/1.0.23/tld/index.html}1.0.23 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.22        | {{{./doc/1.0.22/api/index.html}1.0.22 API Documentation}}                     | {{{./doc/1.0.22/tld/index.html}1.0.22 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.21        | {{{./doc/1.0.21/api/index.html}1.0.21 API Documentation}}                     | {{{./doc/1.0.21/tld/index.html}1.0.21 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.20        | {{{./doc/1.0.20/api/index.html}1.0.20 API Documentation}}                     | {{{./doc/1.0.20/tld/index.html}1.0.20 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.19        | {{{./doc/1.0.19/api/index.html}1.0.19 API Documentation}}                     | {{{./doc/1.0.19/tld/index.html}1.0.19 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.18        | {{{./doc/1.0.18/api/index.html}1.0.18 API Documentation}}                     | {{{./doc/1.0.18/tld/index.html}1.0.18 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.17        | {{{./doc/1.0.17/api/index.html}1.0.17 API Documentation}}                     | {{{./doc/1.0.17/tld/index.html}1.0.17 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.16        | {{{./doc/1.0.16/api/index.html}1.0.16 API Documentation}}                     | {{{./doc/1.0.16/tld/index.html}1.0.16 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.15        | {{{./doc/1.0.15/api/index.html}1.0.15 API Documentation}}                     | {{{./doc/1.0.15/tld/index.html}1.0.15 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.14        | {{{./doc/1.0.14/api/index.html}1.0.14 API Documentation}}                     | {{{./doc/1.0.14/tld/index.html}1.0.14 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.13        | {{{./doc/1.0.13/api/index.html}1.0.13 API Documentation}}                     | {{{./doc/1.0.13/tld/index.html}1.0.13 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.12        | {{{./doc/1.0.12/api/index.html}1.0.12 API Documentation}}                     | {{{./doc/1.0.12/tld/index.html}1.0.12 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.11        | {{{./doc/1.0.11/api/index.html}1.0.11 API Documentation}}                     | {{{./doc/1.0.11/tld/index.html}1.0.11 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.10        | {{{./doc/1.0.10/api/index.html}1.0.10 API Documentation}}                     | {{{./doc/1.0.10/tld/index.html}1.0.10 TLD Documentation}} \                                                                  |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.9         | {{{./doc/1.0.9/api/index.html}1.0.9 API Documentation}}                       | {{{./doc/1.0.9/tld/index.html}1.0.9 TLD Documentation}} \                                                                    |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.8         | {{{./doc/1.0.8/api/index.html}1.0.8 API Documentation}}                       | {{{./doc/1.0.8/tld/index.html}1.0.8 TLD Documentation}} \                                                                    |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+| 1.0.7         | {{{./doc/1.0.7/api/index.html}1.0.7 API Documentation}}                       | {{{./doc/1.0.7/tld/index.html}1.0.7 TLD Documentation}} \                                                                    |
+|               |                                                                               |                                                                                                                                         |
+*---------------+-------------------------------------------------------------------------------+-----------------------------------------------------------------------------------------------------------------------------------------+
+
+Further JSF Documentation
+
+  {{{http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/index.html}JSF 1.1 API Documentation}}\
+  {{{http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/tlddocs/index.html}JSF 1.1 Tag Library Documentation}}
+
+  {{{http://java.sun.com/javaee/javaserverfaces/1.2_MR1/docs/api/index.html}JSF 1.2 API Documentation}}\
+  {{{http://java.sun.com/javaee/javaserverfaces/1.2_MR1/docs/tlddocs/index.html}JSF 1.2 Tag Library Documentation}}
+
+  {{{http://javaserverfaces.java.net/nonav/docs/2.0/javadocs/index.html}JSF 2.0 API Documentation}}\
+  {{{http://javaserverfaces.java.net/nonav/docs/2.0/renderkitdocs/index.html}JSF 2.0 RenderKit Documentation}}\
+  {{{http://javaserverfaces.java.net/nonav/docs/2.0/managed-bean-api/index.html}JSF 2.0 Managed Bean API Documentation}}\
+  {{{http://javaserverfaces.java.net/nonav/docs/2.0/vdldocs/facelets/index.html}JSF 2.0 Facelets Tag Library Documentation}}\
+  {{{http://javaserverfaces.java.net/nonav/docs/2.0/vdldocs/jsp/index.html}JSF 2.0 JSP Tag Library Documentation}}\
+  {{{http://javaserverfaces.java.net/nonav/docs/2.0/jsdocs/index.html}JSF 2.0 JavaScript API}}
+
+  {{{http://javaserverfaces.java.net/nonav/docs/2.1/}JSF 2.1 Documentation}}
+
+  {{{http://javaserverfaces.java.net/nonav/docs/2.2/}JSF 2.2 Documentation}}
diff --git a/tobago-3.0.x/src/site/apt/compatibility.apt b/tobago-3.0.x/src/site/apt/compatibility.apt
new file mode 100644
index 0000000..bed39bf
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/compatibility.apt
@@ -0,0 +1,128 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+ Compatibility
+ ------
+
+Compatibility
+
+  Tobago was compatible with the following specifications, libraries and containers.
+  This list is not exhaustive, additions are welcome.
+
+  \ 
+
+*--+--+--+--+--+
+|| <<Tobago Version>>  || <<1.0.x>>                 || <<1.5.x>>                                   || <<2.0.x>>                             || <<3.x>>
+*--+--+--+--+--+
+|| <<Specifications>>  ||                           ||                                             ||                                       ||
+*--+--+--+--+--+
+| Java                 | 1.4\[retro\], <<1.5>>, 1.6, 1.7 | 1.5, 1.6, 1.7, 1.8                      | 1.5, 1.6, 1.7, 1.8                     | 1.6, 1.7, 1.8
+*--+--+--+--+--+
+| JSF                  | <<1.1>>, 1.2               | 1.2, 2.0\[disable vh\], 2.1\[disable vh\]    | 2.0, 2.1, 2.2                          | 2.0, 2.1, 2.2
+*--+--+--+--+--+
+| Facelets             | <<1.1>>\[ext\]             | <<1.1>>\[ext\]                               | \[int\]                                | \[int\]
+*--+--+--+--+--+
+| Servlet              | 2.3, <<2.4>>, 2.5          | 2.4\[facelets only\], <<2.5>>, 3.0           | 2.4\[facelets only\], <<2.5>>, <<3.0>>, <<3.1>> | 3.0, 3.1
+*--+--+--+--+--+
+| JSP                  | 1.2, <<2.0>>, 2.1          | <<2.1>>, 2.2                                 | 2.1, 2.2                               | -
+*--+--+--+--+--+
+|| <<Implementations>> ||                           ||                                             ||                                       ||
+*--+--+--+--+--+
+| MyFaces              | <<1.1>>, 1.2               | 1.2, 2.0, 2.1                                | 2.0, 2.1, 2.2                          | 2.0, 2.1, 2.2
+*--+--+--+--+--+
+| Sun RI               | <<1.1>>, 1.2               | 1.2, 2.0, 2.1                                | 2.0, 2.1, 2.2                          | 2.0, 2.1, 2.2
+*--+--+--+--+--+
+|                      |                            |                                              |                                        |
+*--+--+--+--+--+
+|| <<Servers>>         ||                           ||                                             ||                                       ||
+*--+--+--+--+--+
+| Tomcat               | 4.1, 5.0, 5.5, 6, 7        | 5.5\[facelets only\], 6, 7                   | 5.5\[facelets only\], 6, 7             | 7, 8
+*--+--+--+--+--+
+| Jetty                | 6, 7                       | 6, 7, 8                                      | 6, 7, 8                                | 8, 9
+*--+--+--+--+--+
+| WebLogic             | 8.1, 9.0, 9.1, 9.2, 10, 11g | 9.2\[facelets only\], 10, 11g, 12c           | 9.2\[facelets only\], 10, 11g, 12c     | 12c
+*--+--+--+--+--+
+| WebSphere            | 6.0, 6.1                   | 6.1\[facelets only\], 7, 8, 8.5              | 6.1\[facelets only\], 7, 8, 8.5        | 8, 8.5
+*--+--+--+--+--+
+| others               |                            | \[other servers\]                            | \[other servers\]                      | \[other servers\]
+*--+--+--+--+--+
+|                      |                            |                                              |                                        |
+*--+--+--+--+--+
+|| <<Browser>>         ||                           ||                                             ||                                       ||
+*--+--+--+--+--+
+| Internet Explorer    | 6, 7, 8, 9, 10, 11         | 6, 7, 8, 9, 10, 11, ...                      | 6\[lim\], 7\[lim\], 8\[lim\], 9, 10, 11, ... | 10\[lim\], 11, ...
+*--+--+--+--+--+
+| Firefox              | 2, 3, 4, ...               | 2, 3, 4, ...                                 | 2\[lim\], 3, 4, ...                    | \[latest\]
+*--+--+--+--+--+
+| Safari               |                            | 4, 5, 6, ...                                 | 4, 5, 6, ...                           | \[latest\]
+*--+--+--+--+--+
+| Chrome               |                            | 5, ...                                       | 5, ...                                 | \[latest\]
+*--+--+--+--+--+
+| Opera                |                            | 10, 11                                       | 10, 11, ...                            | \[latest\]
+*--+--+--+--+--+
+| others               |                            | \[other browsers\]                           | \[other browsers\]                     | \[latest\]
+*--+--+--+--+--+
+|                      |                            |                                              |                                        |
+*--+--+--+--+--+
+|| <<Frameworks>>      ||                           ||                                             ||                                       ||
+*--+--+--+--+--+
+| CDI                  |                            | yes                                          | yes                                    | yes
+*--+--+--+--+--+
+| Codi                 |                            | yes                                          | yes                                    | yes
+*--+--+--+--+--+
+| DeltaSpike           |                            | yes                                          | yes                                    | yes
+*--+--+--+--+--+
+| JSR-303 / BV         |                            | yes                                          | yes                                    | yes
+*--+--+--+--+--+
+
+ ~~ JSF Addon-Frameworks: Apache Shale Dialog, Apache Shale Clay, Spring Web Flow, Seam, WebBeans, "Validator", ...
+ ~~ IoC Frameworks: Spring, Guice, ...
+ ~~ Component Libs: Richfaces, Icefaces, Trinidad, Tomahawk ...
+
+  <<bold:>> preferred
+
+  normal: compatible
+
+  \[retro\]: use the JDK 1.4 retro version (available for Tobago 1.0.41 and before)
+
+  \[ext\]: add the tobago-facelets extension
+
+  \[int\]: since Tobago 2.0 and JSF 2.0 Facelets are integrated in JSF
+
+  \[tbd\]: to be defined (this information is unsettled and may change)
+  
+  \[lim\]: these old browsers are generally supported, but may have weak appearance
+
+  \[facelets only\]: it works with facelets, but not with JSP, because JSF 1.2 requires JSP 2.1
+
+  \[other servers\]: other servers should work, when they are compliant to the named specifications
+
+  \[latest\]: all browser supported by Bootstrap 4 are supported, these are usually the latest, stable releases
+
+  \[other browsers\]: other browsers should work, in their actual version, when they are standard compliant to HTML 4 and CSS 2.1
+
+  \[no release\]: Using Tobago 1.5 with JSF 1.1 is currently not part of the release, but can be build from the sources with mvn -Pjsf-1.1
+
+  \[disable vh\]: Tobago 1.5 works with JSF 2.0 when you are disable the Facelets ViewHandler from JSF 2.0 and using the
+  original Facelets:
+
++----------------------------------------
+  <context-param>
+    <description>For backward compatibility (using "old" Facelets with JSF 2.0)</description>
+    <param-name>javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER</param-name>
+    <param-value>true</param-value>
+  </context-param>
++----------------------------------------
diff --git a/tobago-3.0.x/src/site/apt/demo.apt b/tobago-3.0.x/src/site/apt/demo.apt
new file mode 100644
index 0000000..736b612
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/demo.apt
@@ -0,0 +1,57 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+ 
+ ------
+ Demo
+ ------
+
+Live Demo
+
+  A live demo can be found for different versions here:
+
+  * {{{http://www.irian.biz/tobago-example-demo-3.0.x/}3.0.x (current release)}}
+
+  * {{{http://www.irian.biz/tobago-example-demo-2.0.x/}2.0.x (last release)}}
+
+  * {{{http://example.irian.at/tobago-example-demo-1.5.x/}1.5.x (old release - nightly)}}
+
+  * {{{http://example.irian.at/tobago-example-demo-1.0.x/}1.0.x (old release - nightly)}}
+
+  []
+
+  This demo and more examples you can find in the Subversion (see {{{./getting-started.html}Getting Started}} section).
+
+  The current snapshot of the demo war can be downloaded at:
+  {{https://repository.apache.org/content/repositories/snapshots/org/apache/myfaces/tobago/tobago-example-demo/}}
+
+Examples
+
+  Tobago contains various example applications including a general demo, an address book application, a blank WAR,
+  and an example theme.
+
+* Tobago Demo
+
+  The Tobago demo is for demonstration and documentation purpose.
+  It presents the features of Tobago including layout and themes and contains
+  an overview of the provided controls and best practices how to use Tobago.
+
+* Blank WAR
+
+  The Blank WAR is a minimal WAR to display a simple page with Tobago -- useful to get started with your own Tobago
+  application.
+
+* Blank Theme
+
+  This theme shows how to extend an existing theme.
diff --git a/tobago-3.0.x/src/site/apt/download.apt b/tobago-3.0.x/src/site/apt/download.apt
new file mode 100644
index 0000000..012cf10
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/download.apt
@@ -0,0 +1,190 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+ 
+ ------
+Download MyFaces Tobago
+ ------
+
+Download MyFaces Tobago
+
+
+  Use the links below to download a distribution of MyFaces Tobago from
+  one of our mirrors. It is good practice to verify the integrity of the
+  distribution files.
+
+  You will be prompted for a mirror - if the file is not found on yours, please be patient, as it may take 24
+  hours to reach all mirrors.
+
+  Apache MyFaces Tobago is distributed as a <<<zip>>> archive (for Windows) and
+  as a <<<tar.gz>>> archive (for UNIX). The content is the same. Please note
+  that the <<<tar.gz>>> archives contain file names longer than 100 characters and have been
+  created using GNU tar extensions. Thus they must be untarred with a GNU compatible
+  version of tar.
+
+MyFaces Tobago 3.0.1 Distribution
+
+    Release notes can be found in
+    {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12338730}Jira}}.
+
+*-------------------------+--------+---------+----------+-----------+
+|                         | Typ    | Mirrors | Checksum | Signature |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-3.0.1-dist.tar.gz} myfaces-tobago-3.0.1-dist.tar.gz}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-dist.tar.gz.sha256} myfaces-tobago-3.0.1-dist.tar.gz.sha256}}\             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-dist.tar.gz.asc} myfaces-tobago-3.0.1-dist.tar.gz.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-dist.tar.gz.md5}    myfaces-tobago-3.0.1-dist.tar.gz.md5}}                 | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-3.0.1-dist.zip} myfaces-tobago-3.0.1-dist.zip}}                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-dist.zip.sha256} myfaces-tobago-3.0.1-dist.zip.sha256}}\                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-dist.zip.asc} myfaces-tobago-3.0.1-dist.zip.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-dist.zip.md5}    myfaces-tobago-3.0.1-dist.zip.md5}}                       | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Source   | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/source/myfaces-tobago-3.0.1-source-release.zip} myfaces-tobago-3.0.1-source-release.zip}} | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-3.0.1-source-release.zip.sha256} myfaces-tobago-3.0.1-source-release.zip.sha256}}\ | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-3.0.1-source-release.zip.asc} myfaces-tobago-3.0.1-source-release.zip.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-3.0.1-source-release.zip.md5}    myfaces-tobago-3.0.1-source-release.zip.md5}}     | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-3.0.1-example.tar.gz} myfaces-tobago-3.0.1-example.tar.gz}}       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-example.tar.gz.sha256} myfaces-tobago-3.0.1-example.tar.gz.sha256}}\       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-example.tar.gz.asc} myfaces-tobago-3.0.1-example.tar.gz.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-example.tar.gz.md5}    myfaces-tobago-3.0.1-example.tar.gz.md5}}           | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-3.0.1-example.zip} myfaces-tobago-3.0.1-example.zip}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-example.zip.sha256} myfaces-tobago-3.0.1-example.zip.sha256}}\             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-example.zip.asc} myfaces-tobago-3.0.1-example.zip.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-3.0.1-example.zip.md5}    myfaces-tobago-3.0.1-example.zip.md5}}                 | |
+*-------------------------+--------+---------+----------+-----------+
+
+MyFaces Tobago 2.0.10 Distribution
+
+    Release notes can be found in
+    {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12334742}Jira}}.
+
+*-------------------------+--------+---------+----------+-----------+
+|                         | Typ    | Mirrors | Checksum | Signature |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-2.0.10-dist.tar.gz} myfaces-tobago-2.0.10-dist.tar.gz}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-dist.tar.gz.sha256} myfaces-tobago-2.0.10-dist.tar.gz.sha256}}\             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-dist.tar.gz.asc} myfaces-tobago-2.0.10-dist.tar.gz.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-dist.tar.gz.md5}    myfaces-tobago-2.0.10-dist.tar.gz.md5}}                 | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-2.0.10-dist.zip} myfaces-tobago-2.0.10-dist.zip}}                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-dist.zip.sha256} myfaces-tobago-2.0.10-dist.zip.sha256}}\                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-dist.zip.asc} myfaces-tobago-2.0.10-dist.zip.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-dist.zip.md5}    myfaces-tobago-2.0.10-dist.zip.md5}}                       | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Source   | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/source/myfaces-tobago-2.0.10-source-release.zip} myfaces-tobago-2.0.10-source-release.zip}} | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-2.0.10-source-release.zip.sha256} myfaces-tobago-2.0.10-source-release.zip.sha256}}\ | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-2.0.10-source-release.zip.asc} myfaces-tobago-2.0.10-source-release.zip.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-2.0.10-source-release.zip.md5}    myfaces-tobago-2.0.10-source-release.zip.md5}}     | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-2.0.10-example.tar.gz} myfaces-tobago-2.0.10-example.tar.gz}}       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-example.tar.gz.sha256} myfaces-tobago-2.0.10-example.tar.gz.sha256}}\       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-example.tar.gz.asc} myfaces-tobago-2.0.10-example.tar.gz.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-example.tar.gz.md5}    myfaces-tobago-2.0.10-example.tar.gz.md5}}           | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-2.0.10-example.zip} myfaces-tobago-2.0.10-example.zip}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-example.zip.sha256} myfaces-tobago-2.0.10-example.zip.sha256}}\             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-example.zip.asc} myfaces-tobago-2.0.10-example.zip.asc}} |
+|                         |        |                                                                                                                                           | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-2.0.10-example.zip.md5}    myfaces-tobago-2.0.10-example.zip.md5}}                 | |
+*-------------------------+--------+---------+----------+-----------+
+
+MyFaces Tobago 1.5.13 Distribution
+
+    Release notes can be found in
+    {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12325597}Jira}}.
+
+*-------------------------+--------+---------+----------+-----------+
+|                         | Typ    | Mirrors | Checksum | Signature |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.5.13-dist.tar.gz} myfaces-tobago-1.5.13-dist.tar.gz}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-dist.tar.gz.md5} myfaces-tobago-1.5.13-dist.tar.gz.md5}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-dist.tar.gz.asc} myfaces-tobago-1.5.13-dist.tar.gz.asc}} |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.5.13-dist.zip} myfaces-tobago-1.5.13-dist.zip}}                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-dist.zip.md5} myfaces-tobago-1.5.13-dist.zip.md5}}                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-dist.zip.asc} myfaces-tobago-1.5.13-dist.zip.asc}} |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Source   | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/source/myfaces-tobago-1.5.13-source-release.zip} myfaces-tobago-1.5.13-source-release.zip}} | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-1.5.13-source-release.zip.md5} myfaces-tobago-1.5.13-source-release.zip.md5}} | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-1.5.13-source-release.zip.asc} myfaces-tobago-1.5.13-source-release.zip.asc}} |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.5.13-example.tar.gz} myfaces-tobago-1.5.13-example.tar.gz}}       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-example.tar.gz.md5} myfaces-tobago-1.5.13-example.tar.gz.md5}}       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-example.tar.gz.asc} myfaces-tobago-1.5.13-example.tar.gz.asc}} |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.5.13-example.zip} myfaces-tobago-1.5.13-example.zip}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-example.zip.md5} myfaces-tobago-1.5.13-example.zip.md5}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.5.13-example.zip.asc} myfaces-tobago-1.5.13-example.zip.asc}} |
+*-------------------------+--------+---------+----------+-----------+
+
+MyFaces Tobago 1.0.42 Distribution
+
+    Release notes can be found in
+    {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12326705}Jira}}.
+
+*-------------------------+--------+---------+----------+-----------+
+|                         | Typ    | Mirrors | Checksum | Signature |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.0.42-dist.tar.gz} myfaces-tobago-1.0.42-dist.tar.gz}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-dist.tar.gz.sha256} myfaces-tobago-1.0.42-dist.tar.gz.sha256}}\             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-dist.tar.gz.asc} myfaces-tobago-1.0.42-dist.tar.gz.asc}} |
+|                         |        |                                                                                                                                             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-dist.tar.gz.md5} myfaces-tobago-1.0.42-dist.tar.gz.md5}}                    | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago          | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.0.42-dist.zip} myfaces-tobago-1.0.42-dist.zip}}                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-dist.zip.sha256} myfaces-tobago-1.0.42-dist.zip.sha256}}\                   | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-dist.zip.asc} myfaces-tobago-1.0.42-dist.zip.asc}} |
+|                         |        |                                                                                                                                             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-dist.zip.md5} myfaces-tobago-1.0.42-dist.zip.md5}}                          | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Source   | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/source/myfaces-tobago-1.0.42-source-release.zip} myfaces-tobago-1.0.42-source-release.zip}} | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-1.0.42-source-release.zip.sha256} myfaces-tobago-1.0.42-source-release.zip.sha256}}\ | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-1.0.42-source-release.zip.asc} myfaces-tobago-1.0.42-source-release.zip.asc}} |
+|                         |        |                                                                                                                                             | {{{https://www.apache.org/dist/myfaces/source/myfaces-tobago-1.0.42-source-release.zip.md5} myfaces-tobago-1.0.42-source-release.zip.md5}}        | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | tar.gz | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.0.42-example.tar.gz} myfaces-tobago-1.0.42-example.tar.gz}}       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-example.tar.gz.sha256} myfaces-tobago-1.0.42-example.tar.gz.sha256}}\       | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-example.tar.gz.asc} myfaces-tobago-1.0.42-example.tar.gz.asc}} |
+|                         |        |                                                                                                                                             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-example.tar.gz.md5} myfaces-tobago-1.0.42-example.tar.gz.md5}}              | |
+*-------------------------+--------+---------+----------+-----------+
+| MyFaces Tobago Example  | zip    | {{{http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.0.42-example.zip} myfaces-tobago-1.0.42-example.zip}}             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-example.zip.sha256} myfaces-tobago-1.0.42-example.zip.sha256}}\             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-example.zip.asc} myfaces-tobago-1.0.42-example.zip.asc}} |
+|                         |        |                                                                                                                                             | {{{https://www.apache.org/dist/myfaces/binaries/myfaces-tobago-1.0.42-example.zip.md5} myfaces-tobago-1.0.42-example.zip.md5}}                    | |
+*-------------------------+--------+---------+----------+-----------+
+
+
+Latest source code from SVN repository
+
+    If you want to use the latest Apache MyFaces Tobago features, the source code is under
+    version control with SVN. In the {{{./getting-started.html} Getting Started }}
+    section you will find information how to use the ASF MyFaces Tobago SVN Repository.
+
+Nightly builds from SVN repository
+
+    There are also nightly {{{https://repository.apache.org/content/repositories/snapshots/org/apache/myfaces/tobago/tobago-assembly} dist builds}} and
+    {{{https://repository.apache.org/content/repositories/snapshots/org/apache/myfaces/tobago/tobago} source builds}}
+    available every 24 hours (11:00 PM EST).
+
+Archive of old releases
+
+    Older releases are available in the {{{http://archive.apache.org/dist/myfaces/} archive}}.  Those
+    releases are only provided as historical artifacts. We strongly
+    recommend not to use those releases, but upgrade to the most recent release.
+
+Verifying checksums
+
+    It is essential that you verify the integrity of the downloaded
+    files using the PGP and MD5 signatures. MD5 verification ensures the
+    file was not corrupted during the download process. PGP verification
+    ensures that the file came from a certain person.
+
+    To verify the MD5 signature on the files, you need to use a program
+    called <<<md5>>> or <<<md5sum>>>, which is
+    included in many UNIX distributions.  It is also available as part of
+    {{{http://www.gnu.org/software/textutils/textutils.html}GNU Textutils}}.
+    Windows users can get binary md5 programs from {{{http://www.fourmilab.ch/md5/}here}},
+    {{{http://www.pc-tools.net/win32/freeware/console/}here}}, or
+    {{{http://www.slavasoft.com/fsum/}here}}.
+
+Verifying signatures
+
+  	PGP verification ensures that the file came from a certain person.  We strongly recommend
+	  you verify your downloads with both PGP and MD5.
+
+	  The PGP signatures can be verified using {{{http://www.pgpi.org/}PGP}} or
+	  {{{http://www.gnupg.org/}GPG}}.  First download the Apache MyFaces
+	  {{{http://www.apache.org/dist/myfaces/KEYS}KEYS}}	as well as the <<<asc>>> signature file
+	  for the particular distribution. It is important that you get these files from the ultimate
+	  trusted source - the main ASF distribution site, rather than from a mirror.
+	  Then verify the signatures using ...
+
+	  <<<
+	  % pgpk -a KEYS
+	  % pgpv myfaces-tobago-<version>-dist.tar.gz.asc
+	  >>>
+
+	  <or>
+
+	  <<<
+	  % pgp -ka KEYS
+	  % pgp myfaces-tobago-<version>-dist.tar.gz.asc
+	  >>>
+
+	  <or>
+
+	  <<<
+  	% gpg --import KEYS
+	  % gpg --verify myfaces-tobago-<version>-dist.tar.gz.asc
+	  >>>
diff --git a/tobago-3.0.x/src/site/apt/getting-started.apt b/tobago-3.0.x/src/site/apt/getting-started.apt
new file mode 100644
index 0000000..8b4d343
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/getting-started.apt
@@ -0,0 +1,117 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+ Getting Started
+ ------
+
+  This section describes how to build Tobago and run the
+  example applications from the sources.
+
+Checking Out
+
+  Check out the 3.x.x sources by running the following:
+
++----------------------------------------
+  svn checkout http://svn.apache.org/repos/asf/myfaces/tobago/trunk tobago
++----------------------------------------
+
+  Check out the 2.0.x sources by running the following:
+
++----------------------------------------
+  svn checkout http://svn.apache.org/repos/asf/myfaces/tobago/branches/tobago-2.0.x tobago-2.0.x
++----------------------------------------
+
+  Check out the 1.5.x sources by running the following:
+
++----------------------------------------
+  svn checkout http://svn.apache.org/repos/asf/myfaces/tobago/branches/tobago-1.5.x tobago-1.5.x
++----------------------------------------
+
+  Check out the 1.0.x sources by running the following:
+
++----------------------------------------
+  svn checkout http://svn.apache.org/repos/asf/myfaces/tobago/branches/tobago-1.0.x tobago-1.0.x
++----------------------------------------
+
+
+Building
+
+  You need {{{http://maven.apache.org/download.html}Maven 2}} (at least 2.2.1) Java 5 to build Tobago 1.0.x.\
+  You need {{{http://maven.apache.org/download.html}Maven 2}} (at least 3.0.4) Java 6 or 7 to build Tobago 1.5.x.
+  You need {{{http://maven.apache.org/download.html}Maven 2}} (at least 3.0.4) Java 8 to build Tobago 2.0.x and
+  Tobago 3.0.x.
+
+  In the
+  {{{http://svn.apache.org/repos/asf/myfaces/tobago/trunk/}main directory}}
+  you can use
+
++----------------------------------------
+  mvn install
++----------------------------------------
+
+  to run the install target on all sub projects. This will
+  put all necessary artifacts into your local repository.
+
+The Demo
+
+  You can run the examples inside tobago-example with jetty
+
++----------------------------------------
+  mvn jetty:run
++----------------------------------------
+
+  or (for the addressbook and the JSP versions of demo and test)
+
++----------------------------------------
+  mvn jetty:run-exploded
++----------------------------------------
+
+  or
+
++----------------------------------------
+  mvn package
++----------------------------------------
+
+  and deploy the WAR from the target directory manually.
+
+Using different JSF implementations (Tobago 1.x)
+
+  By default the example will be started with MyFaces 1.2.
+  You can run the examples with other version like you see here:
+
++----------------------------------------
+  mvn jetty:run
+  mvn jetty:run -Djsf=myfaces-2.0
+  mvn jetty:run -Djsf=myfaces-2.1
+  mvn jetty:run -Djsf=mojarra-1.2
+  mvn jetty:run -Djsf=mojarra-2.0
+  mvn jetty:run -Djsf=mojarra-2.1
+  mvn jetty:run -Djsf=mojarra-2.2
++----------------------------------------
+
+Using different JSF implementations (Tobago 2.x)
+
+  By default the example will be started with MyFaces 2.0
+  You can run the examples with other version like you see here:
+
++----------------------------------------
+  mvn jetty:run
+  mvn jetty:run -Djsf=myfaces-2.1
+  mvn jetty:run -Djsf=myfaces-2.2
+  mvn jetty:run -Djsf=mojarra-2.0
+  mvn jetty:run -Djsf=mojarra-2.1
+  mvn jetty:run -Djsf=mojarra-2.2
++----------------------------------------
diff --git a/tobago-3.0.x/src/site/apt/guide.apt b/tobago-3.0.x/src/site/apt/guide.apt
new file mode 100644
index 0000000..3628b08
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/guide.apt
@@ -0,0 +1,660 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+ Guide to Tobago
+ ------
+
+{Guide to Tobago}
+
+  <This guide covers primarily Tobago 1 and 2. Most basic ideas are the same in Tobago 3, but
+  documented in the demo application.>
+
+====================
+
+  Tobago is a JavaServer Faces (JSF) framework and component library. It provides a comfortable way to layout screens
+  of desktop-like applications with a consistent look & feel. Tobago emphasizes the separation of structure
+  and design of screens. Screens are developed independently of the view technology -- no HTML, CSS, or JavaScript.
+  Because of strict separation a screen can be displayed with different themes. These themes can be used to render
+  screens according to different cooperate design without changing the sources of the screens.
+
+  This guide assumes basic knowledge about JSF. For more information about JSF see one of the various books about JSF,
+  the {{{http://java.sun.com/javaee/5/docs/tutorial/doc/bnaph.html}Sun Java 5 Tutorial}} or
+  the {{{http://java.sun.com/javaee/javaserverfaces/download.html}JSF Specification.}}
+
+{Content}
+
+  \ 
+
+%{toc|fromDepth=0|toDepth=4}
+
+{Environment}
+
+* {Building and Deploying the Tobago Examples}
+
+  Tobago uses Maven as a build management system. The provided examples are normally build with Maven, but it would
+  be easy to use an alternative build system. The necessary artifacts can be downloaded {{{./download.html}here}} or
+  from the Maven repository.
+
+  We will use the address book demo as an example in this guide. Since the address book example is currently
+  not part of the Tobago distribution, you have to check-out the sources from the Apache Subversion repository.
+  We will use the latest release tag for this.
+
++------------------------------------------+
+svn co https://svn.apache.org/repos/asf/myfaces/tobago/tags/tobago-1.0.22/example/addressbook/ tobago-addressbook
++------------------------------------------+
+
+  You will need Java 5 and Maven 2.0.9 or later to build the address book example. Use the following command to
+  compile the sources and deploy the web application on an embedded Jetty server:
+
++------------------------------------------+
+mvn jetty:run-exploded
++------------------------------------------+
+
+  If you point your browser to {{http://localhost:8080/}} and you will be directed to the login dialog of the address
+  book example.\
+  \ 
+
+[images/guide-addressbook-login.png] Address Book Login
+
+  You can click on the guest/guest or admin/admin links or fill in the authentication information yourself
+  and press the 'Login' button. After displaying a splash screen for a while the application will direct you to
+  the address list page.\
+  \ 
+
+[images/guide-addressbook-list.png] Address List
+
+  A freshly started instance of the address book example will not contain any addresses in the list. But you can
+  add addresses by pressing the 'New' button in the tool bar. The addresses will be stored in an embedded Derby
+  database.
+
+* {Building Tobago}
+
+  To use the latest version of Tobago you can use the snapshot artifacts build by our continuous integration server Continuum,
+  which are available in the {{{https://repository.apache.org/content/repositories/snapshots/org/apache/myfaces/tobago/}Apache snapshot repository.}}
+
+  Alternatively, you can build Tobago yourself. You will need Java 5 and Maven 2.0.9 or later.
+
+  Check-out Tobago from the Apache Subversion repository
+
++------------------------------------------+
+svn co https://svn.apache.org/repos/asf/myfaces/tobago/trunk/ tobago
++------------------------------------------+
+
+  To build the complete project with all sub-modules you have to enter the following command
+
++------------------------------------------+
+mvn install
++------------------------------------------+
+
+  For more information on building Tobago -- especially the 1.0.x branch -- see {{{./getting-started.html}Getting Started.}}
+
+* {Building your own Tobago Application}
+
+  The Tobago example distribution contains the tobago-example-blank WAR, which can act as starting point for
+  your own Tobago application. Since Tobago is based on JSF you need a JSF implementation if the application server
+  you are targeting doesn't contain one.
+
+  If you cannot use Java 5 or higher you can use retrotranslated JARs from the Tobago distribution to develop and
+  run Tobago applications with Java\ 1.4 (only Tobago 1.0.x).
+
+  A Tobago application is a web application which is packaged as a WAR. For a JSF application the <<<FacesServlet>>> needs
+  to be configured in the <<</WEB-INF/web.xml>>>. To serve the internal resources of Tobago directly from the Tobago
+  JARs the Tobago <<<ResourceServlet>>> has to configured, too. The configuration of a Tobago application is controlled
+  by the <<<WEB-INF/tobago-config.xml>>> file. This can be used to declare the available themes and the default theme.
+  Additionally, it can be used to locally add markup -- see the {{Themes}} section for further information.
+
+* {A Minimal Tobago Page}
+
+  You can use JSP or Facelets to write Tobago pages. For Facelets support the extension module tobago-facelets has to
+  be added as a dependency. Because the address book example uses JSP as rendering technology we will focus on JSP
+  for now.
+
+  Tobago provides two tag libraries --  the core library and the extension library. The corresponding TLDs contain
+  documentation for the provided tags which is generated from annotations on the underlying tag classes. The core tag
+  library contains basic controls and the extension library convenience tags for pre-assembled tag compositions -- for
+  example a composition of a label and an input control.
+
+  A minimal Tobago JSP page looks like this:
+
++------------------------------------------+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
+<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
+<%@ taglib uri="http://myfaces.apache.org/tobago/extension" prefix="tx" %>
+<f:view>
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+    <tc:out value="Hello World"/>
+  </tc:page>
+</f:view>
++------------------------------------------+
+
+  A similar page is part of the blank WAR: \
+  {{https://svn.apache.org/repos/asf/myfaces/tobago/tags/tobago-1.0.22/example/blank/src/main/webapp/helloWorld.jsp}}
+
+{Creating a Tobago page}
+
+  The address book example needs an address editing page to add new addresses to the address book and to update
+  existing ones.
+
+  A simple version of an address editor allows to edit the first and last name of a person and basic address data
+  like street, house number and city. Such an editor could look like this:\
+  \ 
+
+[images/guide-simple-editor.png] Simple Address Editor
+
+  This page is generated by the following code:
+
++------------------------------------------+
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
+<%@ taglib uri="http://myfaces.apache.org/tobago/component" prefix="tc" %>
+<%@ taglib uri="http://myfaces.apache.org/tobago/extension" prefix="tx" %>
+<f:view>
+  <tc:page width="400">
+    <f:facet name="layout">
+      <tc:gridLayout rows="fixed;*" margin="10"/>
+    </f:facet>
+    <tc:box label="Address">
+      <f:facet name="layout">
+        <tc:gridLayout rows="fixed;fixed;fixed;fixed"/>
+      </f:facet>
+      <tx:in label="First Name"/>
+      <tx:in label="Last Name"/>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="6*;1*"/>
+        </f:facet>
+        <tx:in label="Street / No"/>
+        <tc:in />
+      </tc:panel>
+
+      <tx:in label="City"/>
+    </tc:box>
+
+    <tc:cell />
+  </tc:page>
+</f:view>
++------------------------------------------+
+
+  We have a box with the label "Address" containing four rows of input controls for first name, last name, street, 
+  house number, and city.
+
+* {Basic Controls}
+
+  HTML offers a decent set of basic controls. These controls form the basis of the Tobago controls including
+  single-line input controls, text areas, check boxes, radio buttons, links, buttons, labels, and others.
+
+  The Tobago demo contains an overview page for the basic controls.\
+  \ 
+
+[images/guide-basic-controls.png] Basic Controls  
+
+  Live demo of the basic controls: {{http://www.irian.biz/tobago-example-demo-2.0.x/faces/content/01-basic/basic.xhtml}}
+
+  The basic controls page also shows two variants of a normal input control: the date input control and the time input
+  control.
+
+* {Text Input}
+
+  The single-line text input control comes in two flavors: the <<<\<tc:in\>>>> tag from the core tag library (<<<tc>>>
+  is the preferred prefix for the core tag library) and the <<<\<tx:in\>>>> from the extension tag library (<<<tx>>>).
+
+  The extension tag library provides convenient shorthands for boilerplate code. For every input control there
+  is for example an extended version, which layouts a label next before the input field. The label is connected
+  with the field. If the label is clicked the related field is focused.
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tx:in value="#{controller.currentAddress.firstName}"
+    label="#{bundle.editorFirstName}" required="true">
+  <f:validateLength minimum="2" maximum="20"/>
+</tx:in>
++------------------------------------------+
+
+  The <<<value>>> attribute refers the content of the control. If a value binding is used, this content can be written
+  back into a bean property.
+
+  The <<<label>>> attribute generates the textual description for the control. The theme decides how the label is
+  actually rendered, for example it assigns a default width. This width can be overwritten with the <<<labelWidth>>>
+  attribute. If you utilize a value binding to a resource bundle declared by a <<<\<tc:loadBundle\>>>> tag, you
+  automatically get localization for the text labels. An underscore in the label transforms the following
+  character into an access key. The theme normally underlines the access key to make this circumstance visible to
+  the user. The access key can be used to quickly focus the related input control by pressing <<<Alt>>> in combination
+  with the access key.
+
+  If the control is marked as <<<required>>> the respective validation takes place. Additionally, the theme tries to
+  visualize this fact. Speyside renders a small check mark icon inside the field, which vanishes if the field
+  contains any data.
+
+  For more information about the possible attributes of an input tag see the TLD documentation for
+  {{{http://myfaces.apache.org/tobago/tobago-core/tlddoc/tc/in.html}<<<\<tc:in\>>>>}} and
+  {{{http://myfaces.apache.org/tobago/tobago-core/tlddoc/tx/in.html}<<<\<tx:in\>>>>}}.
+
+* {Sheet}
+
+  The sheet control is used to display tabular data.
+
+  The address book example uses a sheet to give an overview of all stored addresses.\
+  \ 
+
+[images/guide-sheet.png] Sheet
+
+  Live demo of a sheet: {{http://www.irian.biz/tobago-example-demo-2.0.x/faces/content/02-sheet/sheet.xhtml}}
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:sheet columns="1*;1*;1*" value="#{controller.currentAddressList}"
+    var="address" state="#{controller.selectedAddresses}"
+    sortActionListener="#{controller.sheetSorter}" rows="25"
+    showRowRange="left" showPageRange="right" showDirectLinks="center">
+  <tc:columnEvent event="dblclick" >
+    <tc:command action="#{controller.editAddress}"/>
+  </tc:columnEvent>
+  <tc:column id="firstName" label="#{bundle.listFirstName}" sortable="true"
+      rendered="#{controller.renderFirstName}">
+    <tc:out value="#{address.firstName}"/>
+  </tc:column>
+  <tc:column id="lastName" label="#{bundle.listLastName}" sortable="true"
+      rendered="#{controller.renderLastName}">
+    <tc:out value="#{address.lastName}"/>
+  </tc:column>
+  <tc:column id="dayOfBirth" label="Birthday" sortable="true"
+      rendered="#{controller.renderDayOfBirth}">
+    <tc:out value="#{address.dayOfBirth}">
+      <f:convertDateTime pattern="#{bundle.editorDatePattern}"/>
+    </tc:out>
+  </tc:column>
+</tc:sheet>
++------------------------------------------+
+
+* {Tab Group}
+
+  The tab group control displays rectangular content in the same area of the screen with the help of tab panels.
+
+  In the address book example the tab group is used to structure the input controls for an address into three groups
+  for general, business, and miscellaneous information.\
+  \ 
+
+[images/guide-tab-group.png] Tab Group
+
+  Live demo of a tab group: {{http://www.irian.biz/tobago-example-demo-2.0.x/faces/content/04-tab/tab.xhtml}}
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:tabGroup switchType="reloadTab" immediate="true">
+  <tc:tab label="#{bundle.editorTabPersonal}">
+    <jsp:include page="tab/personal.jsp"/>
+  </tc:tab>
+
+  <tc:tab label="#{bundle.editorTabBusiness}" rendered="#{!controller.simple}">
+    <jsp:include page="tab/business.jsp"/>
+  </tc:tab>
+
+  <tc:tab label="#{bundle.editorTabMisc}" rendered="#{!controller.simple}">
+    <jsp:include page="tab/misc.jsp"/>
+  </tc:tab>
+</tc:tabGroup>
++------------------------------------------+
+
+* {Menu}
+
+  The menu control can be used to render a menu bar at the top of a screen like it is typically used in desktop
+  applications. But the location for menus is not limited to this place.\
+  \ 
+  
+[images/guide-menu.png] Menu
+
+  Live demo of a menu: {{http://www.irian.biz/tobago-example-demo-2.0.x/faces/content/05-toolBar/toolBar.xhtml}}
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:menuBar>
+  <tc:menu label="#{bundle.menuFile}">
+    <tc:menuCommand label="#{bundle.menuFileNew}" action="#{controller.createAddress}" immediate="true"
+        image="image/org/tango-project/tango-icon-theme/16x16/actions/contact-new.png"/>
+    <tc:menuCommand label="Add Dummy Addresses" action="#{controller.addDummyAddresses}" immediate="true"/>
+    <tc:menuSeparator/>
+    <tc:menuCommand label="#{bundle.admin}" action="#{admin.admin}"
+        image="image/org/tango-project/tango-icon-theme/16x16/categories/preferences-system.png"/>
+    <tc:menuSeparator/>
+    <tc:menuCommand label="Logout" action="#{controller.logout}"
+        image="image/org/tango-project/tango-icon-theme/16x16/actions/system-log-out.png"/>
+  </tc:menu>
+
+  <tc:menu label="#{bundle.menuSettings}">
+    ...
+  </tc:menu>
+
+  <tc:menu label="#{bundle.menuHelp}">
+    ...
+  </tc:menu>
+</tc:menuBar>
++------------------------------------------+
+
+* {Tool Bar}
+
+  The tool bar control is used to render a special rectangular area of buttons. There are two versions of toolbars:
+  a standalone version and version that embeds itself in the border of a box. To embed a tool bar it has to be
+  attached to a <<<\<tc:box\>>>> via a toolbar facet.
+
+  The address book example uses a tool bar below the menu to provide convenient access to the most common actions
+  from the menu.\
+  \ 
+
+[images/guide-toolbar.png] Tool Bar
+
+  Live demo of a tool bar: {{http://www.irian.biz/tobago-example-demo-2.0.x/faces/content/05-toolBar/toolBar.xhtml}}
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:toolBar iconSize="big">
+  <tc:button label="#{bundle.toolbarAddressList}" action="#{controller.search}" immediate="true"
+      image="image/org/tango-project/tango-icon-theme/32x32/mimetypes/x-office-address-book.png"
+      disabled="#{facesContext.viewRoot.viewId == '/application/list.jsp'}"/>
+  <tc:button label="#{bundle.listNew}" action="#{controller.createAddress}"
+      image="image/org/tango-project/tango-icon-theme/32x32/actions/contact-new.png"/>
+  <tc:button label="#{bundle.toolbarAbout}"
+      image="image/org/tango-project/tango-icon-theme/32x32/apps/help-browser.png">
+    <tc:popupReference for=":page:about"/>
+  </tc:button>
+  <tc:button label="#{bundle.admin}" action="#{admin.admin}"
+      image="image/org/tango-project/tango-icon-theme/32x32/categories/preferences-system.png"/>
+</tc:toolBar>
++------------------------------------------+
+
+* {Popup}
+
+  Popups are used to render small modal dialogs inside the current screen. The original screen is disabled until
+  the popup is released with one of the popup buttons.\
+  \ 
+
+[images/guide-popup.png] Tool Bar
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:popup id="about" width="300" height="220" left="200" top="200">
+  <tc:box label="About">
+    <f:facet name="layout">
+      <tc:gridLayout rows="150px;*;fixed" columns="150px;*"/>
+    </f:facet>
+
+    <tc:image width="150" height="150"
+        value="image/org/tango-project/tango-icon-theme/address-book-splash-screen.png"/>
+    <tc:panel>
+      ...
+    </tc:panel>
+
+    <tc:cell spanX="2"/>
+
+    <tc:cell spanX="2">
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;fixed"/>
+        </f:facet>
+        <tc:cell/>
+        <tc:button label="OK">
+          <tc:attribute name="popupClose" value="immediate"/>
+        </tc:button>
+      </tc:panel>
+    </tc:cell>
+  </tc:box>
+</tc:popup>
++------------------------------------------+
+
+* {File Upload}
+
+  The file select control can be used to upload files.\
+  \ 
+
+[images/guide-upload.png] File Upload
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:file value="#{controller.uploadedFile}" required="true">
+  <tc:validateFileItem contentType="image/*"/>
+</tc:file>
++------------------------------------------+
+
+{Features and Concepts}
+
+* {Layout}
+
+  Tobago organizes the placement of components with the help of layout managers. The main layout manager
+  is called grid layout. It divides the available rectangular space into grid cells. The grid is spawned
+  by the column and row values of the <<<\<tc:gridLayout\>>>> tag. The syntax of these values is based on
+  the {{{http://www.w3.org/TR/html401/types.html#type-multi-length}multi-length notation}} known from HTML.
+
+  To add a layout manager to a container like box, panel or page you have to add a layout facet (i.e. a facet
+  with the name 'layout') to the respective container tag.
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:panel>
+  <f:facet name="layout">
+    <tc:gridLayout columns="*" rows="fixed;fixed;*"/>
+  </f:facet>
+  <tx:in label="First Name"/>
+  <tx:in label="Last Name"/>
+  <tc:cell />
+</tc:panel>
++------------------------------------------+
+
+  In this example we place to two input controls with labels into two consecutive rows. Below the two input fields
+  we add a spacer element. The layout token '<<<fixed>>>' advises the layout manager to give the input control
+  the height, which this kind of control normally possesses in the selected theme.
+
+  The values of the column and row attributes of the <<<\<tc:gridLayout\>>>> tag can contain a semicolon separated
+  list of layout tokens. A layout token can be an exact length in pixels like <<<200px>>>, a percentage length like <<<25%>>>,
+  a relative length like <<<2*>>>, or a specific length called <<<fixed>>>, which's exact length is determined by the
+  theme and make sure the control is usable -- a single-line input control for example needs to be so high that
+  characters from the assigned font can be read inside the control.
+
+  Relative lengths are determined last by the layout manager. The available remaining space is distributed among the
+  existing relative lengths. Each length receives space proportional to the integer before the '<<<*>>>'. A single
+  '<<<*>>>' is a shorthand for '<<<1*>>>'.
+
+  The layout manager handles the <<<rendered>>> attribute of controls, too. If the <<<rendered>>> attribute is
+  dynamically defined by a value binding, the page can contain fewer controls in some cases than in others.
+  The layout manager can then distribute the newly available space between the remaining relative and percentage
+  lengths.
+
+* {Themes}
+
+  A theme defines how the structured view is actually rendered. It provides the look & feel of the controls inside a
+  view. It appoints colors, dimensions, spacing, fonts and other graphical properties.
+
+  Tobago includes a small collection of themes called after cities on the island Tobago: Scarborough, Speyside,
+  Charlotteville, and Richmond. Scarborough is a basic theme, which tries to focus on features of plain
+  HTML, Speyside is the main theme of Tobago, Charlotteville and Richmond are mainly color variations of Speyside.\
+  \  
+
+[images/guide-theme-scarborough.png] Scarborough
+
+  Scarborough\
+  \ 
+
+[images/guide-theme-speyside.png] Speyside
+
+  Speyside\
+  \ 
+
+[images/guide-theme-charlotteville.png] Charlotteville
+
+  Charlotteville\
+  \ 
+
+[images/guide-theme-richmond.png] Richmond
+
+  Richmond
+
+* {Markup}
+
+  Since you don't have direct control over design without writing your own theme, Tobago supports the concept of
+  markup. You can assign certain logical markup values to a control to fine-tune the rendering. A theme specifies
+  the supported markup for every control. The standard theme already provides some helpful markups.\
+  \ 
+
+*-----------------------+-------------------------+
+| <<<\<tc:out\>>>>      | strong, deleted, number |
+*-----------------------+-------------------------+
+| <<<\<tc:in\>>>>       | number                  |
+*-----------------------+-------------------------+
+| <<<\<tc:label\>>>>    | number                  |
+*-----------------------+-------------------------+
+| <<<\<tc:treeNode\>>>> | strong                  |
+*-----------------------+-------------------------+
+
+  Also see the {{{https://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml}standard <<<tobago-config.xml>>>}}
+
+  The markup <<<strong>>> is normally emphasized, <<<deleted>>> is rendered struck out, and <<<number>>> is
+  right aligned. Multiple markups can be combined as a comma separated list:
+
++------------------------------------------+
+...
+<tc:label value="Normal"/>
+<tc:out value="999.99"/>
+
+<tc:label value="Number"/>
+<tc:out markup="number" value="999.99"/>
+
+<tc:label value="Emphasized"/>
+<tc:out markup="strong" value="999.99"/>
+
+<tc:label value="Emphasized Number"/>
+<tc:out markup="number,strong" value="999.99"/>
+...
++------------------------------------------+
+
+  This code fragment is rendered like this:\
+  \ 
+
+[images/guide-markup.png] Markup example
+
+  You can add markup in your own theme or extend the current themes on the fly by adding a <<<\<renderers\>>>> section
+  into the <<<tobago-config.xml.>>>
+
+  The address book example adds markup values to the <<<\<tc:progress\>>>> control to be able to colorize the control
+  depending on the criticallity of the progress value. On the administration page the progress control is used to
+  visualize the memory consumption of the VM.
+
++------------------------------------------+
+<renderers>
+  <renderer>
+    <name>Progress</name>
+    <supported-markup>
+      <markup>ok</markup>
+      <markup>warn</markup>
+      <markup>error</markup>
+    </supported-markup>
+  </renderer>
+</renderers>
++------------------------------------------+
+
+  See the {{{https://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-example/tobago-example-addressbook-war/src/main/webapp/WEB-INF/tobago-config.xml}address book <<<tobago-config.xml>>>}} for a complete example.
+
+  The various progress variants look like this:\
+  \ 
+
+[images/guide-progress.png] Progress markup
+
+
+  Markup attributes are rendered into HTML as extra CSS style classes, which can be used to modify the normal
+  styling of a control. In the progress example the following CSS is added to the Speyside theme:
+
++------------------------------------------+
+.tobago-progress-value-markup-ok {
+  background: green;
+}
+
+.tobago-progress-value-markup-warn {
+  background: yellow;
+}
+
+.tobago-progress-value-markup-error {
+  background: red;
+}
++------------------------------------------+
+
+  See the address book example 
+  {{{https://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-example/tobago-example-addressbook-web/src/main/webapp/tobago-resource/html/speyside/standard/style/tobago.css}Speyside <<<tobago.css>>>}}.
+
+  The <<<tobago.css>>> file is collected by the Tobago resource manager and can be used to overwrite and extend the
+  default <<<tobago.css>>> file of the theme.
+
+  Tobago 1.0.x and Tobago 1.5.x are using the old name <<<style.css>>>, since Tobago 2.0.0
+  <<<tobago.css>>> is used, <<<style.css>>> will also be included for compatibility (in Tobago 2.x).
+
+  The {{{https://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-theme/tobago-theme-example/}example theme}} provides
+  an example for styling sheet cells and contains more complex examples of markup, which need addtional JavaScript
+  to generate more dynamic behaviours like fade-out effects or client-side change detection.
+
+* {Partial Rendering}
+
+  To avoid the reload of complete screens Tobago provides partial rendering, which advises the client to update
+  only parts of the screen to optimize the amount of data sent to the client and the time to render necessary updates.
+  Some controls like the tab control and the sheet directly support partial rendering. Whereas container
+  controls like the generic panel allow to group arbitrary controls to be able to update them exclusively as a group.
+
+* {Virtual Forms}
+
+  The page tag establishes an implicit form for all controls on the screen. The form tag allows to divide these
+  controls into smaller groups to be able to manage validation only for these grouped controls.
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+<tc:form>
+  <tx:selectOneChoice label="#{bundle.footerLanguage}"
+      value="#{controller.language}">
+    <f:selectItems value="#{controller.languages}"/>
+    <f:facet name="change">
+      <tc:command action="#{controller.languageChangedList}"/>
+    </f:facet>
+  </tx:selectOneChoice>
+</tc:form>
++------------------------------------------+
+
+* {Security}
+
+  The extension module tobago-security allows to protect method bindings with the help of annotations. The module
+  provides alternative command components with security handling. The available annotations are <<<...@RolesAllowed>>>,
+  <<<...@DenyAll>>>, and <<<...@PermitAll>>>.
+
+  A code fragment from the address book example:
+
++------------------------------------------+
+public class AdminController {
+
+  @RolesAllowed("admin")
+  public String admin() {
+    return OUTCOME_ADMIN;
+  }
+
+  ...
+}
++------------------------------------------+
diff --git a/tobago-3.0.x/src/site/apt/howto-test.apt b/tobago-3.0.x/src/site/apt/howto-test.apt
new file mode 100644
index 0000000..06a1a88
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/howto-test.apt
@@ -0,0 +1,57 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+ Howto create tests for Tobago Demo 3.0 or higher
+ ------
+
+Howto create QUnit tests for Tobago Demo 3.0 or higher
+
+  [[1]] Choose a \<sample\>.xhtml file for testing.
+
+  [[2]] Create a \<sample\>.test.js file (with same name).
+
+  [[3]] Add a {{{http://api.qunitjs.com/QUnit.test/}QUnit test}} to the \<sample\>.test.js.
+
++----------------------------------------
+  QUnit.test("Testtitle", function(assert) {
+    ...
+  });
++----------------------------------------
+
+    [[a]] The test will run in a different frame.
+    To get an element in the test frame use <<<jQueryFrame()>>> instead of <<<jQuery()>>>.
+
+    [[b]] To wait for a submit use <<<jQuery("#page\\:testframe").load()>>>.
+
+    [[c]] To wait for an AJAX event use <<<waitForAjax(waitingDone, executeWhenDone)>>>.
+    The function <<<waitingDone>>> must return false if still waiting and true if the waiting is done.
+    The function <<<executeWhenDone>>> is executed afterwards.
+
+  [[4]] Add the test to QUnitTests.
+
++----------------------------------------
+  @Test
+  public void testname() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/.../testname.xhtml";
+    runStandardTest(page);
+  }
++----------------------------------------
+
+  [[5]] Run the tests from QUnitTests or type
+
++----------------------------------------
+  mvn verify -Pqunit-integration-tests
++----------------------------------------
diff --git a/tobago-3.0.x/src/site/apt/index.apt b/tobago-3.0.x/src/site/apt/index.apt
new file mode 100644
index 0000000..ea33d09
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/index.apt
@@ -0,0 +1,1125 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+ 
+ ------
+ Apache Tobago
+ ------
+
+Apache Tobago
+
+  The goal of Apache Tobago\u2122 is to provide the community with a well designed set of user
+  interface components based on JSF and run on MyFaces.
+
+  Tobago is more than just a tag library. The following statements characterize
+  Tobago and make it different from other frameworks:
+
+  * The focus of Tobago is to create business applications without the need of coding
+    HTML, CSS and JavaScript. The development of Tobago pages follows more the development of
+    conventional user interfaces than the creation of web pages.
+
+  * The UI components are abstracted from HTML and any layout information that does
+    not belong to the general page structure. The final output format is determined
+    by the client/user-agent.
+
+  * A theming mechanism makes it easy to change the look and feel and to provide
+    special implementations for certain browsers. A fallback solution ensures that
+    as much code is reused for new themes as possible.
+
+  * A layout manager is used to arrange the components automatically. This means, no
+    manual laying out with HTML tables or other constructs is needed.
+
+  []
+
+  The development of Tobago started in 2002.
+
+
+News
+
+* January 17, 2016 - MyFaces Tobago 3.0.1 Released
+
+      The MyFaces Tobago component library in version 3.0.1 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12338730}Jira}}.
+
+      Major changes are:
+
+      * Bug fixes
+
+      \ {}
+      ~~ hack for a bit space
+
+* December 16, 2016 - MyFaces Tobago 3.0.0 Released
+
+      The MyFaces Tobago component library in version 3.0.0 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12325880}Jira}}.
+
+      Major changes (regarding version 2) are:
+
+      * LayoutManager moved from Server to CSS (or JS in limited cases)
+
+      * Themes using CSS lib Bootstrap 4 http://getbootstrap.com/
+
+      * Responsiveness
+
+      * Simplify many things by using current technologies
+
+      * Easier to integrate Tobago in other projects
+
+      * Easier to integrate Libraries in Tobago
+
+      * In general: do less magic, but more standard
+
+      []
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* December 7, 2016 - MyFaces Tobago 3.0.0-beta-1 Released
+
+      The MyFaces Tobago component library in version 3.0.0-beta-1 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12333888}Jira}}.
+
+      Major changes are:
+
+      * Theme building appropriate with Bootstrap
+
+      * Drop ResourceManager
+
+      * New tag <<<\<tc:event\>>>> for non ajax client behavior
+
+      * Update Bootstrap 4 alpha 5
+
+      * Standard mechanism to load XML Properties
+
+      * Move client data to TobagoContext
+
+      * End of theme-dependent renderer selection
+
+      * Reduce jQuery UI lib
+
+      * Rename <<<\<tc:commands\>>>> (aka. <<<\<tc:commandGroup\>>>>) to <<<\<tc:links\>>>>
+
+      * Actions are not visible, when roles are not allowed
+
+      * HTML lang attribute for hyphenation support
+
+      * Several fixes
+
+      []
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* November 1, 2016 - MyFaces Tobago 3.0.0-alpha-7 Released
+
+      The MyFaces Tobago component library in version 3.0.0-alpha-7 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12338278}Jira}}.
+
+      Major changes are:
+
+      * New component tc:figure
+
+      * Rename action facet to load facet
+
+      * Improve column resizing in sheet
+
+      * Label layout support for tc:selectBooleanCheckbox
+
+      * Some bug fixes
+
+      []
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* September 20, 2016 - MyFaces Tobago 3.0.0-alpha-6 Released
+
+      The MyFaces Tobago component library in version 3.0.0-alpha-6 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12338231}Jira}}.
+
+      Major changes are:
+
+      * HTML of tc:button and tc:link changed
+
+      * Removing old tags tc:menu*
+
+      * Update Bootstrap alpha 4
+
+      * some bug fixes
+
+      []
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* September 8, 2016 - MyFaces Tobago 2.0.10 Released
+
+      The MyFaces Tobago component library in version 2.0.10 has been released.
+
+      Release notes can be found in
+      {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12334742}Jira}}.
+
+      Major changes are:
+
+      * Multifile-Upload Component
+
+      * New SplitLayout Component in tobago-core
+
+      \ {}
+      ~~ hack for a bit space
+
+
+* August 28, 2016 - MyFaces Tobago 3.0.0-alpha-5 Released
+
+      The MyFaces Tobago component library in version 3.0.0-alpha-5 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12338164}Jira}}.
+
+      Major changes are:
+
+      * new input-groups
+
+      * update Bootstrap to alpha 3
+
+      * better suggest component
+
+      * better upload component
+
+      * better AJAX handling
+
+      * fix converter for type java.lang.String
+
+      * some other fixes
+
+      []
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* July 17, 2016 - MyFaces Tobago 3.0.0-alpha-4 Released
+
+      The MyFaces Tobago component library in version 3.0.0-alpha-4 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12337842}Jira}}.
+
+      Major changes are:
+
+      * buttons-, nav-, bar-tags
+
+      * collapsible (also for popups)
+
+      * security annotations
+
+      * new date/time-picker
+
+      []
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* June 1, 2016 - Changes in the trunk
+
+      There are some refactorings in the trunk, if using the trunk please follow these steps:
+
+      * Rename <<<\<tc:nav\>>>> to <<<\<tc:bar\>>>>
+
+      * Rename <<<\<tc:commandGroup\>>>> to <<<\<tc:commands\>>>>
+
+      * <<<\<tc:nav\>>>> attributes label and image was removed: use <<<\<f:facet name="brand"\>>>> with a <<<\<tc:link\>>>> inside
+
+      * The attribute <<<execute>>> of <<<\<f:ajax\>>>> is now implemented.
+
+* April 26, 2016 - Switching Subversion trunk to Tobago 3.0.x
+
+      Today the Subversion <<<trunk>>> has been moved to <<<branches/tobago-2.0.x>>> and
+      the <<<branches/tobago-3.0.x>>> has been moved to trunk.
+
+      To migrate an already checked out project, please check at first your current location like:
+
++----------------------------------------
+svn info | grep "Repository Root"
++----------------------------------------
+
+      The result shows you whether you are using <<<http>>> or <<<https>>>
+
+      To switch from the old trunk to the 2.0.x branch use:
+
++----------------------------------------
+svn switch https://svn.apache.org/repos/asf/myfaces/tobago/branches/tobago-2.0.x/
++----------------------------------------
+
+      To switch from the old 3.0.x branch to the new trunk use:
+
++----------------------------------------
+svn switch https://svn.apache.org/repos/asf/myfaces/tobago/trunk/
++----------------------------------------
+
+      \ {}
+      ~~ hack for a bit space
+
+* April 20, 2016 - MyFaces Tobago 3.0.0-alpha-3 Released
+
+      The MyFaces Tobago component library in version 3.0.0-alpha-3 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12334363}Jira}}.
+
+      Major changes are
+
+      * integration of <<<\<f:ajax\>>>>,
+
+      * upgrading from Bootstrap 3 to Bootstrap 4 (alpha) and
+
+      * using Servlet 3.0 API for uploading files (instead of commons-fileupload).
+
+      []
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* February 1, 2016 - MyFaces Tobago 2.0.9 Released
+
+      The MyFaces Tobago component library in version 2.0.9 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12332146}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+
+* December 21, 2015 - MyFaces Tobago 3.0.0-alpha-2 Released
+
+      The MyFaces Tobago component library in version 3.0.0-alpha-2 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12333887}Jira}}.
+
+      Major change since alpha 1 is replacing "Glyphicons" with "Font Awesome".
+      This may be the last version using Bootstrap 3.
+      The next alpha of Tobago will properly using Bootstrap 4, where the second alpha was released a few days ago.
+
+      Also see section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* November 11, 2015 - MyFaces Tobago 3.0.0-alpha-1 Released
+
+      The MyFaces Tobago component library in version 3.0.0-alpha-1 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12325880}Jira}}.
+
+      See section: {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml} What's new in Tobago 3.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* July 16, 2015 - MyFaces Tobago 1.0.42 Released
+
+      The MyFaces Tobago component library in version 1.0.42 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12326705}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+
+* June 9, 2015 - MyFaces Tobago 2.0.8 Released
+
+      The MyFaces Tobago component library in version 2.0.8 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12329723}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+
+* March 22, 2015 - MyFaces Tobago 2.0.7 Released
+
+      The MyFaces Tobago component library in version 2.0.7 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12329376}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+
+* February 24, 2015 - MyFaces Tobago 2.0.6 Released
+
+      The MyFaces Tobago component library in version 2.0.6 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12329161}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+
+* December 20, 2014 - MyFaces Tobago 2.0.5 Released
+
+      The MyFaces Tobago component library in version 2.0.5 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12329025}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+
+* November 22, 2014 - MyFaces Tobago 2.0.4 Released
+
+      The MyFaces Tobago component library in version 2.0.4 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12328041}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* Oktober 12, 2014 - MyFaces Tobago 2.0.3 Released
+
+      The MyFaces Tobago component library in version 2.0.3 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12328040}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* August 26, 2014 - MyFaces Tobago 2.0.2 Released
+
+      The MyFaces Tobago component library in version 2.0.2 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12327500}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* August 6, 2014 - MyFaces Tobago 2.0.1 Released
+
+      The MyFaces Tobago component library in version 2.0.1 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12327455}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* July 21, 2014 - MyFaces Tobago 2.0.0 Released
+
+      The MyFaces Tobago component library in version 2.0.0 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12321253}Jira}}.
+
+      See section: {{{./new-2.0.html} What's new in Tobago 2.0?}}
+
+      \ {}
+      ~~ hack for a bit space
+
+* June 2, 2014 - MyFaces Tobago 2.0.0-beta-4 Released
+
+      The MyFaces Tobago component library in version 2.0.0-beta-4 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12326809}Jira}}.
+
+      Highlights:
+
+        * Sanitize content against XSS.
+
+        * Examples to integrate {{{http://ckeditor.com/}CKEditor™}} and {{{http://www.tinymce.com/}TinyMCE}}.
+
+        * Bugfixes
+
+      \ {}
+      ~~ hack for a bit space
+
+* May 5, 2014 - MyFaces Tobago 2.0.0-beta-3 Released
+
+      The MyFaces Tobago component library in version 2.0.0-beta-3 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12326693}Jira}}.
+
+      Highlights:
+
+        * Icons and toolbar buttons in tabs.
+
+        * Bugfixes
+
+      \ {}
+      ~~ hack for a bit space
+
+* March 31, 2014 - MyFaces Tobago 2.0.0-beta-2 Released
+
+      The MyFaces Tobago component library in version 2.0.0-beta-2 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12326662}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* March 25, 2014 - MyFaces Tobago 2.0.0-beta-1 Released
+
+      The MyFaces Tobago component library in version 2.0.0-beta-1 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12325856}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* March 25, 2014 - MyFaces Tobago 1.5.13 Released
+
+      The MyFaces Tobago component library in version 1.5.13 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12325858}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* March 25, 2014 - MyFaces Tobago 1.0.41 Released
+
+      The MyFaces Tobago component library in version 1.0.41 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12324116}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* January 13, 2014 - New Branch for Tobago 3.0 Created
+
+      There was a new branch in the Subversion to start development on the next major version:
+      {{{https://svn.apache.org/repos/asf/myfaces/tobago/branches/tobago-3.0.x}Tobago 3.0}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* January 11, 2014 - MyFaces Tobago 1.5.12 Released
+
+      The MyFaces Tobago component library in version 1.5.12 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12325597}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* January 7, 2014 - MyFaces Tobago 2.0.0-alpha-3 Released
+
+      The MyFaces Tobago component library in version 2.0.0-alpha-3 has been released.
+
+      Release notes can be found in
+      {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12325247}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* November 11, 2013 - MyFaces Tobago 1.5.11 Released
+
+      The MyFaces Tobago component library in version 1.5.11 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12324453}Jira}}.
+
+      \ {}
+      ~~ hack for a bit space
+
+* October 14, 2013 - MyFaces Tobago 2.0.0-alpha-2 Released
+
+      The MyFaces Tobago component library in version 2.0.0-alpha-2 has been released.
+
+      Release notes can be found in
+      {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12324818}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* August 7, 2013 - MyFaces Tobago 2.0.0-alpha-1 Released
+
+      The MyFaces Tobago component library in version 2.0.0-alpha-1 has been released.
+
+      Release notes can be found in
+      {{{https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=12321874}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* Mai 27, 2013 - MyFaces Tobago 1.5.10 Released
+
+      The MyFaces Tobago component library in version 1.5.10 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12324008}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* April 9, 2013 - MyFaces Tobago trunk version is now 2.0.x
+
+      Because of the extensive upgrade of this version, the major version number was increased.
+
+      Version 1.6.x will be replaced with 2.0.x.
+
+  \ {}
+  ~~ hack for a bit space
+
+* March 4, 2013 - MyFaces Tobago 1.5.9 Released
+
+      The MyFaces Tobago component library in version 1.5.9 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12323506}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* March 4, 2013 - MyFaces Tobago 1.0.40 Released
+
+     The MyFaces Tobago component library in version 1.0.40 has been released.
+
+     Release notes can be found in
+     {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12319866}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* October 25, 2012 - MyFaces Tobago 1.5.8 Released
+
+      The MyFaces Tobago component library in version 1.5.8 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12322450}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* July 11, 2012 - MyFaces Tobago 1.5.7 Released
+
+      The MyFaces Tobago component library in version 1.5.7 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12321444}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* June 27, 2012 - MyFaces Tobago 1.6.0-beta-2 Released
+
+      The MyFaces Tobago component library in version 1.6.0-beta-2 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12321701}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* June 6, 2012 - MyFaces Tobago 1.6.0-beta-1 Released
+
+      The MyFaces Tobago component library in version 1.6.0-beta-1 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12321691}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* Mai 22, 2012 - New branch created
+
+      The 1.5.x branch has been created. The trunk is now 1.6.x.
+
+      The new trunk contains API changes with respect to the tree.
+
+  \ {}
+  ~~ hack for a bit space
+
+* Mai 21, 2012 - MyFaces Tobago 1.5.6 Released
+
+      The MyFaces Tobago component library in version 1.5.6 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12321251}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* Mai 11, 2012 - MyFaces Tobago 1.5.5 Released
+
+      The MyFaces Tobago component library in version 1.5.5 has been released.
+
+      Release notes can be found in
+      {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12319865}Jira}}.
+
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* March 5, 2012 - MyFaces Tobago 1.5.4 Released
+
+     The MyFaces Tobago component library in version 1.5.4 has been released.
+
+     Release notes can be found in
+     {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12319864}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* February 19, 2012 - MyFaces Tobago 1.0.39 Released
+
+     The MyFaces Tobago component library in version 1.0.39 has been released.
+
+     Release notes can be found in
+     {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12319455}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* February 15, 2012 - MyFaces Tobago 1.5.3 Released
+
+     The MyFaces Tobago component library in version 1.5.3 has been released.
+
+     Release notes can be found in
+     {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12319499}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* January 24, 2012 - MyFaces Tobago 1.5.2 Released
+
+    The MyFaces Tobago component library in version 1.5.2 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12319248}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* December 12, 2011 - MyFaces Tobago 1.5.1 Released
+
+    The MyFaces Tobago component library in version 1.5.1 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12319154}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* November 30, 2011 - MyFaces Tobago 1.5.0 Released
+
+    The MyFaces Tobago component library in version 1.5.0 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12312205}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* November 9, 2011 - MyFaces Tobago 1.5.0-beta-2 Released
+
+    The MyFaces Tobago component library in version 1.5.0-beta-2 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12317052}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* October 23, 2011 - MyFaces Tobago 1.0.38 Released
+
+    The MyFaces Tobago component library in version 1.0.38 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12317350}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* July 14, 2011 - MyFaces Tobago 1.5.0-beta-1 Released
+
+    The MyFaces Tobago component library in version 1.5.0-beta-1 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12316222}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* July 14, 2011 - MyFaces Tobago 1.0.37 Released
+
+    The MyFaces Tobago component library in version 1.0.37 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12316458}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* Mai 13, 2011 - MyFaces Tobago 1.0.36 Released
+
+    The MyFaces Tobago component library in version 1.0.36 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12316297}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* March 13, 2011 - MyFaces Tobago 1.0.35 Released
+
+    The MyFaces Tobago component library in version 1.0.35 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12316183}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* February 23, 2011 - MyFaces Tobago 1.5.0-alpha-2 Released
+
+    The MyFaces Tobago component library in version 1.5.0-alpha-2 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12314340}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* February 23, 2011 - MyFaces Tobago 1.0.34 Released
+
+    The MyFaces Tobago component library in version 1.0.34 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12316162}Jira}}.
+
+
+  \ {}
+  ~~ hack for a bit space
+
+* February 8, 2011 - MyFaces Tobago 1.0.33 Released
+
+    The MyFaces Tobago component library in version 1.0.33 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12315586}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* November 30, 2010 - MyFaces Tobago 1.0.32 Released
+
+    The MyFaces Tobago component library in version 1.0.32 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12315489}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* November 4, 2010 - MyFaces Tobago 1.0.31 Released
+
+    The MyFaces Tobago component library in version 1.0.31 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12315383}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* October 6, 2010 - MyFaces Tobago 1.0.30 Released
+
+    The MyFaces Tobago component library in version 1.0.30 has been released.
+
+    Release notes can be found in
+    {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12315336}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* September 23, 2010 - MyFaces Tobago 1.0.29 Released
+
+   The MyFaces Tobago component library in version 1.0.29 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12315262}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* August 18, 2010 - MyFaces Tobago 1.0.28 Released
+
+   The MyFaces Tobago component library in version 1.0.28 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12315109}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* June 7, 2010 - MyFaces Tobago 1.0.27 Released
+
+   The MyFaces Tobago component library in version 1.0.27 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12315099}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* June 4, 2010 - MyFaces Tobago 1.0.26 Released
+
+   The MyFaces Tobago component library in version 1.0.26 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12314961}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* May 1, 2010 - MyFaces Tobago 1.0.25 Released
+
+   The MyFaces Tobago component library in version 1.0.25 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12314527}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* January 22, 2010 - MyFaces Tobago 1.0.24 Released
+
+   The MyFaces Tobago component library in version 1.0.24 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12314193}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* September 6, 2009 - MyFaces Tobago 1.0.23 Released
+
+   The MyFaces Tobago component library in version 1.0.23 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12314159}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* August 16, 2009 - MyFaces Tobago 1.0.22 Released
+
+   The MyFaces Tobago component library in version 1.0.22 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12314027}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* June 12, 2009 - MyFaces Tobago 1.0.21 Released
+
+   The MyFaces Tobago component library in version 1.0.21 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12313470}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* October 26, 2008 - MyFaces Tobago 1.0.20 Released
+
+   The MyFaces Tobago component library in version 1.0.20 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12313447}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* October 6, 2008 - MyFaces Tobago 1.0.19 Released
+
+   The MyFaces Tobago component library in version 1.0.19 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12313372}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* August 26, 2008 - MyFaces Tobago 1.0.18 Released
+
+   The MyFaces Tobago component library in version 1.0.18 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12313150}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* May 20, 2008 - MyFaces Tobago 1.0.17 Released
+
+   The MyFaces Tobago component library in version 1.0.17 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12313084}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* April 16, 2008 - MyFaces Tobago 1.0.16 Released
+
+   The MyFaces Tobago component library in version 1.0.16 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12312966}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* February 18, 2008 - MyFaces Tobago 1.0.15 Released
+
+   The MyFaces Tobago component library in version 1.0.15 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12312929}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* January 26, 2008 - MyFaces Tobago 1.0.14 Released
+
+   The MyFaces Tobago component library in version 1.0.14 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12312878}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* January 11, 2008 -  1.0.x branch has been created
+
+   Trunk is now 1.1.0-SNAPSHOT
+
+  \ {}
+  ~~ hack for a bit space
+
+* December 18, 2007 - MyFaces Tobago 1.0.13 Released
+
+   The MyFaces Tobago component library in version 1.0.13 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12312766}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* October 19, 2007 - MyFaces Tobago 1.0.12 Released
+
+   The MyFaces Tobago component library in version 1.0.12 has been released.
+
+   Release notes can be found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12312498}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* June 3, 2007 - MyFaces Tobago 1.0.11 Released
+
+   MyFaces Tobago 1.0.11 has been released. It is available from the
+   {{{./download.html}download}} page, and in the central Maven repository under
+   Group ID "org.apache.myfaces.tobago".
+
+   More information on this release, including a list of resolved issues, can be
+   found in
+   {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12312376}Jira}}.
+
+  \ {}
+  ~~ hack for a bit space
+
+* March 12, 2007 - MyFaces Tobago 1.0.10 Released
+
+   MyFaces Tobago 1.0.10 has been released.
+
+  \ {}
+  ~~ hack for a bit space
+
+* December 23, 2006 - MyFaces Tobago 1.0.9 Released
+
+   MyFaces Tobago 1.0.9 has been released.
+
+  \ {}
+  ~~ hack for a bit space
+
+* September 20, 2006 - MyFaces Tobago 1.0.8 Released
+
+   MyFaces Tobago 1.0.8 has been released.
+
+  \ {}
+  ~~ hack for a bit space
+
+* March 23, 2006 - Tobago Has Left Incubation
+
+  The goal of Tobago is to provide the community with a well designed set of user
+  interface components based on JSF and run on MyFaces.  Tobago is more than just a tag library,
+  it contains some powerful tools for layouts and themes.  For more information, please visit
+  the Tobago {{{http://myfaces.apache.org/tobago}site}}.
diff --git a/tobago-3.0.x/src/site/apt/new-2.0.apt b/tobago-3.0.x/src/site/apt/new-2.0.apt
new file mode 100644
index 0000000..d315d3d
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/new-2.0.apt
@@ -0,0 +1,200 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+ What's new in Tobago 2.0?
+ ------
+
+{What's new in Tobago 2.0?}
+
+    At July 21, 2014 the version 2.0.0 has been released.
+    Here was a quick overview over the features and changes made in the last time
+    to release this major revision.
+
+    Tobago 2.0.0 contains 184 entries in {{{http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=12321253}Jira}}
+    and most of them are exclusive in this version.
+
+    Please take also a look at the {{{http://www.irian.biz/tobago-example-demo/faces/content/10-intro/50-migration/98-migration/migration20.xhtml}Migration from Tobago 1.5 to 2.0}} guide.
+
+Enhancements
+
+* Date- and Time-Picker
+
+    * Using jQuery UI Datepicker and TimePicker Addon
+
+    * Faster — no server request
+
+    * Better interactivity
+
+    * Old Date-/TimePicker via <<<tobago-config.xml>>>
+
+* Draggable Popups
+
+* Input Suggest
+
+    * New implementation
+
+    * Sub-Tag <<<tc:suggest>>>
+
+    * More configuration options
+
+* Tabs
+
+    * Icons
+
+    * Toolbar buttons
+
+* File upload
+
+    * Looks pretty now in every browser
+
+* Radio Buttons
+
+    * Icons
+
+New Features
+
+* HTML WYSIWYG Editor
+
+      * Integration example in the demo of {{{http://ckeditor.com/}CKEditor™}} and {{{http://www.tinymce.com/}TinyMCE}}
+
+      * Not included, because of incompatible licences or breaks CSP
+
+      * Other possible, but many have disadvantages
+
+* Default Command for Sub-Forms
+
+      * Dependent from the focused input, the default command will be selected
+
+      * Markup to show the command to the user
+    
+* Tree and Tree-Table
+
+      * Big internal refactoring
+
+      * Work internally now with the JSF <<<UIData>>>
+
+      * Free model: <<<DefaultMutableTreeNode>>> is not required any longer, but you can implement <<<javax.faces.model.DataModel>>>
+
+      * TreeTable
+
+      * Infinite Trees possible
+
+      * Selectors: sub-tree selection
+
+* More
+
+      * Dynamic lists in <<<f:selectItems>>> need not glue code (JSF 2.0)
+
+      * Redirect in navigation rules doesn't break layout size
+
+      * Additional possibility to show paging arrows in sheet
+
+      * Automatically create accesskey from underscore is know configurable
+    
+Security
+
+* Content Security Policy
+
+      * To prevent XSS
+
+      * {{{http://www.w3.org/TR/CSP/}W3C Standard}}
+
+      * Idea:
+        
+          * Don't execute any code inside the HTML file
+            
+              * No content in script tags
+
+              * no onclick, nor on* etc.
+            
+          
+          * Don't execute <<<eval(script)>>>
+
+          * Don't apply CSS inside the HTML file
+
+          * Define the sources of any resources
+
+          * Strict separation of code and data
+            
+              * Keep the code in JavaScript Files
+
+              * Put additional data in HTML5 <<<data-*>>> attributes
+            
+          
+        
+      
+      * Browser support: all current, but IE 10 and 11 only "sandbox"
+
+      * Activated by default, can be configured via <<<tobago-config.xml>>>
+
+      * There is also a "report-only" mode for development
+
+
+* Content Security Policy and Tobago
+
+    
+      * All renderers and scripts are refactored to be compliant with CSP
+
+      * Using application specific JavaScript in Tobago
+        
+          * script attribute in command tags is deprecated
+
+          * Problem: when setting non of these attributes: <<<action>>>, <<<script>>>,
+          <<<link>>>, Tobago will create a default
+          action. This can't be changed without breaking compatibility.
+
+          * Solution: <<<omit="true">>>
+
+* Sanitize potentially malicious content (to prevent XSS)
+
+    
+      * <<<tc:textarea>>>, when it contains a <<<tc:dataAttribute>>> with <<<name="html-editor">>>
+
+      * <<<tc:out>>>, when <<<escape="false">>>
+
+      * Default implementation: {{{http://jsoup.org/cookbook/cleaning-html/whitelist-sanitizer}JSoup}}
+        whitelist scanning
+      
+      * Configurable via <<<tobago-config.xml>>>
+
+      * Why? See {{{https://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet#RULE_.236_-_Sanitize_HTML_Markup_with_a_Library_Designed_for_the_Job}OSWAP}}
+
+* More
+
+      * Setting nosniff HTTP header (to prevent XSS)
+
+      * Don't allow to be in a frame (to prevent Frame-Attacks)
+
+      * Both are configurable via <<<tobago-config.xml>>>, default is secure
+    
+
+Internal Refactoring
+
+      * Tree uses subclass of <<<javax.faces.model.DataModel>>>
+
+      * Using Java APT generator
+
+      * Using ' instead of " for HTML attributes (JSON friendly)
+
+      * JavaScript logging via console (plus workaround for old browsers)
+
+      * The <<<theme-config.xml>>> was merged with <<<tobago-config.xml>>>
+
+      * Access the Tobago configuration via the <<<TobagoContext>>>
+
+      * The <<<TobagoConfig>>> is immutable after initialization
+
+      * Add the version of Tobago into the resource URLs to avoid caching problem after updates
diff --git a/tobago-3.0.x/src/site/apt/release-checklist.apt b/tobago-3.0.x/src/site/apt/release-checklist.apt
new file mode 100644
index 0000000..5ea4bc3
--- /dev/null
+++ b/tobago-3.0.x/src/site/apt/release-checklist.apt
@@ -0,0 +1,358 @@
+ ~~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~~ contributor license agreements.  See the NOTICE file distributed with
+ ~~ this work for additional information regarding copyright ownership.
+ ~~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~~ (the "License"); you may not use this file except in compliance with
+ ~~ the License.  You may obtain a copy of the License at
+ ~~
+ ~~      http://www.apache.org/licenses/LICENSE-2.0
+ ~~
+ ~~ Unless required by applicable law or agreed to in writing, software
+ ~~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~~ See the License for the specific language governing permissions and
+ ~~ limitations under the License.
+
+ ------
+ Release Checklist (Developer Info)
+ ------
+
+Release Checklist (Developer Info)
+
+  Checklist of tasks to perform for each release. For general information about Apache releases you may also consult {{{http://www.apache.org/dev/publishing-maven-artifacts.html}Publishing Maven Artifacts}}.
+
+* Preparation
+
+  * You need to add your GPG keys in {{{https://svn.apache.org/repos/asf/myfaces/keys/KEYS}Subversion}} and the {{{https://www.apache.org/dist/myfaces/KEYS}Apache site}} before a release.
+
+  * Ensure that all open bugs and issues in {{{https://issues.apache.org/jira/}Jira}} have been either fixed
+    or moved to an other release version.
+
+  * Ensure that all examples are working with the release candidate.
+
+  * Check the scheduled version number against "semantic versioning".
+
+  * Post a note and ask for problems with the release candidate (see {{Preparation template}} below).
+
+  * Install (or unpack) a jdk 1.4 on your computer (only for Tobago 1.0.x).
+
+  * Please switch to a jdk depending of the version to build:
+
+    * for Tobago 1.0.x use jdk 1.5 or 1.6 for build and 1.7 for deployment.
+
+    * for Tobago 1.5.x use jdk 1.7.
+
+    * for Tobago 2.0.x use jdk 1.8.
+
+    * for Tobago 3.0.x use jdk 1.8.
+
+  * Perform basic checks on an unmodified checkout for all modules:
+
++------------------------+
+# for Tobago 1.0.x
+mvn checkstyle:check rat:check -Pall-modules
+
+# for Tobago 1.5.x and higher
+mvn clean install -Pall-modules && mvn checkstyle:check apache-rat:check animal-sniffer:check -Pall-modules
+
+# for Tobago 2.0.9 and higher
+mvn clean install && mvn checkstyle:check apache-rat:check animal-sniffer:check dependency-check:check
+
+# for Tobago 3.0.0 and higher
+mvn clean install -Pall-modules && mvn checkstyle:check apache-rat:check animal-sniffer:check dependency-check:check -Pall-modules
++------------------------+
+
+* Building the Release (Tobago 1.0.x to 2.0.8)
+
+  * Prepare the release with:
+
++------------------------+
+mvn release:prepare -Pall-modules
++------------------------+
+
+  * Check out a fresh copy of the svn tag:
+
++------------------------+
+cd ..
+svn co https://svn.apache.org/repos/asf/myfaces/tobago/tags/tobago-<version>
+cd tobago-<version>
++------------------------+
+
+  * Deploy the fresh copy to the Nexus repository with the apache-release profile (we are not using release:perform here, because of some different options):
+
++------------------------+
+# for Tobago 1.0.x
+# "install" with Java 1.6 and Maven 2
+mvn install -Papache-release,jdk14retro,generate-assembly --no-plugin-updates -Dnon-default-modules -Djava14.home=${java14.jre}
+# "deploy" with Java 1.7 and Maven 3 (hotfix: also comment out the maven-apt-plugin stuff)
+mvn deploy -Papache-release,generate-assembly --no-plugin-updates -Dnon-default-modules
+
+# for Tobago 1.5.x to 2.0.8
+mvn deploy -Papache-release,generate-assembly --no-plugin-updates -Dnon-default-modules
++------------------------+
+
+* Building the Release (Tobago 2.0.9 and higher)
+
+  * Prepare and perform the release with:
+
++------------------------+
+mvn release:prepare
+mvn release:perform
++------------------------+
+
+* Staging repository
+
+  * <Close> the repository on the {{{https://repository.apache.org/}Nexus}} instance for stating (you will receive a mail with the staging location).
+
+* Voting
+
+  * Propose a vote on the dev list with the staging location (see {{Vote template}} below).
+
+  * For a positive result wait at least 72 hours.
+
+  * Once a vote is successful, post the result to the dev list.
+
+* Publishing
+
+  * <Release> the version in {{{https://issues.apache.org/jira/}Jira}} and close all resolved issues for the release.
+
+  * <Release> the staging repository on the {{{https://repository.apache.org/}Nexus}} instance.
+
+  * Copy the download artifacts from the repository to the site (see script below)
+
+  * Add the release version and date to the {{{https://reporter.apache.org/addrelease.html?myfaces}Apache Committee Report Helper}}.
+
+  * Building the site
+
+    * Note: The site can only be build correctly on file systems that supports to differ upper-/lower-case.
+      This is not the default on Windows and Mac OS X machines.
+      On Mac OS X you can mount a virtual filesystem (sparse bundle) that supports upper-/lower-case with the
+      Disk Utility.
+
++------------------------+
+cd /Volumes/tobago-site
+svn co https://svn.apache.org/repos/asf/myfaces/tobago/trunk tobago
+svn co https://svn.apache.org/repos/asf/myfaces/site/publish/tobago tobago-publish
+cd tobago
+export MAVEN_OPTS="-Xmx1500m ${MAVEN_OPTS}"
+mvn clean package -Pattach-source
+mvn site:site
+mvn site:stage -DstagingDirectory=/Volumes/tobago-site/tobago-publish
++------------------------+
+
+
+  * Update the site after the distribution is on the Apache mirrors available.
+
+  * Unpack and commit the API Docs of the release with the update-1.0.sh, update-1.5.sh or update-2.0.sh script in
+    /Volumes/tobago-site/tobago-publish (set correct version first).
+
+  * Delete old assemblies in /www/www.apache.org/dist/myfaces/binaries on people.apache.org.
+    Older releases are automatic available in the {{{http://archive.apache.org/dist/myfaces/} archive}}.
+
+  * Delete old snapshots in /www/people.apache.org/builds/myfaces/nightly/ on people.apache.org.
+
+  * Create and send announcement (see {{Announcement template}} below).
+
+
+{Preparation template}
+
+  Send to: {{mailto:MyFaces Development \<dev@myfaces.apache.org\>}}
+
+  <Replace the variable parts like \<version\>>.
+
++------------------------+
+
+Subject: [Tobago] Preparation for the <version> release
+
+
+Hi, folks,
+
+I plan to build the <version> of Tobago soon.
+
+If you know any blocking problems with the current SNAPSHOT, give me a hint.
+
+Regards,
+<sender>
+
++------------------------+
+
+
+
+{Vote template}
+
+  Send to: {{mailto:MyFaces Development \<dev@myfaces.apache.org\>}}
+
+  <Replace the variable parts like \<version\>>.
+
++------------------------+
+
+Subject: [VOTE] Release Tobago <version>
+
+
+Hello,
+
+I would like to release Tobago <version>.
+
+Major changes since last release are:
+
+<insert list>
+
+<use one of>
+<a> This is a MAJOR release and may contain incompatible API changes.
+<b> This is a MINOR release with new functionality in a backwards-compatible manner.
+<c> This is a PATCH release with backwards-compatible bug fixes.
+
+For a detail list please consult the release notes at:
+
+https://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&version=<version_id_from_jira>
+
+The version is available at the staging repository (Nexus) at:
+
+https://repository.apache.org/content/repositories/orgapachemyfaces-<id_from_nexus>/
+
+Please vote now! (The vote is open for 72h.)
+
+[ ] +1
+[ ] +0
+[ ] -1
+
+Regards,
+<sender>
+
++------------------------+
+
+
+
+{Announcement template}
+
+  For all versions send to: {{mailto:MyFaces Discussion \<users@myfaces.apache.org\>}}\
+  Only for major versions send to: {{mailto:announce@apache.org}}
+
+  <Replace the variable parts like \<version\>>.
+
++------------------------+
+
+Subject: [ANNOUNCE] Apache Tobago <version> released
+
+
+The Apache MyFaces team is pleased to announce the release of Apache
+Tobago <version>.
+
+Apache Tobago is a component library for JavaServer Faces (JSF) that
+allows to write web-applications without the need of coding HTML, CSS
+and JavaScript
+
+Main new features
+-----------------
+
+<list of main new features here or remove this section>
+
+Changes
+-------
+
+Please check the release notes at
+http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&styleName=Html&version=<versionidfromjira>
+for a full list of the changes in this version.
+
+Known limitations and bugs
+--------------------------
+
+<add main limitations and known bugs here or remove this section>
+
+For more information about Apache Tobago, please visit
+http://myfaces.apache.org/tobago/.
+
+Have fun,
+-The MyFaces team
+
++------------------------+
+
+
+
+Copy the download artifacts from the repository to the site (release-tobago.sh)
+
++------------------------+
+#!/bin/sh
+set -e
+
+#VERSION=2.0.10
+VERSION=3.0.1
+
+MAVEN_REPOSITORY=https://repository.apache.org/content/repositories/releases
+DIST_REPOSITORY=https://dist.apache.org/repos/dist/release/myfaces
+
+# download file and hashes/signatures
+function download() {
+  DIR="$1"
+  FILE_ON_REPO="$2"
+  FILE="$3"
+
+  curl --fail "${MAVEN_REPOSITORY}/${DIR}/${VERSION}/${FILE_ON_REPO}"      -o ${FILE}
+  curl --fail "${MAVEN_REPOSITORY}/${DIR}/${VERSION}/${FILE_ON_REPO}.asc"  -o ${FILE}.asc
+  curl --fail "${MAVEN_REPOSITORY}/${DIR}/${VERSION}/${FILE_ON_REPO}.md5"  -o ${FILE}.md5
+  curl --fail "${MAVEN_REPOSITORY}/${DIR}/${VERSION}/${FILE_ON_REPO}.sha1" -o ${FILE}.sha1
+}
+
+# this performs check of the hashes (if this fails, something might went wrong absolutely)
+function check() {
+  FILE="$1"
+
+  echo "Checking file ${FILE}: "
+
+  md5 -q "${FILE}" > "${FILE}.md5.temp"
+  if ! diff --ignore-all-space "${FILE}.md5" "${FILE}.md5.temp" ; then
+    echo "Error: MD5 check failed!"
+    exit -1
+  fi
+  echo "  MD5 hash okay"
+
+  shasum -a 1 "${FILE}" | cut "-d " -f1 > "${FILE}.sha1.temp"
+  if ! diff --ignore-all-space "${FILE}.sha1" "${FILE}.sha1.temp" ; then
+    echo "Error: SHA1 check failed!"
+    exit -1
+  fi
+  echo "  SHA1 hash okay"
+
+  if ! gpg --verify "${FILE}.asc" ; then
+    echo "Error: GPG check failed!"
+    exit -1
+  fi
+  echo "  GPG signature okay"
+
+  # todo: change, if maven creates the sha256
+  shasum -a 256 "${FILE}" > "${FILE}.sha256"
+  echo "  SHA-256 created"
+
+}
+
+# this uploads the files into the svn dist repo
+function upload() {
+  PATTERN="$1"
+  FOLDER="$2"
+
+  for file in $(find . -type file -name "${PATTERN}" -exec basename \{\} \; ) ; do
+    # echo $file;
+    svn import -m "Tobago ${VERSON}" $file ${DIST_REPOSITORY}/${FOLDER}/$file;
+  done
+}
+
+# commands
+
+download "org/apache/myfaces/tobago/tobago-assembly"         "tobago-assembly-${VERSION}-dist.tar.gz"            "myfaces-tobago-${VERSION}-dist.tar.gz"
+download "org/apache/myfaces/tobago/tobago-assembly"         "tobago-assembly-${VERSION}-dist.zip"               "myfaces-tobago-${VERSION}-dist.zip"
+download "org/apache/myfaces/tobago/tobago-example-assembly" "tobago-example-assembly-${VERSION}-example.tar.gz" "myfaces-tobago-${VERSION}-example.tar.gz"
+download "org/apache/myfaces/tobago/tobago-example-assembly" "tobago-example-assembly-${VERSION}-example.zip"    "myfaces-tobago-${VERSION}-example.zip"
+download "org/apache/myfaces/tobago/tobago"                  "tobago-${VERSION}-source-release.zip"              "myfaces-tobago-${VERSION}-source-release.zip"
+
+check "myfaces-tobago-${VERSION}-dist.tar.gz"
+check "myfaces-tobago-${VERSION}-dist.zip"
+check "myfaces-tobago-${VERSION}-example.tar.gz"
+check "myfaces-tobago-${VERSION}-example.zip"
+check "myfaces-tobago-${VERSION}-source-release.zip"
+
+rm -f *.temp
+
+upload "myfaces-tobago-${VERSION}-dist.*"           "binaries"
+upload "myfaces-tobago-${VERSION}-example.*"        "binaries"
+upload "myfaces-tobago-${VERSION}-source-release.*" "source"
++------------------------+
diff --git a/tobago-3.0.x/src/site/fml/faq.fml b/tobago-3.0.x/src/site/fml/faq.fml
new file mode 100644
index 0000000..9cbf4d0
--- /dev/null
+++ b/tobago-3.0.x/src/site/fml/faq.fml
@@ -0,0 +1,499 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+  Note: Please use &lt; instead of < in the source tag, when the example is XML.
+  Otherwise you will lost the attributes.
+-->
+
+<faqs xmlns="http://maven.apache.org/FML/1.0.1"
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xsi:schemaLocation="http://maven.apache.org/FML/1.0.1 http://maven.apache.org/xsd/fml-1.0.1.xsd"
+      title="Frequently Asked Questions">
+
+  <part id="faq">
+    <faq id="howto">
+      <question>Where can I find documentation or HowTos for using Tobago?</question>
+      <answer>
+        <p>
+          Please, see
+        </p>
+        <p>
+          <a href="http://www.irian.biz/tobago-example-demo/">Tobago Demo</a>.
+        </p>
+        <p>
+          There is also a demo for
+        </p>
+        <p>
+          <a href="http://www.irian.biz/tobago-example-demo-2.0.x/">
+            Tobago 2.0
+          </a>
+        </p>
+      </answer>
+    </faq>
+    <faq id="hello-world">
+      <question>Where can I find a "Hello World" example and a list of required
+        jars?
+      </question>
+      <answer>
+        <p>
+          Please look at
+          <a href="http://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-example/tobago-example-blank/">
+            tobago-example-blank</a> or download the myfaces-tobago-example from the
+          <a href="https://repository.apache.org/content/repositories/snapshots/org/apache/myfaces/tobago/" >nightly builds directory</a>.
+        </p>
+      </answer>
+    </faq>
+    <faq id="tobago/RI">
+      <question>Does Tobago run with the Sun reference implementation (RI)?</question>
+      <answer>
+        <p>Tobago runs with Sun RI and with MyFaces.
+        Please take a look at the <a href="compatibility.html">Compatibility</a> List.</p>
+      </answer>
+    </faq>
+    <faq id="tobago/facelets">
+      <question>Does Tobago supports Facelets?</question>
+      <answer>
+        <p>Tobago 2.0.x:</p>
+        <p>Tobago supports the JSF 2.0 Facelets.
+          Note: Please add following context param in your web.xml</p>
+        <source>
+&lt;context-param>
+  &lt;param-name>javax.faces.FACELETS_SKIP_COMMENTS&lt;/param-name>
+  &lt;param-value>true&lt;/param-value>
+&lt;/context-param></source>
+        <p>Tobago 1.0.x and 1.5.x:</p>
+        <p>Tobago supports Facelets with the tobago-facelets.jar.
+        Note: Please add following context param in your web.xml</p>
+        <source>
+&lt;context-param>
+  &lt;param-name>facelets.SKIP_COMMENTS&lt;/param-name>
+  &lt;param-value>true&lt;/param-value>
+&lt;/context-param></source>
+      </answer>
+    </faq>
+    <faq id="tobago/myfaces extension">
+      <question>Can I mix Tobago and MyFaces extensions in the same web application?
+      </question>
+      <answer>
+        <p>JSF only supports one renderkit (renderkitId) per page (f:view).
+          Because Tobago has it's own renderkitId you cannot use any non-Tobago
+          components that need a renderer.
+        </p>
+      </answer>
+    </faq>
+    <faq id="tobago/layout">
+      <question>How do I use GridLayout in Tobago?</question>
+      <answer>
+        <source>
+&lt;tc:gridLayout rows="fixed;100px;1*;2*" /></source>
+        <p>
+          The attribute 'fixed' means a theme dependent height of one row (i.e. in Speyside
+          a row is typically 20px high.) In a 'fixed' row all one height unit high elements find their place
+          (like buttons, input fields, one row of text...).<br/>
+          Using px heights is at your own risk, but it is sometimes needed for elements like box or sheet.
+        </p>
+        <p>
+          Alternatively you can give elements a proportion with the * notation.<br/>
+          For example rows="1*;2*" gives the first row 1/3 of the available vertical space and the
+          second row 2/3. This works fine for columns, too.
+        </p>
+        <p>
+          You can group elements with a tc:panel element. Such a panel is interpreted as one
+          element regarding layout. The panel itself can have its own layout for multiple elements inside
+          the panel.
+        </p>
+      </answer>
+    </faq>
+
+    <faq id="tobago/fileupload">
+      <question>How do I configure file upload in Tobago?</question>
+      <answer>
+        <p>Till Tobago 2.0 and lower, you have two options.</p>
+        <p>Add a TobagoMultipartFormdataFilter to your web.xml.
+          <a href="http://myfaces.apache.org/tobago/apidocs/org/apache/myfaces/tobago/webapp/TobagoMultipartFormdataFilter.html">JavaDoc Description</a>
+        </p>
+        <p>Add the tobago-fileupload.jar to your project.
+           The tobago-fileupload.jar contains a FacesContextFactory that wraps the
+            multipart-formdata request inside the FacesContext.
+          <a href="http://myfaces.apache.org/tobago/apidocs/org/apache/myfaces/tobago/fileupload/FileUploadFacesContextFactoryImpl.html">JavaDoc Description</a>
+        </p>
+        <p>Starting with Tobago 3.0 the Servlet API 3.0 will be used. Some more information about the
+          usage you will find in <a href="https://issues.apache.org/jira/browse/TOBAGO-1539">Jira</a>
+          and in the <a href="http://www.irian.biz/tobago-example-demo-3.0.x/faces/content/20-component/100-upload/upload.xhtml">Tobago Demo 3.0</a>.
+          There is also a <a href="http://www.irian.biz/tobago-example-demo/faces/content/10-intro/50-migration/97-migration/migration30.xhtml">migration guide</a> available.
+        </p>
+      </answer>
+    </faq>
+
+    <faq id="tobago/form">
+      <question>Do I need a form tag in a normal Tobago page?</question>
+      <answer>
+        <p>The page tag already acts like a form tag. You only need a explicit form tag for partial validation of your data.
+        Please look at the forms example in the
+        <a href="http://www.irian.biz/tobago-example-demo-3.0.x/faces/content/30-concept/08-form/form.xhtml">Tobago demo</a>
+        </p>
+      </answer>
+    </faq>
+
+    <faq id="tobago/browser">
+      <question>Which web browsers are currently supported by Tobago?</question>
+      <answer>
+        <p>Please take a look at the <a href="compatibility.html">Compatibility</a> List.</p>
+      </answer>
+    </faq>
+
+    <faq id="tobago/owntheme">
+      <question>How do I create my own theme?</question>
+      <answer>
+        <p>
+          You have to define a new name for the theme in the META-INF/tobago-config.xml.
+          Choose a fallback theme in the tobago-config.xml.
+          Put the modified resources under the resource-path + theme-name.
+          An example for this is the charlotteville theme. (TODO more details resource handling)
+          </p>
+        <p>
+        Example layout of a theme jar:
+        </p>
+         <source>
+/META-INF/tobago-config.xml
+(resource-path/html/theme-name)
+/org/apache/myfaces/tobago/renderkit/html/xxxxx/standard/style/tobago.css (standard styles)
+/org/apache/myfaces/tobago/renderkit/html/xxxxx/standard/style/tobago-menu.css (menu styles)
+/org/apache/myfaces/tobago/renderkit/html/xxxxx/standard/style/tobago-sheet.css (sheet styles)
+/org/apache/myfaces/tobago/renderkit/html/xxxxx/msie/style/tobago.css (different styles for msie)</source>
+
+           Property and resource loading and renderer loading is done in the following order
+           <source>
+resource-path/content-type/theme/client/[tag(for renderer)|property|style|script|image]_locale
+    .(class|property|property.xml|css|js|gif|png...]</source>
+
+           for example OutRenderer<br/>
+
+           org.apache.myfaces.tobago.renderkit.html.scarborough.standard.tag.OutRenderer<br/>
+
+           OutRenderer is getRendererType() + "Renderer"<br/>
+
+        The locale handling is handled like the Properties Class.<br/>
+
+        You have not define everything because the ResourceManager is asking the fallback theme for missing resources<br/>
+
+        The fallback theme of charlotteville is speyside.<br/>
+        The fallback theme of speyside is scarborough.<br/>
+        The fallback theme of scarborough is standard<br/>
+
+        The resource manager looks in the case of the charlotteville theme in<br/>
+        charlotteville -> speyside -> scarborough -> standard
+        <p>
+          Please look at
+          <a href="http://svn.apache.org/repos/asf/myfaces/tobago/trunk/tobago-theme/tobago-theme-example/src/main/resources">
+            tobago-example-theme
+          </a>
+         </p>
+      </answer>
+    </faq>
+
+    <faq id="tobago/custommarkup">
+      <question>How do I use and extend the markup attribute?</question>
+      <answer>
+        <p>UIBox, UIInput and UIOutput support custom markup with the markup attribute.
+          The supported markup is defined in the tobago-config.xml.
+          The standard markup is defined in tobago-config.xml of the tobago-theme-standard.
+          This can be extended in your own theme.
+          The markup attribute is rendered as a CSS class tobago-[renderer-name.toLowerCase]-markup-[markup].
+          For an example please look at the markup number and the CSS class tobago-in-markup-number for UIIn
+          in theme/scarborough/src/main/resources/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/style/tobago.css
+          </p>
+      </answer>
+    </faq>
+
+    <faq id="tobago/container">
+      <question>In which containers was Tobago tested?</question>
+      <answer>
+        <p>Please take a look at the <a href="compatibility.html">Compatibility</a> List.
+        Feel free to post your own experiences.</p>
+      </answer>
+    </faq>
+
+    <faq id="tiles/sitemesh">
+      <question>Can Tobago replace Tiles? Can I ignore Tiles and Sitemesh in
+        favor of Tobago?
+      </question>
+      <answer>
+        <p>Tobago cannot replace it. But sometimes you may not need it, when
+          you are using Tobago.
+          If you want to position and size your components automatically, you
+          can do this with a Tobago LayoutManager.
+          If you want your header and sidebar rendered without writing duplicate
+          code, you may use JSP 2.0 tag files, Facelets or Tiles/Sitemesh.
+        </p>
+      </answer>
+    </faq>
+    <faq id="maven-mirror">
+      <question>How to configure a maven mirror?</question>
+      <answer>
+        <p>
+          If you want to set up a different mirror for some reason, you can use
+          your ~/.m2/settings.xml and add the following lines:
+        </p>
+        <source>
+&lt;mirrors>
+  &lt;mirror>
+    &lt;id>mirror ID&lt;/id>
+    &lt;name>Give it a name&lt;/name>
+    &lt;url>The URL of the mirror&lt;/url>
+    &lt;mirrorOf>The server ID of the repository being mirrored.
+        This must not match the mirror ID&lt;/mirrorOf>
+  &lt;/mirror>
+&lt;/mirrors></source>
+        <p>See:
+          <a href="http://maven.apache.org/guides/mini/guide-mirror-settings.html">
+            Guide to mirror settings
+          </a>
+        </p>
+        <p>Mirrors:
+          <a href="http://docs.codehaus.org/display/MAVENUSER/Mirrors+Repositories">
+            List of mirrors
+          </a>
+        </p>
+      </answer>
+    </faq>
+    <faq id="offline-build">
+      <question>How do I configure an offline build?</question>
+      <answer>
+        <p>
+          If you run into problems with fetching jars from the online
+          repository, you can configure Maven not to fetch them but use
+          the ones already in your local repository by adding the following to your ~/.m2/settings.xml:
+        </p>
+        <source>
+&lt;settings>
+  &lt;offline/>
+&lt;/settings></source>
+        <p>or use the mvn -o switch.</p>
+      </answer>
+    </faq>
+    <faq id="checkstyle">
+      <question>How do I perform a local checkstyle check?</question>
+      <answer>
+        <source>
+mvn compile checkstyle:check</source>
+      </answer>
+    </faq>
+    <faq id="checkstyle-vdl">
+      <question>How do I check the syntax of Facelet-Files (*.xhtml) with respect to the Taglib?</question>
+      <answer>
+        <p>
+        The problem is, that there is no concept for <em>deprecation</em> in Taglibs.
+        The tobago-core.jar contains a generated checkstyle configuration to perform
+        a syntax check via the maven checkstyle plugin.
+        </p>
+
+        <p>
+        Configure in the applications pom.xml an entry like this example
+        <source>    &lt;profile>
+      &lt;id>checkstyle-for-view-definition-language&lt;/id>
+      &lt;build>
+        &lt;plugins>
+          &lt;plugin>
+            &lt;groupId>org.apache.maven.plugins&lt;/groupId>
+            &lt;artifactId>maven-checkstyle-plugin&lt;/artifactId>
+            &lt;configuration>
+              &lt;configLocation>META-INF/checkstyle-tobago.xml&lt;/configLocation>
+              &lt;includes>**/*.xhtml&lt;/includes>
+              &lt;excludes>**/*.java&lt;/excludes>
+              &lt;sourceDirectory>src/main/webapp&lt;/sourceDirectory>
+            &lt;/configuration>
+            &lt;dependencies>
+              &lt;dependency>
+                &lt;groupId>org.apache.myfaces.tobago&lt;/groupId>
+                &lt;artifactId>tobago-core&lt;/artifactId>
+                &lt;version>${tobago.version}&lt;/version>
+              &lt;/dependency>
+            &lt;/dependencies>
+          &lt;/plugin>
+        &lt;/plugins>
+      &lt;/build>
+    &lt;/profile>
+        </source>
+        </p>
+        <p>
+        To perform a check call
+        <source>
+mvn checkstyle:check -Pcheckstyle-for-view-definition-language</source>
+          You will find the result in target/checkstyle-result.xml
+        </p>      </answer>
+    </faq>
+    <faq id="max-path">
+      <question>Why my Subversion checkout fails on Windows?</question>
+      <answer>
+        One reason is, that the checked out files will have a too long path name.
+        Under Windows the MAX_PATH is set to 260 characters. When you try to checkout in
+        a directory like C:\Dokumente und Einstellungen\MyUser\Apache Projects\
+        the path will be too long. A workaround will be checking out in an other directory
+        or register a new drive letter and check it out in X:
+        <source>
+SUBST X: "C:\Dokumente und Einstellungen\MyUser\Apache Projects\"</source>
+      </answer>
+    </faq>
+    <faq id="seleniumTobago12">
+      <question>How can I run the Selenium tests? (Tobago 1 and 2)</question>
+      <answer>
+      <p>
+        In the tobago-example-test application, the pages can be checked with selenium since Tobago 1.5.
+        To run the full test automatically call
+        <source>
+mvn -P integration-test</source>
+        This will start a jetty server and a selenium server and calls every listed page in the test application.
+      </p>
+
+        <p>
+        If you want to run the tests from your IDE, please start the jetty with
+        <source>
+mvn jetty:run</source> or <source>mvn jetty:run-exploded</source>
+        and start the selenium server with
+        <source>
+mvn selenium:start-server</source>
+        Now you can start the selenium tests in the IDE.
+        </p>
+        <p>
+          Sometimes there is a problem with Firefox. You may try to use a different version, or an installation without
+          plugins.
+        </p>
+      </answer>
+    </faq>
+    <faq id="integrationTestTobago3">
+      <question>How can I run the integration tests? (Tobago 3)</question>
+      <answer>
+        <p>In the tobago-example-demo application, the pages can be checked with QUnit/Arquillian.
+          To run the full test automatically call <source>mvn verify -Pqunit-integration-tests</source>
+          The default arquillian browser is 'phantomjs'.
+          You can change it in tobago-example-demo/pom.xml &lt;arquillian.browser>.</p>
+        <p>If you want to run the tests from your IDE, please use the maven profile 'tomee'.
+          After that, you can start the test from the QUnitTests class.</p>
+      </answer>
+    </faq>
+    <faq id="liberty">
+      <question>How can I run the Tobago demo with WebSphere Liberty Profile (WLP) from Maven?</question>
+      <answer>
+        <p>
+          <b>Please use at least Tobago 2.0 for this guidance (in this version the pom.xml files are prepared).</b>
+        </p>
+        <p>
+          You will need to do the following steps for preparation:
+        </p>
+        <ul>
+          <li>Download the server like:
+            <source>wlp-developers-runtime-8.5.5.0.jar</source>
+            from
+            <a href="https://www.ibm.com/developerworks/mydeveloperworks/blogs/wasdev/entry/download?lang=en">IBM</a>
+          </li>
+          <li>
+            Unpack the server anywhere in you file system, e.g. like this
+            <source>mkdir /opt/wlp-developers-runtime-8.5.5.0
+cd /opt/wlp-developers-runtime-8.5.5.0
+java -jar ~/Downloads/wlp-developers-runtime-8.5.5.0.jar
+            </source>
+          </li>
+          <li>
+            Adding your server home to a property in the settings.xml of Maven
+            <source>&lt;wlp.directory&gt;/opt/wlp-developers-runtime-8.5.5.0/wlp&lt;/wlp.directory&gt;</source>
+          </li>
+        </ul>
+        <p>
+          After these steps you can start/stop the server and deploy an built artifact.
+          For these steps, you need to be in the Tobago example demo directory.
+          <source>cd tobago-examples/tobago-example-demo</source>
+          This is <b>important</b> for the first start of the server,
+          because at the first start the server will be initialized.
+          For the setup the file
+          <source>test/resources/server.xml</source>
+          will be read. It contains the features, the WLP server will be support, and other configurations.
+          In our case we have the following features:
+          <source>
+            &lt;feature>cdi-1.0&lt;/feature>
+            &lt;feature>jsp-2.2&lt;/feature>
+            &lt;feature>servlet-3.0&lt;/feature>
+            &lt;feature>jsf-2.0&lt;/feature></source>
+        </p>
+        <ul>
+          <li>
+            Start the server
+            <source>mvn -Pliberty liberty:start-server</source>
+          </li>
+          <li>
+            Build an artifact (you need the "provided" property, because JSF and OWB comes from the server)
+            <source>mvn clean package -Djsf=provided</source>
+          </li>
+          <li>
+            Deploy an artifact
+            <source>mvn -Pliberty liberty:deploy</source>
+          </li>
+          <li>
+            You will find the web application under this URL
+            <source>http://localhost:9080/tobago-example-demo/</source>
+          </li>
+          <li>
+            Redeploy an artifact: The same as deploy.
+          </li>
+          <li>
+            Stop the server
+            <source>mvn -Pliberty liberty:stop-server</source>
+          </li>
+        </ul>
+        <p>
+          The server starts very fast and is simple to use (very different from the full WebSphere installation).
+          The log files you will find here:
+          <source>cd /opt/wlp-developers-8.5.next.beta/wlp/usr/servers/tobago/logs/</source>
+          Sometime you may need to the clean the server, in particular when you are changing JAR dependencies.
+          For doing that
+        </p>
+        <ul>
+          <li>
+            Stop the server
+          </li>
+          <li>
+            Remove the whole concrete server installation
+            <source>rm -r /opt/wlp-developers-8.5.next.beta/wlp/usr/servers/tobago</source>
+          </li>
+          <li>
+            Start the server (don't forget the server.xml)
+          </li>
+          <li>
+            Deploy again
+          </li>
+        </ul>
+        Please also consider the plugin configuration in the tobago-example/pom.xml
+        <source>
+          &lt;groupId>com.ibm.websphere.wlp.maven.plugins&lt;/groupId>
+          &lt;artifactId>liberty-maven-plugin&lt;/artifactId></source>
+      </answer>
+    </faq>
+    <faq id="portlet">
+      <question>How to setup my project to work with Portlets?</question>
+      <answer>
+        <p>
+          There is a basic example for portlets in the Subversion repository in the sub-folder
+          tobago-example/tobago-example-portlet
+          There is no specific configuration to use Tobago in Portlets.
+        </p>
+      </answer>
+    </faq>
+  </part>
+</faqs>
diff --git a/tobago-3.0.x/src/site/resources/doap_tobago.rdf b/tobago-3.0.x/src/site/resources/doap_tobago.rdf
new file mode 100644
index 0000000..02e8787
--- /dev/null
+++ b/tobago-3.0.x/src/site/resources/doap_tobago.rdf
@@ -0,0 +1,87 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<rdf:RDF xml:lang="en"
+         xmlns="http://usefulinc.com/ns/doap#" 
+         xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 
+         xmlns:asfext="http://projects.apache.org/ns/asfext#"
+         xmlns:foaf="http://xmlns.com/foaf/0.1/">
+  <Project rdf:about="http://tobago.rdf.apache.org/">
+    <created>2006-07-10</created>
+    <license rdf:resource="http://usefulinc.com/doap/licenses/asl20" />
+    <name>Apache Tobago</name>
+    <homepage rdf:resource="http://myfaces.apache.org/tobago" />
+    <asfext:pmc rdf:resource="http://myfaces.apache.org" />
+    <shortdesc>Set of user interface components based on JSF.</shortdesc>
+    <description>The goal of Tobago is to provide the community with a well designed set of user interface components based on JSF.</description>
+    <bug-database rdf:resource="http://issues.apache.org/jira/browse/TOBAGO" />
+    <mailing-list rdf:resource="http://myfaces.apache.org/tobago/mail-lists.html" />
+    <download-page rdf:resource="http://myfaces.apache.org/tobago/download.html" />
+    <programming-language>Java</programming-language>
+    <category rdf:resource="http://projects.apache.org/category/web-framework" />
+    <release>
+      <Version>
+        <name>Latest stable release of 1.0.x</name>
+        <created>2015-07-16</created>
+        <revision>1.0.42</revision>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.0.42-dist.tar.gz</file-release>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.0.42-dist.zip</file-release>
+      </Version>
+    </release>
+    <release>
+      <Version>
+        <name>Latest stable release of 1.5.x</name>
+        <created>2014-03-25</created>
+        <revision>1.5.13</revision>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.5.13-dist.tar.gz</file-release>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-1.5.13-dist.zip</file-release>
+      </Version>
+    </release>
+    <release>
+      <Version>
+        <name>Latest stable release of 2.0.x</name>
+        <created>2016-09-08</created>
+        <revision>2.0.10</revision>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-2.0.10-dist.tar.gz</file-release>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-2.0.10-dist.zip</file-release>
+      </Version>
+    </release>
+    <release>
+      <Version>
+        <name>Latest stable release of 3.0.x</name>
+        <created>2017-01-17</created>
+        <revision>3.0.1</revision>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-3.0.1-dist.tar.gz</file-release>
+        <file-release>http://www.apache.org/dyn/closer.lua/myfaces/binaries/myfaces-tobago-3.0.1-dist.zip</file-release>
+      </Version>
+    </release>
+    <repository>
+      <SVNRepository>
+        <location rdf:resource="http://svn.apache.org/repos/asf/myfaces/tobago"/>
+        <browse rdf:resource="http://svn.apache.org/viewvc/myfaces/tobago"/>
+      </SVNRepository>
+    </repository>
+    <maintainer>
+      <foaf:Person>
+        <foaf:name>Bernd Bohmann</foaf:name>
+          <foaf:mbox rdf:resource="mailto:bommel@apache.org"/>
+      </foaf:Person>
+    </maintainer>
+  </Project>
+</rdf:RDF>
diff --git a/tobago-3.0.x/src/site/resources/images/addressbook.png b/tobago-3.0.x/src/site/resources/images/addressbook.png
new file mode 100644
index 0000000..5b55e43
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/addressbook.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/demo.png b/tobago-3.0.x/src/site/resources/images/demo.png
new file mode 100644
index 0000000..eea4e87
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/demo.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-about.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-about.png
new file mode 100644
index 0000000..ede34aa
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-about.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-date.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-date.png
new file mode 100644
index 0000000..35dbd4e
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-date.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-editor-simple.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-editor-simple.png
new file mode 100644
index 0000000..5298a82
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-editor-simple.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-editor.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-editor.png
new file mode 100644
index 0000000..800d93d
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-editor.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-list.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-list.png
new file mode 100644
index 0000000..bdda5aa
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-list.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-logging.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-logging.png
new file mode 100644
index 0000000..214ab45
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-logging.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-login.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-login.png
new file mode 100644
index 0000000..a975e4e
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-login.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-memory.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-memory.png
new file mode 100644
index 0000000..542aa06
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-memory.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-menu.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-menu.png
new file mode 100644
index 0000000..084889f
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-menu.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-popup.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-popup.png
new file mode 100644
index 0000000..656e55b
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-popup.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-addressbook-upload.png b/tobago-3.0.x/src/site/resources/images/guide-addressbook-upload.png
new file mode 100644
index 0000000..ab230cc
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-addressbook-upload.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-basic-controls.png b/tobago-3.0.x/src/site/resources/images/guide-basic-controls.png
new file mode 100644
index 0000000..a2ac458
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-basic-controls.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-markup.png b/tobago-3.0.x/src/site/resources/images/guide-markup.png
new file mode 100644
index 0000000..ca5efe7
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-markup.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-menu.png b/tobago-3.0.x/src/site/resources/images/guide-menu.png
new file mode 100644
index 0000000..731440e
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-menu.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-popup.png b/tobago-3.0.x/src/site/resources/images/guide-popup.png
new file mode 100644
index 0000000..c3d50e3
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-popup.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-progress.png b/tobago-3.0.x/src/site/resources/images/guide-progress.png
new file mode 100644
index 0000000..51a5215
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-progress.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-sheet.png b/tobago-3.0.x/src/site/resources/images/guide-sheet.png
new file mode 100644
index 0000000..55018d3
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-sheet.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-simple-editor.png b/tobago-3.0.x/src/site/resources/images/guide-simple-editor.png
new file mode 100644
index 0000000..6c71bb4
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-simple-editor.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-tab-group.png b/tobago-3.0.x/src/site/resources/images/guide-tab-group.png
new file mode 100644
index 0000000..d5abd7f
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-tab-group.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-theme-charlotteville.png b/tobago-3.0.x/src/site/resources/images/guide-theme-charlotteville.png
new file mode 100644
index 0000000..e8db6fb
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-theme-charlotteville.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-theme-richmond.png b/tobago-3.0.x/src/site/resources/images/guide-theme-richmond.png
new file mode 100644
index 0000000..59b2eb5
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-theme-richmond.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-theme-scarborough.png b/tobago-3.0.x/src/site/resources/images/guide-theme-scarborough.png
new file mode 100644
index 0000000..2407578
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-theme-scarborough.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-theme-speyside.png b/tobago-3.0.x/src/site/resources/images/guide-theme-speyside.png
new file mode 100644
index 0000000..317d0c6
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-theme-speyside.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-toolbar.png b/tobago-3.0.x/src/site/resources/images/guide-toolbar.png
new file mode 100644
index 0000000..18a8cf3
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-toolbar.png differ
diff --git a/tobago-3.0.x/src/site/resources/images/guide-upload.png b/tobago-3.0.x/src/site/resources/images/guide-upload.png
new file mode 100644
index 0000000..2983cef
Binary files /dev/null and b/tobago-3.0.x/src/site/resources/images/guide-upload.png differ
diff --git a/tobago-3.0.x/src/site/site.xml b/tobago-3.0.x/src/site/site.xml
new file mode 100644
index 0000000..be625f2
--- /dev/null
+++ b/tobago-3.0.x/src/site/site.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<project name="Tobago">
+  <bannerLeft>
+    <name>Tobago</name>
+    <src>images/tobagoLogo.png</src>
+    <href>http://myfaces.apache.org/tobago</href>
+  </bannerLeft>
+  <bannerRight>
+    <name>Apache MyFaces</name>
+    <src>img/banners/MyFaces_logo.jpg</src>
+    <href>http://myfaces.apache.org/</href>
+  </bannerRight>
+  <publishDate format="dd MMM yyyy" />
+  <skin>
+    <groupId>org.apache.myfaces.maven</groupId>
+    <artifactId>myfaces-site-skin</artifactId>
+    <version>4</version>
+  </skin>
+  <body>
+    <links>
+      <item name="Apache"   href="http://www.apache.org/"/>
+      <item name="MyFaces"  href="http://myfaces.apache.org/"/>
+      <item name="Tobago"   href="http://myfaces.apache.org/tobago"/>
+      <item name="Download" href="http://myfaces.apache.org/download.html" />
+      <item name="Mailing Lists"    href="http://myfaces.apache.org/tobago/mail-lists.html" />
+    </links>
+
+    <menu name="Tobago">
+      <item name="Introduction"  href="http://myfaces.apache.org/tobago/index.html"/>
+      <item name="Download"      href="http://myfaces.apache.org/tobago/download.html"/>
+      <item name="Demo"          href="http://myfaces.apache.org/tobago/demo.html"/>
+      <item name="Mailing Lists" href="mail-lists.html" />
+    </menu>
+
+    <menu name="Documentation">
+      <item name="Getting Started" href="http://myfaces.apache.org/tobago/getting-started.html"/>
+      <item name="Compatibility" href="http://myfaces.apache.org/tobago/compatibility.html"/>
+      <item name="New in Tobago 3.0" href="http://www.irian.biz/tobago-example-demo/faces/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml"/>
+      <item name="New in Tobago 2.0" href="http://myfaces.apache.org/tobago/new-2.0.html"/>
+      <item name="Guide to Tobago" href="http://myfaces.apache.org/tobago/guide.html"/>
+      <item name="Test Tobago 3.0 Demo" href="http://myfaces.apache.org/tobago/howto-test.html"/>
+      <item name="Migration to 3.0" href="http://www.irian.biz/tobago-example-demo/faces/content/10-intro/50-migration/97-migration/migration30.xhtml"/>
+      <item name="Roadmap" href="https://issues.apache.org/jira/browse/TOBAGO#selectedTab=com.atlassian.jira.plugin.system.project%3Aroadmap-panel" />
+      <item name="FAQ" href="http://myfaces.apache.org/tobago/faq.html" />
+      <item name="API Documentation" href="http://myfaces.apache.org/tobago/api.html" />
+      <item name="Release Checklist" href="http://myfaces.apache.org/tobago/release-checklist.html" />
+    </menu>
+
+<!--
+    ${parentProject}
+    ${modules}
+-->
+    ${reports}
+
+    <menu name="Foundation">
+      <item name="ASF" href="http://apache.org/" />
+      <item name="Sponsorship" href="http://www.apache.org/foundation/sponsorship.html" />
+      <item name="Thanks" href="http://www.apache.org/foundation/thanks.html" />
+      <item name="Security" href="http://www.apache.org/security/" />
+      <item name="License" href="http://www.apache.org/licenses/" />
+    </menu>
+
+  </body>
+</project>
diff --git a/tobago-3.0.x/tobago-3.0.txt b/tobago-3.0.x/tobago-3.0.txt
new file mode 100644
index 0000000..8bd0f9b
--- /dev/null
+++ b/tobago-3.0.x/tobago-3.0.txt
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+Some notices and ideas (which aren't on the home page).
+
+  - Use box-sizing: border-box (requires IE 8) (required for Bootstrap)
+  - Use min/max-width/height (requires IE 9 (IE 8 have bugs (see caniuse.com)))
+  - Use n-th child (requires IE 9 and FF 3.5)
+  - Better: Using Flexible Box Layout Module (requires IE 10, might be emulated with JavaScript)
+  - TBD: consolidate LinkRenderer, ButtonRenderer with CommandRenderer
diff --git a/tobago-3.0.x/tobago-assembly/pom.xml b/tobago-3.0.x/tobago-assembly/pom.xml
new file mode 100644
index 0000000..60134a2
--- /dev/null
+++ b/tobago-3.0.x/tobago-assembly/pom.xml
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>tobago-assembly</artifactId>
+  <packaging>pom</packaging>
+  <name>Tobago Assembly</name>
+  <description>This is the MyFaces Tobago Assembly</description>
+
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago</artifactId>
+    <version>3.0.3</version>
+  </parent>
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.apache.myfaces.core</groupId>
+      <artifactId>myfaces-api</artifactId>
+      <optional>true</optional>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-standard</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-speyside</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-sandbox</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-servlet_3.0_spec</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-el_2.2_spec</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>generate-assembly</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>copy-javadoc</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-core</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>javadoc</classifier>
+                    </artifactItem>
+                  </artifactItems>
+                  <outputDirectory>${project.build.directory}/javadoc
+                  </outputDirectory>
+                </configuration>
+              </execution>
+
+              <!--execution>
+                <id>copy-project</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>source-release</classifier>
+                      <type>zip</type>
+                    </artifactItem>
+                  </artifactItems>
+                  <outputDirectory>${project.build.directory}/assembly/out
+                  </outputDirectory>
+                  <unpackMarkersDirectory>${project.build.directory}/project
+                  </unpackMarkersDirectory>
+                </configuration>
+              </execution-->
+
+              <execution>
+                <id>copy-sandbox</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-sandbox</artifactId>
+                      <version>${project.version}</version>
+                    </artifactItem>
+                  </artifactItems>
+                  <outputDirectory>${project.build.directory}/sandbox
+                  </outputDirectory>
+                </configuration>
+              </execution>
+
+<!--
+XXX TOBAGO-1654
+              <execution>
+                <id>copy-tlddoc</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-core</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>tlddoc</classifier>
+                    </artifactItem>
+
+                  </artifactItems>
+                  <outputDirectory>${project.build.directory}/tlddoc
+                  </outputDirectory>
+                </configuration>
+              </execution>
+-->
+
+               <execution>
+                <id>copy-tld</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>unpack</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-core</artifactId>
+                      <version>${project.version}</version>
+                    </artifactItem>
+
+                  </artifactItems>
+                  <outputDirectory>${project.build.directory}/tld
+                  </outputDirectory>
+                </configuration>
+              </execution>
+              <execution>
+                <id>copy-source</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-core</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>sources</classifier>
+                    </artifactItem>
+<!--
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-theme-charlotteville</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>sources</classifier>
+                    </artifactItem>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-theme-richmond</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>sources</classifier>
+                    </artifactItem>
+-->
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-theme-speyside</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>sources</classifier>
+                    </artifactItem>
+<!--
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-theme-scarborough</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>sources</classifier>
+                    </artifactItem>
+-->
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-theme-standard</artifactId>
+                      <version>${project.version}</version>
+                      <classifier>sources</classifier>
+                    </artifactItem>
+
+                  </artifactItems>
+                  <outputDirectory>${project.build.directory}/src
+                  </outputDirectory>
+                </configuration>
+              </execution>
+
+            </executions>
+          </plugin>
+
+          <plugin>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>package</phase>
+                <id>generate-assembly</id>
+                <goals>
+                  <goal>single</goal>
+                </goals>
+
+                <configuration>
+                  <descriptor>src/main/assembly/dep.xml</descriptor>
+                  <finalName>myfaces-tobago-${project.version}</finalName>
+                  <outputDirectory>target/assembly/out</outputDirectory>
+                  <workDirectory>target/assembly/work</workDirectory>
+                  <tarLongFileMode>gnu</tarLongFileMode>
+                </configuration>
+              </execution>
+            </executions>
+
+          </plugin>
+
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/tobago-3.0.x/tobago-assembly/src/main/assembly/dep.xml b/tobago-3.0.x/tobago-assembly/src/main/assembly/dep.xml
new file mode 100644
index 0000000..5d577f0
--- /dev/null
+++ b/tobago-3.0.x/tobago-assembly/src/main/assembly/dep.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<assembly>
+  <id>dist</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <dependencySets>
+    <dependencySet>
+      <outputDirectory>lib</outputDirectory>
+      <scope>runtime</scope>
+    </dependencySet>
+  </dependencySets>
+  <fileSets>
+    <fileSet>
+    	<directory>src/main/resources</directory>
+    	<outputDirectory></outputDirectory>
+      <includes>
+        <include>README*</include>
+        <include>LICENSE*</include>
+        <include>NOTICE*</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>target/javadoc</directory>
+      <outputDirectory>javadoc</outputDirectory>
+      <excludes>
+        <exclude>*.unpacked</exclude>
+      </excludes>
+    </fileSet>
+    <fileSet>
+      <directory>target/tlddoc</directory>
+      <outputDirectory>tlddoc</outputDirectory>
+      <excludes>
+        <exclude>*.unpacked</exclude>
+      </excludes>
+    </fileSet>
+     <fileSet>
+      <directory>target/tld/META-INF/org/apache/myfaces/tobago/internal/taglib/component/</directory>
+      <outputDirectory>tld</outputDirectory>
+    </fileSet>
+     <fileSet>
+      <directory>target/tld/META-INF/org/apache/myfaces/tobago/internal/taglib/extension/</directory>
+      <outputDirectory>tld</outputDirectory>
+    </fileSet>
+    <fileSet>
+      <directory>target/extension</directory>
+      <outputDirectory>extension</outputDirectory>
+      <includes>
+        <include>*.jar</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>target/src</directory>
+      <outputDirectory>src</outputDirectory>
+      <includes>
+        <include>*.jar</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>target/sandbox</directory>
+      <outputDirectory>sandbox</outputDirectory>
+      <includes>
+        <include>*.jar</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</assembly>
diff --git a/tobago-3.0.x/tobago-assembly/src/main/resources/LICENSE.txt b/tobago-3.0.x/tobago-assembly/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..4ad7a26
--- /dev/null
+++ b/tobago-3.0.x/tobago-assembly/src/main/resources/LICENSE.txt
@@ -0,0 +1,328 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+
+------------------------------------------------------------------------------
+For jQuery:
+------------------------------------------------------------------------------
+
+Copyright 2012, 2014 jQuery Foundation and other contributors,
+https://jquery.org/
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/jquery/jquery.org
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+====
+
+All files located in the node_modules directory are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
+
+------------------------------------------------------------------------------
+For jQuery UI:
+------------------------------------------------------------------------------
+
+Copyright 2014 jQuery Foundation and other contributors,
+http://jqueryui.com/
+
+This software consists of voluntary contributions made by many
+individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
+contribution history, see the revision history and logs, available
+at http://jquery-ui.googlecode.com/svn/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For jQuery Timepicker Addon:
+------------------------------------------------------------------------------
+
+Copyright (c) 2009 Trent Richardson, http://trentrichardson.com/Impromptu/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------------------------------------------
+ For SLF4J:
+------------------------------------------------------------------------------
+
+ Copyright (c) 2004-2008 QOS.ch
+ All rights reserved.
+
+ Permission is hereby granted, free  of charge, to any person obtaining
+ a  copy  of this  software  and  associated  documentation files  (the
+ "Software"), to  deal in  the Software without  restriction, including
+ without limitation  the rights to  use, copy, modify,  merge, publish,
+ distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ permit persons to whom the Software  is furnished to do so, subject to
+ the following conditions:
+
+ The  above  copyright  notice  and  this permission  notice  shall  be
+ included in all copies or substantial portions of the Software.
+
+ THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
diff --git a/tobago-3.0.x/tobago-assembly/src/main/resources/NOTICE.txt b/tobago-3.0.x/tobago-assembly/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..0f93d52
--- /dev/null
+++ b/tobago-3.0.x/tobago-assembly/src/main/resources/NOTICE.txt
@@ -0,0 +1,16 @@
+Apache Tobago
+Copyright 2005-2017 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
+
+This product includes software developed by
+The jQuery Foundation (http://jquery.org/ and http://jqueryui.com/)
+
+This product includes software developed by
+QOS.ch (slf4j) (http://QOS.ch/)
+
diff --git a/tobago-3.0.x/tobago-assembly/src/main/resources/README.txt b/tobago-3.0.x/tobago-assembly/src/main/resources/README.txt
new file mode 100644
index 0000000..15e36be
--- /dev/null
+++ b/tobago-3.0.x/tobago-assembly/src/main/resources/README.txt
@@ -0,0 +1,6 @@
+Thank you for using Apache Tobago.
+
+The distribution of Apache Tobago requires Java 6 or higher.
+
+Warning: The tobago-sandbox.jar contains unstable components.
+Everything is subject to change without prior notice.
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-core/assembly-tlddoc.xml b/tobago-3.0.x/tobago-core/assembly-tlddoc.xml
new file mode 100644
index 0000000..8ef664b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/assembly-tlddoc.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
+
+  <id>tlddoc</id>
+
+  <formats>
+    <format>jar</format>
+  </formats>
+
+  <includeBaseDirectory>false</includeBaseDirectory>
+
+  <fileSets>
+    <fileSet>
+      <includes>
+        <include>**/*</include>
+      </includes>
+      <directory>target/tlddoc</directory>
+      <outputDirectory>/</outputDirectory>
+
+    </fileSet>
+  </fileSets>
+
+</assembly>
diff --git a/tobago-3.0.x/tobago-core/pom.xml b/tobago-3.0.x/tobago-core/pom.xml
new file mode 100644
index 0000000..173bf3e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/pom.xml
@@ -0,0 +1,328 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-core</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Core</name>
+  <description>Tobago-core contains the basic application components without any special rendering or layout options. The rendering itself depends on the theme.</description>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>${maven.compile.source}</source>
+          <target>${maven.compile.target}</target>
+          <encoding>${maven.compile.encoding}</encoding>
+          <showWarnings>true</showWarnings>
+          <!-- <compilerArgument>-Xlint:all,-serial,-fallthrough</compilerArgument>-->
+          <generatedSourcesDirectory>${project.build.directory}/generated</generatedSourcesDirectory>
+          <annotationProcessors>
+            <annotationProcessor>org.apache.myfaces.tobago.apt.processor.ClassesGenerator</annotationProcessor>
+            <annotationProcessor>org.apache.myfaces.tobago.apt.processor.TaglibGenerator</annotationProcessor>
+            <annotationProcessor>org.apache.myfaces.tobago.apt.processor.FacesConfigGenerator</annotationProcessor>
+            <annotationProcessor>org.apache.myfaces.tobago.apt.processor.CheckstyleConfigGenerator</annotationProcessor>
+          </annotationProcessors>
+          <compilerArgs>
+            <arg>-AsourceFacesConfig=${basedir}/src/main/faces-config/faces-config.xml</arg>
+            <arg>-AtargetFacesConfig=META-INF/faces-config.xml</arg>
+            <arg>-AtargetTaglib=META-INF</arg>
+            <arg>-AtargetCheckstyle=META-INF</arg>
+          </compilerArgs>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-resources</id>
+            <goals><goal>copy-resources</goal></goals>
+            <phase>process-classes</phase>
+            <configuration>
+              <outputDirectory>${project.build.outputDirectory}</outputDirectory>
+              <resources>
+                <resource>
+                  <directory>${project.build.directory}/generated</directory>
+                  <includes>
+                    <include>META-INF/**/*</include>
+                  </includes>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>test-jar</id>
+            <goals>
+             <goal>test-jar</goal>
+           </goals>
+          </execution>
+          <execution>
+            <goals>
+             <goal>jar</goal>
+           </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <archive>
+            <manifest>
+              <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+            </manifest>
+            <manifestEntries>
+              <Revision>${scm.revision}</Revision>
+            </manifestEntries>
+            <manifestSections>
+              <manifestSection>
+                <name>${project.artifactId}</name>
+                <manifestEntries>
+                  <Implementation-Vendor>${project.organization.name}</Implementation-Vendor>
+                  <Implementation-Version>${project.version}</Implementation-Version>
+                </manifestEntries>
+              </manifestSection>
+            </manifestSections>
+          </archive>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-source-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-source</id>
+            <goals><goal>jar</goal></goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <reporting>
+    <plugins>
+
+      <plugin>
+        <groupId>com.github.matinh.vdldoc</groupId>
+        <artifactId>vdldoc-maven-plugin</artifactId>
+        <configuration>
+          <destDir>tlddoc</destDir>
+          <documentTitle>Tag Library Documentation</documentTitle>
+          <excludes>
+            <exclude>target/classes/**</exclude>
+          </excludes>
+          <includes>
+            <include>target/generated/META-INF/tobago.taglib.xml</include>
+          </includes>
+          <reportOutputDirectory>target</reportOutputDirectory>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </reporting>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.core</groupId>
+      <artifactId>myfaces-api</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>commons-beanutils</groupId>
+      <artifactId>commons-beanutils</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-tool-apt</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-tool-annotation</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.test</groupId>
+      <artifactId>myfaces-test20</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-codec</groupId>
+      <artifactId>commons-codec</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.jsoup</groupId>
+      <artifactId>jsoup</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-annotation_1.0_spec</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+      <optional>true</optional>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-atinject_1.0_spec</artifactId>
+      <optional>true</optional>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>apache-release</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>com.github.matinh.vdldoc</groupId>
+            <artifactId>vdldoc-maven-plugin</artifactId>
+            <configuration>
+              <destDir>tlddoc</destDir>
+              <documentTitle>Tag Library Documentation</documentTitle>
+              <excludes>
+                <exclude>target/classes/**</exclude>
+              </excludes>
+              <includes>
+                <include>target/generated/META-INF/tobago.taglib.xml</include>
+              </includes>
+              <reportOutputDirectory>target</reportOutputDirectory>
+            </configuration>
+            <executions>
+              <execution>
+                <id>attach-tlddoc</id>
+                <phase>generate-sources</phase>
+                <goals>
+                  <goal>vdldoc</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>tlddoc-jar</id>
+                <phase>process-resources</phase>
+                <goals>
+                  <goal>assembly</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <classifier>tlddoc</classifier>
+              <descriptors>
+                <descriptor>assembly-tlddoc.xml</descriptor>
+              </descriptors>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+    <profile>
+      <id>generate-assembly</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>com.github.matinh.vdldoc</groupId>
+            <artifactId>vdldoc-maven-plugin</artifactId>
+            <configuration>
+              <destDir>tlddoc</destDir>
+              <documentTitle>Tag Library Documentation</documentTitle>
+              <excludes>
+                <exclude>target/classes/**</exclude>
+              </excludes>
+              <includes>
+                <include>target/generated/META-INF/tobago.taglib.xml</include>
+              </includes>
+              <reportOutputDirectory>target</reportOutputDirectory>
+            </configuration>
+            <executions>
+              <execution>
+                <id>attach-tlddoc</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>vdldoc</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>tlddoc-jar</id>
+                <phase>process-resources</phase>
+                <goals>
+                  <goal>assembly</goal>
+                </goals>
+              </execution>
+            </executions>
+            <configuration>
+              <classifier>tlddoc</classifier>
+              <descriptors>
+                <descriptor>assembly-tlddoc.xml</descriptor>
+              </descriptors>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>attach-source</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-source</id>
+                <goals><goal>jar</goal></goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+  </profiles>
+</project>
diff --git a/tobago-3.0.x/tobago-core/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-core/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..b1db76e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,3 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
diff --git a/tobago-3.0.x/tobago-core/src/main/faces-config/faces-config.xml b/tobago-3.0.x/tobago-core/src/main/faces-config/faces-config.xml
new file mode 100644
index 0000000..c3cad02
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/faces-config/faces-config.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<faces-config
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
+    version="2.0">
+
+  <name>tobago_core</name>
+
+  <application>
+    <default-render-kit-id>tobago</default-render-kit-id>
+    <message-bundle>org.apache.myfaces.tobago.context.TobagoResourceBundle</message-bundle>
+    <resource-bundle>
+      <base-name>org.apache.myfaces.tobago.context.TobagoResourceBundle</base-name>
+      <var>tobagoResourceBundle</var>
+    </resource-bundle>
+  </application>
+
+  <lifecycle>
+    <!--<phase-listener>org.apache.myfaces.tobago.internal.ajax.AjaxNavigationListener</phase-listener>-->
+    <phase-listener>org.apache.myfaces.tobago.lifecycle.SecretPhaseListener</phase-listener>
+  </lifecycle>
+
+  <behavior>
+    <behavior-id>org.apache.myfaces.tobago.behavior.Event</behavior-id>
+    <behavior-class>org.apache.myfaces.tobago.internal.behavior.EventBehavior</behavior-class>
+  </behavior>
+
+  <component>
+    <component-type>javax.faces.NamingContainer</component-type>
+    <component-class>org.apache.myfaces.tobago.component.UINamingContainer</component-class>
+  </component>
+
+  <converter>
+    <converter-for-class>java.util.Date</converter-for-class>
+    <converter-class>javax.faces.convert.DateTimeConverter</converter-class>
+  </converter>
+
+</faces-config>
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/application/LabelValueExpressionFacesMessage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/application/LabelValueExpressionFacesMessage.java
new file mode 100644
index 0000000..9c06472
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/application/LabelValueExpressionFacesMessage.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.application;
+
+import javax.el.ValueExpression;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+
+public class LabelValueExpressionFacesMessage extends FacesMessage {
+  public LabelValueExpressionFacesMessage() {
+    super();
+  }
+
+  public LabelValueExpressionFacesMessage(
+      final FacesMessage.Severity severity, final String summary, final String detail) {
+    super(severity, summary, detail);
+  }
+
+  public LabelValueExpressionFacesMessage(final String summary, final String detail) {
+    super(summary, detail);
+  }
+
+  public LabelValueExpressionFacesMessage(final String summary) {
+    super(summary);
+  }
+
+  @Override
+  public String getDetail() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final ValueExpression value = facesContext.getApplication().getExpressionFactory().
+        createValueExpression(facesContext.getELContext(), super.getDetail(), String.class);
+    return (String) value.getValue(facesContext.getELContext());
+  }
+
+  @Override
+  public String getSummary() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final ValueExpression value = facesContext.getApplication().getExpressionFactory().
+        createValueExpression(facesContext.getELContext(), super.getSummary(), String.class);
+    return (String) value.getValue(facesContext.getELContext());
+  }
+
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/application/ProjectStage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/application/ProjectStage.java
new file mode 100644
index 0000000..d2a3c48
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/application/ProjectStage.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.application;
+
+
+public enum ProjectStage {
+    Development,
+    Production,
+    SystemTest,
+    UnitTest;
+
+    public static final String PROJECT_STAGE_JNDI_NAME = "java:comp/env/jsf/ProjectStage";
+
+    public static final String PROJECT_STAGE_PARAM_NAME = "javax.faces.PROJECT_STAGE";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java
new file mode 100644
index 0000000..255c2b3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Attributes.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Name constants of the attributes of the Tobago components.
+ */
+public enum Attributes {
+
+  accessKey,
+  action,
+  actionListener,
+  align,
+  alignItems,
+  alt,
+  applicationIcon,
+  autoReload,
+  bodyContent,
+  border,
+  /**
+   * Used by a layout manager
+   */
+  borderBottom,
+  /**
+   * Used by a layout manager
+   */
+  borderLeft,
+  /**
+   * Used by a layout manager
+   */
+  borderRight,
+  /**
+   * Used by a layout manager
+   */
+  borderTop,
+  charset,
+  clientProperties,
+  collapsed,
+  collapsedMode,
+  column,
+  columnSpacing,
+  columns,
+  converter,
+  createSpan,
+  css,
+  cssClassesBlocks,
+  dateStyle,
+  defaultCommand,
+  delay,
+  directLinkCount,
+  disabled,
+  enctype,
+  escape,
+  expanded,
+  execute,
+  event,
+  extraSmall,
+  fieldId,
+  first,
+  fixed,
+  frequency,
+  focus,
+  focusId,
+  formatPattern,
+  forValue("for"),
+  globalOnly,
+  height,
+  hidden,
+  hover,
+  i18n,
+  iconSize,
+  id,
+  immediate,
+  image,
+  inline,
+  itemDescription,
+  itemDisabled,
+  itemLabel,
+  itemImage,
+  itemValue,
+  label,
+  labelLayout,
+  labelPosition,
+  labelWidth,
+  large,
+  layoutOrder,
+  left,
+  link,
+  /** @deprecated since Tobago 2.0.0 */
+  @Deprecated
+  margin,
+  /**
+   * Used by a layout manager
+   */
+  marginBottom,
+  /**
+   * Used by a layout manager
+   */
+  marginLeft,
+  /**
+   * Used by a layout manager
+   */
+  marginRight,
+  /**
+   * Used by a layout manager
+   */
+  marginTop,
+  marked,
+  markup,
+  max,
+  maxSeverity,
+  maxNumber,
+  maximumHeight,
+  maximumWidth,
+  method,
+  min,
+  minSeverity,
+  minimumHeight,
+  minimumWidth,
+  medium,
+  modal,
+  mode,
+  mutable,
+  name,
+  navigate,
+  numberStyle,
+  omit,
+  /** @deprecated */
+  @Deprecated
+  onclick,
+  /** @deprecated */
+  @Deprecated
+  onchange,
+  orderBy,
+  orientation,
+  /**
+   * Used by a layout manager
+   */
+  paddingBottom,
+  /**
+   * Used by a layout manager
+   */
+  paddingLeft,
+  /**
+   * Used by a layout manager
+   */
+  paddingRight,
+  /**
+   * Used by a layout manager
+   */
+  paddingTop,
+  pagingTarget,
+  password,
+  placeholder,
+  popupClose,
+  popupList,
+  popupReset,
+  popupCalendarId,
+  preferredHeight,
+  preferredWidth,
+  preformated,
+  readonly,
+  reference,
+  relative,
+  rendered,
+  rendererType,
+  renderAs,
+  renderRange,
+  renderRangeExtern,
+  required,
+  resizable,
+  rowId,
+  row,
+  rowSpacing,
+  rows,
+  scriptFiles,
+  scrollbarHeight,
+  scrollbars,
+  // Attribute name could not be the same as the method name
+  // this cause an infinite loop on attribute map
+  scrollPosition,
+  selectedIndex,
+  selectedListString,
+  selectable,
+  sheetAction,
+  showDirectLinks,
+  showDirectLinksArrows,
+  showHeader,
+  showJunctions,
+  showNavigationBar,
+  showPageRange,
+  showPageRangeArrows,
+  showPagingAlways,
+  showRoot,
+  showRootJunction,
+  showRowRange,
+  showSummary,
+  showDetail,
+  size,
+  sortable,
+  sortActionListener,
+  small,
+  spanX,
+  spanY,
+  src,
+  state,
+  stateChangeListener,
+  statePreview,
+  style,
+  switchType,
+  tabIndex,
+  target,
+  timeStyle,
+  textAlign,
+  timezone,
+  title,
+  tip,
+  top,
+  transition,
+  type,
+  value,
+  valueChangeListener,
+  var,
+  unit,
+  update,
+  validator,
+  width,
+  widthList,
+  zIndex;
+
+  private static final Logger LOG = LoggerFactory.getLogger(Attributes.class);
+
+  /** This constants are needed for annotations, because they can't use the enums. */
+  public static final String EXECUTE = "execute";
+
+  private final String explicit;
+
+  Attributes() {
+    this(null);
+  }
+
+  Attributes(String explicit) {
+    this.explicit = explicit;
+  }
+
+  public String getName() {
+    if (explicit != null) {
+      return explicit;
+    } else {
+      return name();
+    }
+  }
+
+  public static Attributes valueOfFailsafe(String name) {
+    try {
+      return Attributes.valueOf(name);
+    } catch (IllegalArgumentException e) {
+      LOG.warn("Can't find enum for {} with name '{}'", Attributes.class.getName(), name);
+      return null;
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/ClientBehaviors.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/ClientBehaviors.java
new file mode 100644
index 0000000..b62fac7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/ClientBehaviors.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+public enum ClientBehaviors {
+
+  blur,
+  change,
+  click,
+  complete,
+  dblclick,
+  focus,
+  load,
+  mouseover,
+  mouseout,
+  reload, // tbd
+  resize,
+  suggest; // tbd
+
+  public static final String BLUR = "blur";
+  public static final String CHANGE = "change";
+  public static final String CLICK = "click";
+  public static final String COMPLETE = "complete";
+  public static final String DBLCLICK = "dblclick";
+  public static final String FOCUS = "focus";
+  public static final String LOAD = "load";
+  public static final String MOUSEOVER = "mouseover";
+  public static final String MOUSEOUT = "mouseout";
+  public static final String RELOAD = "reload"; // tbd
+  public static final String RESIZE = "resize";
+  public static final String SUGGEST = "suggest"; // tbd
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/DeprecatedDimension.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/DeprecatedDimension.java
new file mode 100644
index 0000000..fd6e526
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/DeprecatedDimension.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.layout.Measure;
+
+public interface DeprecatedDimension {
+
+  Measure getHeight();
+
+  void setHeight(Measure height);
+
+  Measure getWidth();
+
+  void setWidth(Measure width);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Facets.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Facets.java
new file mode 100644
index 0000000..a6f3763
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Facets.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+public enum Facets {
+
+  after,
+  bar,
+  before,
+  brand,
+  checkbox,
+  confirmation,
+  constraints,
+  /**
+  * @deprecated currently not supported
+   */
+  @Deprecated
+  contextMenu,
+  label,
+  /**
+   * @deprecated since 3.0.0. The layout manager tag should surround the content instead.
+   * Is only for &lt;tc:gridLayout&gt; needed.
+   */
+  @Deprecated
+  layout,
+  pagerPage,
+  pagerPageDirect,
+  pagerRow,
+  radio,
+  reload(true),
+  sorter;
+
+  Facets() {
+  }
+
+  @Deprecated
+  Facets(boolean event) {
+  }
+
+  public static final String AFTER = "after";
+  public static final String BAR = "bar";
+  public static final String BEFORE = "before";
+  public static final String BRAND = "brand";
+  public static final String CHECKBOX = "checkbox";
+  public static final String CONFIRMATION = "confirmation";
+  public static final String CONSTRAINTS = "constraints";
+  /**
+   * @deprecated currently not supported
+   */
+  @Deprecated
+  public static final String CONTEXT_MENU = "contextMenu";
+  public static final String LABEL = "label";
+  /**
+   * @deprecated since 3.0.0. The layout manager tag should surround the content instead.
+   */
+  @Deprecated
+  public static final String LAYOUT = "layout";
+  public static final String PAGER_PAGE = "pagerPage";
+  public static final String PAGER_PAGE_DIRECT = "pagerPageDirect";
+  public static final String PAGER_ROW = "pagerRow";
+  public static final String RADIO = "radio";
+  /**
+   * TODO: Must be replaced by a behavior
+   */
+  public static final String RELOAD = "reload";
+  public static final String SORTER = "sorter";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/InputSuggest.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/InputSuggest.java
new file mode 100644
index 0000000..ee86208
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/InputSuggest.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import javax.faces.el.MethodBinding;
+
+public interface InputSuggest {
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  MethodBinding getSuggestMethod();
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  void setSuggestMethod(MethodBinding suggestMethod);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/InputSuggest2.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/InputSuggest2.java
new file mode 100644
index 0000000..1d2160b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/InputSuggest2.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import javax.el.MethodExpression;
+
+public interface InputSuggest2 extends InputSuggest {
+  
+  MethodExpression getSuggestMethodExpression();
+
+  void setSuggestMethodExpression(MethodExpression suggestExpression);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/LabelLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/LabelLayout.java
new file mode 100644
index 0000000..26a326d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/LabelLayout.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import javax.faces.context.FacesContext;
+
+public enum LabelLayout {
+
+  /**
+   * do not render the label
+   */
+  none,
+
+  /**
+   * flex layout: let the label be on the left side
+   */
+  flexLeft,
+
+  /**
+   * flex layout: let the label be on the right side
+   */
+  flexRight,
+
+  /**
+   * let the label be on the top of the element
+   */
+  top,
+
+  /**
+   * segment layout: let the label be on the left side
+   */
+  segmentLeft,
+
+  /**
+   * segment layout: let the label be on the right side
+   */
+  segmentRight,
+
+  /**
+   * flow layout: let the label be on the left side
+   */
+  flowLeft,
+
+  /**
+   * flow layout: let the label be on the right side
+   */
+  flowRight,
+
+  /**
+   * skip rendering the surrounding container.
+   */
+  skip;
+
+  private static final String SEGMENT_TO_RENDER_KEY = LabelLayout.class.getName();
+
+  public static boolean isSegment(final LabelLayout labelLayout) {
+    return labelLayout == segmentLeft || labelLayout == segmentRight;
+  }
+
+  public static void setSegment(final FacesContext facesContext, final LabelLayout labelLayout) {
+    if (labelLayout != segmentLeft && labelLayout != segmentRight) {
+      throw new IllegalArgumentException("not supported: " + labelLayout);
+    }
+    facesContext.getAttributes().put(SEGMENT_TO_RENDER_KEY, labelLayout);
+  }
+
+  public static LabelLayout getSegment(final FacesContext facesContext) {
+    return (LabelLayout) facesContext.getAttributes().get(SEGMENT_TO_RENDER_KEY);
+  }
+
+  public static void removeSegment(FacesContext facesContext) {
+    facesContext.getAttributes().remove(SEGMENT_TO_RENDER_KEY);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/MethodBindingToMethodExpression.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/MethodBindingToMethodExpression.java
new file mode 100644
index 0000000..963ee17
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/MethodBindingToMethodExpression.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.MethodExpression;
+import javax.el.MethodInfo;
+import javax.el.MethodNotFoundException;
+import javax.faces.FacesException;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.el.EvaluationException;
+import javax.faces.el.MethodBinding;
+
+/**
+ * @deprecated since 2.0.0
+ */
+@Deprecated
+public class MethodBindingToMethodExpression extends MethodExpression implements StateHolder {
+  private MethodBinding methodBinding;
+
+  private boolean transientFlag;
+
+  private transient MethodInfo methodInfo;
+
+  /**
+   * No-arg constructor used during restoreState
+   */
+  public MethodBindingToMethodExpression() {
+  }
+
+  /**
+   * Creates a new instance of MethodBindingToMethodExpression
+   * @param methodBinding The MethodBinding to wrap.
+   */
+  public MethodBindingToMethodExpression(final MethodBinding methodBinding) {
+    checkNullArgument(methodBinding, "methodBinding");
+    this.methodBinding = methodBinding;
+  }
+
+  /**
+   * Return the wrapped MethodBinding.
+   * @return the wrapped MethodBinding
+   */
+  public MethodBinding getMethodBinding() {
+    return methodBinding;
+  }
+
+  void setMethodBinding(final MethodBinding methodBinding) {
+    this.methodBinding = methodBinding;
+  }
+
+  /**
+   * Note: MethodInfo.getParamTypes() may incorrectly return an empty class array if invoke() has not been called.
+   *
+   * @throws IllegalStateException if expected params types have not been determined.
+   */
+  @Override
+  public MethodInfo getMethodInfo(final ELContext context) throws ELException {
+    checkNullArgument(context, "elcontext");
+    checkNullState(methodBinding, "methodBinding");
+
+    if (methodInfo == null) {
+      final FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
+      if (facesContext != null) {
+        methodInfo = invoke(new Invoker<MethodInfo>() {
+          @Override
+          public MethodInfo invoke() {
+            return new MethodInfo(null, methodBinding.getType(facesContext), null);
+          }
+        });
+      }
+    }
+    return methodInfo;
+  }
+
+  @Override
+  public Object invoke(final ELContext context, final Object[] params) throws ELException {
+    checkNullArgument(context, "elcontext");
+    checkNullState(methodBinding, "methodBinding");
+    final FacesContext facesContext = (FacesContext) context.getContext(FacesContext.class);
+    if (facesContext != null) {
+      return invoke(new Invoker<Object>() {
+        @Override
+        public Object invoke() {
+          return methodBinding.invoke(facesContext, params);
+        }
+      });
+    }
+    return null;
+  }
+
+  @Override
+  public boolean isLiteralText() {
+    if (methodBinding == null) {
+      throw new IllegalStateException("methodBinding is null");
+    }
+    final String expr = methodBinding.getExpressionString();
+    return !(expr.startsWith("#{") && expr.endsWith("}"));
+  }
+
+  @Override
+  public String getExpressionString() {
+    return methodBinding.getExpressionString();
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    if (!isTransient()) {
+      if (methodBinding instanceof StateHolder) {
+        final Object[] state = new Object[2];
+        state[0] = methodBinding.getClass().getName();
+        state[1] = ((StateHolder) methodBinding).saveState(context);
+        return state;
+      } else {
+        return methodBinding;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    if (state instanceof MethodBinding) {
+      methodBinding = (MethodBinding) state;
+      methodInfo = null;
+    } else if (state != null) {
+      final Object[] values = (Object[]) state;
+      methodBinding = (MethodBinding) newInstance(values[0].toString());
+      ((StateHolder) methodBinding).restoreState(context, values[1]);
+      methodInfo = null;
+    }
+  }
+
+  @Override
+  public void setTransient(final boolean transientFlag) {
+    this.transientFlag = transientFlag;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return transientFlag;
+  }
+
+  @Override
+  public int hashCode() {
+    final int prime = 31;
+    int result = 1;
+    result = prime * result + ((methodBinding == null) ? 0 : methodBinding.hashCode());
+    return result;
+  }
+
+  @Override
+  public boolean equals(final Object obj) {
+    if (this == obj) {
+      return true;
+    }
+    if (obj == null) {
+      return false;
+    }
+    if (getClass() != obj.getClass()) {
+      return false;
+    }
+    final MethodBindingToMethodExpression other = (MethodBindingToMethodExpression) obj;
+    if (methodBinding == null) {
+      if (other.methodBinding != null) {
+        return false;
+      }
+    } else if (!methodBinding.equals(other.methodBinding)) {
+      return false;
+    }
+    return true;
+  }
+
+  private void checkNullState(final Object notNullInstance, final String instanceName) {
+    if (notNullInstance == null) {
+      throw new IllegalStateException(instanceName + " is null");
+    }
+  }
+
+  private void checkNullArgument(final Object notNullInstance, final String instanceName) {
+    if (notNullInstance == null) {
+      throw new IllegalArgumentException(instanceName + " is null");
+    }
+  }
+
+  private <T> T invoke(final Invoker<T> invoker) {
+    try {
+      return invoker.invoke();
+    } catch (final javax.faces.el.MethodNotFoundException e) {
+      throw new MethodNotFoundException(e.getMessage(), e);
+    } catch (final EvaluationException e) {
+      throw new ELException(e.getMessage(), e);
+    }
+  }
+
+  private interface Invoker<T> {
+    T invoke();
+  }
+
+  private static Object newInstance(final String type) {
+    if (type == null) {
+      throw new NullPointerException("type");
+    }
+    try {
+      try {
+        return Class.forName(type, false, Thread.currentThread().getContextClassLoader()).newInstance();
+      } catch (final ClassNotFoundException e) {
+        // ignore
+        return Class.forName(type, false, MethodBindingToMethodExpression.class.getClassLoader()).newInstance();
+      }
+    } catch (final ClassNotFoundException e) {
+      throw new FacesException(e);
+    } catch (final NoClassDefFoundError e) {
+      throw new FacesException(e);
+    } catch (final InstantiationException e) {
+      throw new FacesException(e);
+    } catch (final IllegalAccessException e) {
+      throw new FacesException(e);
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/MethodExpressionToMethodBinding.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/MethodExpressionToMethodBinding.java
new file mode 100644
index 0000000..7d0ad96
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/MethodExpressionToMethodBinding.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import javax.el.ELException;
+import javax.el.MethodExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.el.EvaluationException;
+import javax.faces.el.MethodBinding;
+import javax.faces.el.MethodNotFoundException;
+
+/**
+ * @deprecated since 2.0.0
+ */
+@Deprecated
+public class MethodExpressionToMethodBinding extends MethodBinding implements StateHolder {
+
+  private MethodExpression methodExpression;
+
+  private boolean isTransient = false;
+
+  public MethodExpressionToMethodBinding() {
+    methodExpression = null;
+  }
+
+  /**
+   * Creates a new instance of MethodExpressionToMethodBinding
+   */
+  public MethodExpressionToMethodBinding(final MethodExpression methodExpression) {
+    this.methodExpression = methodExpression;
+  }
+
+  @Override
+  public String getExpressionString() {
+    return methodExpression.getExpressionString();
+  }
+
+  @Override
+  public Class getType(final FacesContext facesContext)
+      throws MethodNotFoundException {
+
+    try {
+      return methodExpression.getMethodInfo(facesContext.getELContext()).getReturnType();
+    } catch (final javax.el.MethodNotFoundException e) {
+      throw new javax.faces.el.MethodNotFoundException(e);
+    } catch (final ELException e) {
+      throw new EvaluationException(e);
+    }
+  }
+
+  @Override
+  public Object invoke(final FacesContext facesContext, final Object[] params)
+      throws EvaluationException {
+
+    try {
+      return methodExpression.invoke(facesContext.getELContext(), params);
+    } catch (final javax.el.MethodNotFoundException e) {
+      throw new javax.faces.el.MethodNotFoundException(e);
+    } catch (final ELException e) {
+      throw new EvaluationException(e);
+    }
+  }
+
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    if (state != null) {
+      methodExpression = (MethodExpression) state;
+    }
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    if (!isTransient) {
+      return methodExpression;
+    }
+    return null;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    isTransient = newTransientValue;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return isTransient;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
new file mode 100644
index 0000000..d2dca0a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/RendererTypes.java
@@ -0,0 +1,152 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+/**
+ * Constants for the renderer type
+ */
+public enum RendererTypes {
+
+  Bar,
+  Box,
+  Button,
+  Buttons,
+  Calendar,
+  Column,
+  ColumnSelector,
+  Date,
+  Event,
+  Figure,
+  File,
+  FlexLayout,
+  FlowLayout,
+  Footer,
+  Form,
+  GridLayout,
+  Header,
+  Hidden,
+  In,
+  Image,
+  Link,
+  Links,
+  Label,
+  Messages,
+  Object,
+  Operation,
+  Out,
+  Page,
+  Panel,
+  Popup,
+  Progress,
+  Row,
+  Script,
+  Section,
+  SegmentLayout,
+  SelectBooleanCheckbox,
+  SelectManyCheckbox,
+  SelectManyListbox,
+  SelectManyShuttle,
+  SelectOneChoice,
+  SelectOneRadio,
+  SelectOneListbox,
+  SelectReference,
+  Separator,
+  Sheet,
+  SheetPageCommand,
+  Style,
+  Suggest,
+  Textarea,
+  Tab,
+  TabGroup,
+  ToolBar,
+  Tree,
+  TreeData,
+  TreeCommand,
+  TreeIcon,
+  TreeIndent,
+  TreeLabel,
+  TreeListbox,
+  TreeMenu,
+  TreeNode,
+  TreeSelect;
+
+  public static final String BAR = "Bar";
+  public static final String BOX = "Box";
+  public static final String BUTTON = "Button";
+  public static final String BUTTONS = "Buttons";
+  public static final String CALENDAR = "Calendar";
+  public static final String COLUMN = "Column";
+  public static final String COLUMN_SELECTOR = "ColumnSelector";
+  public static final String EVENT = "Event";
+  public static final String DATE = "Date";
+  public static final String FIGURE = "Figure";
+  public static final String FILE = "File";
+  public static final String FLEX_LAYOUT = "FlexLayout";
+  public static final String FLOW_LAYOUT = "FlowLayout";
+  public static final String FOOTER = "Footer";
+  public static final String FORM = "Form";
+  public static final String GRID_LAYOUT = "GridLayout";
+  public static final String HEADER = "Header";
+  public static final String HIDDEN = "Hidden";
+  public static final String IN = "In";
+  public static final String IMAGE = "Image";
+  public static final String LINK = "Link";
+  public static final String LINKS = "Links";
+  public static final String LABEL = "Label";
+  public static final String MESSAGES = "Messages";
+  public static final String OBJECT = "Object";
+  public static final String OPERATION = "Operation";
+  public static final String OUT = "Out";
+  public static final String PAGE = "Page";
+  public static final String PANEL = "Panel";
+  public static final String POPUP = "Popup";
+  public static final String PROGRESS = "Progress";
+  public static final String ROW = "Row";
+  public static final String SCRIPT = "Script";
+  public static final String SECTION = "Section";
+  public static final String SEGMENT_LAYOUT = "SegmentLayout";
+  public static final String SELECT_BOOLEAN_CHECKBOX = "SelectBooleanCheckbox";
+  public static final String SELECT_MANY_CHECKBOX = "SelectManyCheckbox";
+  public static final String SELECT_MANY_LISTBOX = "SelectManyListbox";
+  public static final String SELECT_MANY_SHUTTLE = "SelectManyShuttle";
+  public static final String SELECT_ONE_CHOICE = "SelectOneChoice";
+  public static final String SELECT_ONE_RADIO = "SelectOneRadio";
+  public static final String SELECT_ONE_LISTBOX = "SelectOneListbox";
+  public static final String SELECT_REFERENCE = "SelectReference";
+  public static final String SEPARATOR = "Separator";
+  public static final String SHEET = "Sheet";
+  public static final String SHEET_PAGE_COMMAND = "SheetPageCommand";
+  public static final String STYLE = "Style";
+  public static final String SUGGEST = "Suggest";
+  public static final String TEXTAREA = "Textarea";
+  public static final String TAB = "Tab";
+  public static final String TAB_GROUP = "TabGroup";
+  public static final String TOOL_BAR = "ToolBar";
+  public static final String TREE = "Tree";
+  public static final String TREE_DATA = "TreeData";
+  public static final String TREE_COMMAND = "TreeCommand";
+  public static final String TREE_ICON = "TreeIcon";
+  public static final String TREE_INDENT = "TreeIndent";
+  public static final String TREE_LABEL = "TreeLabel";
+  public static final String TREE_LISTBOX = "TreeListbox";
+  public static final String TREE_MENU = "TreeMenu";
+  public static final String TREE_NODE = "TreeNode";
+  public static final String TREE_SELECT = "TreeSelect";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SelectBooleanCommand.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SelectBooleanCommand.java
new file mode 100644
index 0000000..6173f49
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SelectBooleanCommand.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+public interface SelectBooleanCommand {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SelectOneCommand.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SelectOneCommand.java
new file mode 100644
index 0000000..a85ce5e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SelectOneCommand.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+public interface SelectOneCommand {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Sorter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Sorter.java
new file mode 100644
index 0000000..9420c94
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Sorter.java
@@ -0,0 +1,259 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.event.SortActionEvent;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.component.AbstractUISheet;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.model.SheetState;
+import org.apache.myfaces.tobago.util.BeanComparator;
+import org.apache.myfaces.tobago.util.ValueExpressionComparator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIColumn;
+import javax.faces.component.UICommand;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UIOutput;
+import javax.faces.component.UISelectBoolean;
+import javax.faces.component.UISelectMany;
+import javax.faces.component.UISelectOne;
+import javax.faces.context.FacesContext;
+import javax.faces.model.DataModel;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+public class Sorter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Sorter.class);
+
+  private Comparator comparator;
+
+  /**
+   * @deprecated Please use {@link #perform(org.apache.myfaces.tobago.internal.component.AbstractUISheet)}
+   */
+  @Deprecated
+  public void perform(final SortActionEvent sortEvent) {
+    final AbstractUISheet data = (AbstractUISheet) sortEvent.getComponent();
+    perform(data);
+  }
+
+  public void perform(final AbstractUISheet data) {
+
+    Object value = data.getValue();
+    if (value instanceof DataModel) {
+      value = ((DataModel) value).getWrappedData();
+    }
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final SheetState sheetState = data.getSheetState(facesContext);
+
+    final String sortedColumnId = sheetState.getSortedColumnId();
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("sorterId = '{}'", sortedColumnId);
+    }
+
+    if (sortedColumnId == null) {
+      // not to be sorted
+      return;
+    }
+
+    final UIColumn column = (UIColumn) data.findComponent(sortedColumnId);
+    if (column == null) {
+      LOG.warn("No column to sort found, sorterId = '{}'", sortedColumnId);
+      return;
+    }
+
+    final Comparator actualComparator;
+
+    if (value instanceof List || value instanceof Object[]) {
+      final String sortProperty;
+
+      try {
+        final UIComponent child = getFirstSortableChild(column.getChildren());
+        if (child != null) {
+
+          final Attributes attribute = child instanceof AbstractUICommand ? Attributes.label : Attributes.value;
+          if (child.getValueExpression(attribute.getName()) != null) {
+            final String var = data.getVar();
+            if (var == null) {
+                LOG.error("No sorting performed. Property var of sheet is not set!");
+                unsetSortableAttribute(column);
+                return;
+            }
+            String expressionString = child.getValueExpression(attribute.getName()).getExpressionString();
+            if (isSimpleProperty(expressionString)) {
+              if (expressionString.startsWith("#{")
+                  && expressionString.endsWith("}")) {
+                expressionString =
+                    expressionString.substring(2,
+                        expressionString.length() - 1);
+              }
+              sortProperty = expressionString.substring(var.length() + 1);
+
+              actualComparator = new BeanComparator(
+                  sortProperty, comparator, !sheetState.isAscending());
+
+              if (LOG.isDebugEnabled()) {
+                LOG.debug("Sort property is {}", sortProperty);
+              }
+            } else {
+
+              final boolean descending = !sheetState.isAscending();
+              final ValueExpression expression = child.getValueExpression("value");
+              actualComparator = new ValueExpressionComparator(facesContext, var, expression, descending, comparator);
+            }
+          } else {
+              LOG.error("No sorting performed. No Expression target found for sorting!");
+              unsetSortableAttribute(column);
+              return;
+          }
+        } else {
+          LOG.error("No sorting performed. Value is not instanceof List or Object[]!");
+          unsetSortableAttribute(column);
+          return;
+        }
+      } catch (final Exception e) {
+        LOG.error("Error while extracting sortMethod :" + e.getMessage(), e);
+        if (column != null) {
+          unsetSortableAttribute(column);
+        }
+        return;
+      }
+
+      // TODO: locale / comparator parameter?
+      // don't compare numbers with Collator.getInstance() comparator
+//        Comparator comparator = Collator.getInstance();
+//          comparator = new RowComparator(ascending, method);
+
+      // memorize selected rows
+      List<Object> selectedDataRows = null;
+      if (sheetState.getSelectedRows().size() > 0) {
+        selectedDataRows = new ArrayList<Object>(sheetState.getSelectedRows().size());
+        Object dataRow;
+        for (final Integer index : sheetState.getSelectedRows()) {
+          if (value instanceof List) {
+            dataRow = ((List) value).get(index);
+          } else {
+            dataRow = ((Object[]) value)[index];
+          }
+          selectedDataRows.add(dataRow);
+        }
+      }
+
+      // do sorting
+      if (value instanceof List) {
+        Collections.sort((List) value, actualComparator);
+      } else { // value is instanceof Object[]
+        Arrays.sort((Object[]) value, actualComparator);
+      }
+
+      // restore selected rows
+      if (selectedDataRows != null) {
+        sheetState.getSelectedRows().clear();
+        for (final Object dataRow : selectedDataRows) {
+          int index = -1;
+          if (value instanceof List) {
+            for (int i = 0; i < ((List) value).size() && index < 0; i++) {
+              if (dataRow == ((List) value).get(i)) {
+                index = i;
+              }
+            }
+          } else {
+            for (int i = 0; i < ((Object[]) value).length && index < 0; i++) {
+              if (dataRow == ((Object[]) value)[i]) {
+                index = i;
+              }
+            }
+          }
+          if (index >= 0) {
+            sheetState.getSelectedRows().add(index);
+          }
+        }
+      }
+
+    } else {  // DataModel?, ResultSet, Result or Object
+      LOG.warn("Sorting not supported for type "
+          + (value != null ? value.getClass().toString() : "null"));
+    }
+  }
+
+  // XXX needs to be tested
+  // XXX was based on ^#\{(\w+(\.\w)*)\}$ which is wrong, because there is a + missing after the last \w
+  boolean isSimpleProperty(final String expressionString) {
+    if (expressionString.startsWith("#{") && expressionString.endsWith("}")) {
+      final String inner = expressionString.substring(2, expressionString.length() - 1);
+      final String[] parts = StringUtils.split(inner, '.');
+      for (final String part : parts) {
+        if (!StringUtils.isAlpha(part)) {
+          return false;
+        }
+      }
+      return true;
+    }
+    return false;
+  }
+
+  private void unsetSortableAttribute(final UIColumn uiColumn) {
+    LOG.warn("removing attribute sortable from column " + uiColumn.getId());
+    uiColumn.getAttributes().put(Attributes.sortable.getName(), Boolean.FALSE);
+  }
+
+  private UIComponent getFirstSortableChild(final List<UIComponent> children) {
+    UIComponent result = null;
+
+    for (UIComponent child : children) {
+      result = child;
+      if (child instanceof UISelectMany
+          || child instanceof UISelectOne
+          || child instanceof UISelectBoolean
+          || (child instanceof AbstractUICommand && child.getChildren().isEmpty())
+          || (child instanceof UIInput && RendererTypes.HIDDEN.equals(child.getRendererType()))) {
+        continue;
+        // look for a better component if any
+      }
+      if (child instanceof UIOutput) {
+        break;
+      }
+      if (child instanceof UICommand
+          || child instanceof javax.faces.component.UIPanel) {
+        child = getFirstSortableChild(child.getChildren());
+        if (child instanceof UIOutput) {
+          break;
+        }
+      }
+    }
+    return result;
+  }
+
+  public Comparator getComparator() {
+    return comparator;
+  }
+
+  public void setComparator(final Comparator comparator) {
+    this.comparator = comparator;
+  }
+}
+
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportFieldId.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportFieldId.java
new file mode 100644
index 0000000..8edddd0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportFieldId.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import javax.faces.context.FacesContext;
+
+public interface SupportFieldId {
+
+  String getFieldId(final FacesContext facesContext);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsAccessKey.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsAccessKey.java
new file mode 100644
index 0000000..4acd6ee
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsAccessKey.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+public interface SupportsAccessKey {
+
+  Character getAccessKey();
+
+  String getLabel();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsLabelLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsLabelLayout.java
new file mode 100644
index 0000000..1f316a5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsLabelLayout.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+public interface SupportsLabelLayout {
+
+  LabelLayout getLabelLayout();
+
+  void setLabelLayout(LabelLayout labelLayout);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsStyle.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsStyle.java
new file mode 100644
index 0000000..32ad9fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/SupportsStyle.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.renderkit.css.CustomClass;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+
+public interface SupportsStyle {
+
+  Style getStyle();
+
+  void setStyle(Style style);
+
+  CustomClass getCustomClass();
+
+  void setCustomClass(CustomClass customClass);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/UINamingContainer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/UINamingContainer.java
new file mode 100644
index 0000000..cf91f88
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/UINamingContainer.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+public class UINamingContainer
+    extends javax.faces.component.UINamingContainer {
+
+  public static final String COMPONENT_TYPE = "javax.faces.NamingContainer";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Visual.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Visual.java
new file mode 100644
index 0000000..022a38f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/component/Visual.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.renderkit.css.CustomClass;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+
+public interface Visual {
+
+  Markup getMarkup();
+
+  void setMarkup(Markup markup);
+
+  Style getStyle();
+
+  void setStyle(Style style);
+
+  CustomClass getCustomClass();
+
+  void setCustomClass(CustomClass customClass);
+
+  /**
+   * The renderer is an id that is used by Tobago to gather information about the components which are
+   * configured in the theme configuration files. E. g. the preferredWidth of a component.
+   * @return The renderer type.
+   */
+  String getRendererType();
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java
new file mode 100644
index 0000000..6e081e3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/config/TobagoConfig.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.config;
+
+import org.apache.myfaces.tobago.application.ProjectStage;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.internal.config.ContentSecurityPolicy;
+import org.apache.myfaces.tobago.sanitizer.Sanitizer;
+
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletContext;
+import java.util.List;
+import java.util.Map;
+
+public abstract class TobagoConfig {
+
+  public static final String TOBAGO_CONFIG = "org.apache.myfaces.tobago.config.TobagoConfig";
+
+  public static TobagoConfig getInstance(final FacesContext facesContext) {
+    return (TobagoConfig) facesContext.getExternalContext().getApplicationMap().get(TOBAGO_CONFIG);
+  }
+
+  public static TobagoConfig getInstance(final ServletContext servletContext) {
+    return (TobagoConfig) servletContext.getAttribute(TOBAGO_CONFIG);
+  }
+
+  public abstract Theme getTheme(final String name);
+
+  public abstract List<Theme> getSupportedThemes();
+
+  public abstract Theme getDefaultTheme();
+
+  public abstract ProjectStage getProjectStage();
+
+  public abstract boolean isCreateSessionSecret();
+
+  public abstract boolean isCheckSessionSecret();
+
+  public abstract boolean isPreventFrameAttacks();
+
+  public abstract ContentSecurityPolicy getContentSecurityPolicy();
+
+  public abstract boolean isSetNosniffHeader();
+
+  public abstract Sanitizer getSanitizer();
+
+  public abstract Map<String, String> getMimeTypes();
+
+  /**
+   * @return false
+   * @deprecated since Tobago 3.0.0
+   */
+  @Deprecated
+  public abstract boolean isClassicDateTimePicker();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Capability.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Capability.java
new file mode 100644
index 0000000..0d006c6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Capability.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+public enum Capability {
+
+  /**
+   * Support for the placeholder in HTML 5.
+   */
+  PLACEHOLDER,
+
+  /**
+   * Does the user agent support "application/xhtml+xml" as content type?
+   */
+  CONTENT_TYPE_XHTML,
+
+  /**
+   * In IE 8 and later, a compatibility mode can be activated in the user agent.
+   * For Tobago pages this should not be activated. So this property can be used to
+   * decide, if a warning should be rendered.
+   */
+  IE_COMPATIBILITY_MODE
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Markup.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Markup.java
new file mode 100644
index 0000000..795b494
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Markup.java
@@ -0,0 +1,369 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.apache.commons.collections.iterators.EmptyIterator;
+import org.apache.commons.collections.iterators.ObjectArrayIterator;
+import org.apache.commons.collections.iterators.SingletonIterator;
+import org.apache.myfaces.tobago.internal.util.ArrayUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * <p>
+ * A markup signs a component to be rendered different from the normal.
+ * E. g. <code>markup="emphasized"</code> might be rendered bold
+ * or a <code>markup="deleted"</code> might be rendered with line-through style.
+ * The concrete rendering depends from the theme.
+ * </p>
+ * <p>
+ * The markup can also hold more than one value, e. g. <code>markup="emphasized, deleted"</code>.
+ * </p>
+ * <p>
+ * The value of the markup is unmodifiable.
+ * </p>
+ * <p>
+ * A markup must be registered for a component, before it can be used.
+ * </p>
+ * <p>
+ * A markup should only contain ASCII characters and digits.
+ * </p>
+ * <p>
+ * In JSPs the class {@link org.apache.myfaces.tobago.context.MarkupEditor} will convert the string literals.
+ * </p>
+ */
+public final class Markup implements Serializable, Iterable<String> {
+
+  public static final Markup NULL = new Markup((String) null);
+
+  public static final Markup ASCENDING = valueOf("ascending");
+  public static final Markup BIG = valueOf("big");
+  public static final Markup BORDERED = valueOf("bordered");
+  public static final Markup CENTER = valueOf("center");
+  public static final Markup CLICKABLE = valueOf("clickable");
+  public static final Markup DEFAULT = valueOf("default");
+  public static final Markup DELETED = valueOf("deleted");
+  public static final Markup DESCENDING = valueOf("descending");
+  public static final Markup DISABLED = valueOf("disabled");
+  public static final Markup ERROR = valueOf("error");
+  public static final Markup EVEN = valueOf("even");
+  public static final Markup EXPANDED = valueOf("expanded");
+  public static final Markup FILLER = valueOf("filler");
+  public static final Markup FATAL = valueOf("fatal");
+  /**
+   * @deprecated Can be selected via CSS3.
+   */
+  @Deprecated
+  public static final Markup FIRST = valueOf("first");
+  public static final Markup FOLDER = valueOf("folder");
+  public static final Markup HOVER = valueOf("hover");
+  public static final Markup INFO = valueOf("info");
+  public static final Markup INLINE = valueOf("inline");
+  public static final Markup JUSTIFY = valueOf("justify");
+  public static final Markup INVERSE = valueOf("inverse");
+  public static final Markup LEFT = valueOf("left");
+  public static final Markup MARKED = valueOf("marked");
+  public static final Markup MODAL = valueOf("modal");
+  public static final Markup NUMBER = valueOf("number");
+  public static final Markup ODD = valueOf("odd");
+  public static final Markup PORTLET = valueOf("portlet");
+  public static final Markup READONLY = valueOf("readonly");
+  public static final Markup REQUIRED = valueOf("required");
+  public static final Markup RESIZABLE = valueOf("resizable");
+  public static final Markup RIGHT = valueOf("right");
+  public static final Markup SECONDS = valueOf("seconds");
+  public static final Markup SELECTED = valueOf("selected");
+  public static final Markup SHEET_SELECT_ALL = valueOf("sheetSelectAll");
+  public static final Markup SHEET_DESELECT_ALL = valueOf("sheetDeselectAll");
+  public static final Markup SHEET_TOGGLE_ALL = valueOf("sheetToggleAll");
+  public static final Markup SMALL = valueOf("small");
+  public static final Markup SORTABLE = valueOf("sortable");
+  public static final Markup SPREAD = valueOf("spread");
+  public static final Markup STRIPED = valueOf("striped");
+  public static final Markup STRONG = valueOf("strong");
+  public static final Markup TOP = valueOf("top");
+  public static final Markup VERTICALLY = valueOf("vertically");
+  public static final Markup WARN = valueOf("warn");
+
+  /* Just one of "values" and "value" must be null */
+
+  private final String[] values;
+  private final String value;
+
+  private Markup(final String[] values) {
+    this.values = values;
+    this.value = null;
+  }
+
+  private Markup(final String value) {
+    this.values = null;
+    this.value = value;
+  }
+
+  public static Markup valueOf(final String[] values) {
+    if (values == null || values.length == 0) {
+      return null;
+    } else if (values.length == 1) {
+      return valueOf(values[0]);
+    } else {
+      final Markup markup = new Markup(values.clone());
+      for (int i = 0; i < markup.values.length; i++) {
+        markup.values[i] = markup.values[i].trim();
+      }
+      return markup;
+    }
+  }
+
+  public static Markup valueOf(final String value) {
+    if (StringUtils.isEmpty(value)) {
+      return null;
+    }
+    if (value.contains(",")) {
+      final String[] strings = StringUtils.split(value, ", \t\n");
+      return new Markup(strings);
+    } else {
+      return new Markup(value.trim());
+    }
+  }
+
+  public static Markup valueOf(final Object value) {
+    if (value == null) {
+      return null;
+    }
+    if (value instanceof Markup) {
+      return (Markup) value;
+    }
+    if (value instanceof String) {
+      return valueOf((String) value);
+    }
+    if (value instanceof String[]) {
+      return valueOf((String[]) value);
+    }
+    if (value instanceof Iterable) {
+      final List<String> list = new ArrayList<String>();
+      for (final Object object : (Iterable) value) {
+        list.add(object.toString());
+      }
+      return valueOf(list.toArray(new String[list.size()]));
+    }
+    return valueOf(value.toString());
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final Markup markup = (Markup) o;
+
+    if (value != null ? !value.equals(markup.value) : markup.value != null) {
+      return false;
+    }
+    if (!Arrays.equals(values, markup.values)) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    int result = values != null ? Arrays.hashCode(values) : 0;
+    result = 31 * result + (value != null ? value.hashCode() : 0);
+    return result;
+  }
+
+  @Override
+  public Iterator<String> iterator() {
+    if (value != null) {
+      return new SingletonIterator(value);
+    }
+    if (values != null) {
+      return new ObjectArrayIterator(values);
+    }
+    return EmptyIterator.INSTANCE;
+  }
+
+  /**
+   * Adds one markup to an other.
+   * Attention: The markup itself is not modified, you need to use the result of this operation.
+   */
+  public Markup add(final Markup markup) {
+    if (markup == null) {
+      return this;
+    }
+    if (markup == NULL) {
+      return this;
+    }
+    if (markup.value != null) {
+      return add(markup.value);
+    } else {
+      // this part is not optimized, but it will be used rarely, in the moment...
+      Markup result = this;
+      if (markup.values != null) {
+        for (final String summand : markup.values) {
+          result = result.add(summand);
+        }
+      }
+      return result;
+    }
+  }
+
+  private Markup add(final String summand) {
+    if (summand == null) {
+      return this;
+    }
+    if (values == null) {
+      if (value == null) {
+        return valueOf(summand);
+      } else {
+        if (summand.equals(value)) {
+          return this;
+        } else {
+          return valueOf(new String[]{value, summand});
+        }
+      }
+    } else {
+      if (ArrayUtils.contains(values, summand)) {
+        return this;
+      } else {
+        final String[] strings = new String[values.length + 1];
+        System.arraycopy(values, 0, strings, 0, values.length);
+        strings[values.length] = summand;
+        return valueOf(strings);
+      }
+    }
+  }
+
+  public Markup remove(final Markup markup) {
+    if (markup.value != null) {
+      return remove(markup.value);
+    } else {
+      // this part is not optimized, but it will be used rarely, in the moment...
+      Markup result = this;
+      for (final String summand : markup.values) {
+        result = result.remove(summand);
+      }
+      return result;
+    }
+  }
+
+  private Markup remove(final String summand) {
+    if (summand == null) {
+      return this;
+    }
+    if (values == null) {
+      if (value == null) {
+        return this;
+      } else {
+        if (summand.equals(value)) {
+          return NULL;
+        } else {
+          return this;
+        }
+      }
+    } else {
+      if (ArrayUtils.contains(values, summand)) {
+        final String[] strings = new String[values.length - 1];
+        int found = 0;
+        for (int i = 0; i < strings.length; i++) {
+          if (values[i].equals(summand)) {
+            found++;
+          }
+          strings[i] = values[i + found];
+        }
+        return valueOf(strings);
+      } else {
+        return this;
+      }
+    }
+  }
+
+  public boolean contains(final String markup) {
+    if (markup == null) {
+      return true;
+    }
+    if (this == NULL) {
+      return this == Markup.valueOf(markup);
+    }
+    if (value != null) {
+      return value.equals(markup);
+    }
+    for (final String value : values) {
+      if (value.equals(markup)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public boolean contains(final Markup markup) {
+    if (markup == null || markup == NULL) {
+      return true;
+    }
+    if (this == NULL) {
+      return this == markup;
+    }
+    if (markup.value != null) {
+      if (value != null) {
+        return value.equals(markup.value);
+      } else {
+        for (final String value : values) {
+          if (value.equals(markup.value)) {
+            return true;
+          }
+        }
+        return false;
+      }
+    } else {
+      if (value != null) {
+        return false;
+      } else {
+        for (final String markupString : markup.values) {
+          if (!contains(markupString)) {
+            return false;
+          }
+        }
+        return true;
+      }
+    }
+  }
+
+  @Override
+  public String toString() {
+    if (value != null) {
+      return value;
+    }
+    if (values == null) {
+      return "null";
+    }
+    return Arrays.toString(values);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/MarkupConfig.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/MarkupConfig.java
new file mode 100644
index 0000000..2136b4a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/MarkupConfig.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.io.Serializable;
+
+public class MarkupConfig implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private Set<String> markups = new HashSet<String>();
+
+  public boolean contains(final String markup) {
+    return markups.contains(markup);
+  }
+
+  public void addMarkup(final String markup) {
+    this.markups.add(markup);
+  }
+
+  public String toString() {
+    return "MarkupConfig: " + markups;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/MarkupEditor.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/MarkupEditor.java
new file mode 100644
index 0000000..165af6e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/MarkupEditor.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import java.beans.PropertyEditorSupport;
+
+/**
+ * Converter for {@link org.apache.myfaces.tobago.context.MarkupEditor}
+ */
+public class MarkupEditor extends PropertyEditorSupport {
+
+    @Override
+    public void setAsText(final String text) throws IllegalArgumentException {
+        setValue(Markup.valueOf(text));
+    }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ResourceUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ResourceUtils.java
new file mode 100644
index 0000000..a8caff4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ResourceUtils.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+public final class ResourceUtils {
+
+  /**
+   * @deprecated since Tobago 2.0.3
+   */
+  @Deprecated
+  public static final char FOLDER_SEPARATOR = '/';
+
+  /**
+   * @deprecated since Tobago 2.0.3
+   */
+  @Deprecated
+  public static final char SEPARATOR = '-';
+
+  /**
+   * @deprecated since Tobago 2.0.3
+   */
+  @Deprecated
+  public static final char DOT = '.';
+
+  /**
+   * @deprecated since Tobago 2.0.3
+   */
+  @Deprecated
+  public static final String GIF = "gif";
+  public static final String PNG = "png";
+
+  private ResourceUtils() {
+    assert false;
+  }
+
+  /**
+   * @deprecated since Tobago 2.0.3
+   */
+  @Deprecated
+  public static String createString(
+      final String folder, final String component, final String name, final String postfix, final String extension) {
+    return folder + FOLDER_SEPARATOR + component + SEPARATOR + name + SEPARATOR + postfix + DOT + extension;
+  }
+
+  /**
+   * @deprecated since Tobago 2.0.3
+   */
+  @Deprecated
+  public static String createString(
+      final String folder, final String component, final String name, final String extension) {
+    return folder + FOLDER_SEPARATOR + component + SEPARATOR + name + DOT + extension;
+  }
+
+  public static String addPostfixToFilename(final String filename, final String postfix) {
+    final int dotIndex = filename.lastIndexOf('.');
+    if (dotIndex == -1) {
+      return filename + postfix;
+    } else {
+      return filename.substring(0, dotIndex) + postfix + filename.substring(dotIndex);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Theme.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Theme.java
new file mode 100644
index 0000000..d763765
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/Theme.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.apache.myfaces.tobago.internal.config.RenderersConfig;
+
+import java.util.List;
+
+public interface Theme {
+  String getName();
+
+  List<Theme> getFallbackList();
+
+  String getDisplayName();
+
+  /**
+   * For internal use only.
+   */
+  RenderersConfig getRenderersConfig();
+
+  String[] getScriptResources(boolean production);
+
+  String[] getStyleResources(boolean production);
+
+  String getVersion();
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeImpl.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeImpl.java
new file mode 100644
index 0000000..8ac9a12
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeImpl.java
@@ -0,0 +1,303 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.apache.myfaces.tobago.internal.config.RendererConfig;
+import org.apache.myfaces.tobago.internal.config.RenderersConfig;
+import org.apache.myfaces.tobago.internal.config.RenderersConfigImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ThemeImpl implements Theme, Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(ThemeImpl.class);
+
+  private String name;
+  private String displayName;
+  private ThemeImpl fallback;
+  private String fallbackName;
+  private List<Theme> fallbackList;
+  private RenderersConfigImpl renderersConfig;
+  private ThemeResources productionResources;
+  private ThemeResources resources;
+  private String[] productionScripts;
+  private String[] productionStyles;
+  private String[] scripts;
+  private String[] styles;
+  private boolean versioned;
+  private String version;
+
+  private boolean unmodifiable = false;
+
+  public ThemeImpl() {
+    resources = new ThemeResources(false);
+    productionResources = new ThemeResources(true);
+  }
+
+  private void checkLocked() throws IllegalStateException {
+    if (unmodifiable) {
+      throw new RuntimeException("The configuration must not be changed after initialization!");
+    }
+  }
+
+  /**
+   * Lock the configuration, so it cannot be modified any more.
+   */
+  public void lock() {
+    unmodifiable = true;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    checkLocked();
+    this.name = name;
+  }
+
+  @Override
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  public void setDisplayName(final String displayName) {
+    checkLocked();
+    this.displayName = displayName;
+  }
+
+  public ThemeImpl getFallback() {
+    return fallback;
+  }
+
+  public void setFallback(final ThemeImpl fallback) {
+    checkLocked();
+    this.fallback = fallback;
+  }
+
+  public String getFallbackName() {
+    return fallbackName;
+  }
+
+  public void setFallbackName(final String fallbackName) {
+    checkLocked();
+    this.fallbackName = fallbackName;
+  }
+
+  @Override
+  public List<Theme> getFallbackList() {
+    return fallbackList;
+  }
+
+  public void resolveFallbacks() {
+    checkLocked();
+    fallbackList = new ArrayList<Theme>();
+    ThemeImpl actual = this;
+    while (actual != null) {
+      fallbackList.add(actual);
+      actual = actual.getFallback();
+    }
+    fallbackList = Collections.unmodifiableList(fallbackList);
+    if (LOG.isDebugEnabled()) {
+      for (final Theme theme : fallbackList) {
+        LOG.debug("fallbackList: {}", theme.getName());
+      }
+    }
+  }
+
+  public void resolveRendererConfig(final RenderersConfig rendererConfigFromTobagoConfig) {
+    checkLocked();
+    if (renderersConfig == null) {
+      renderersConfig = new RenderersConfigImpl();
+    }
+    if (!renderersConfig.isMerged()) {
+      final ThemeImpl fallback = getFallback();
+      if (fallback != null) {
+        fallback.resolveRendererConfig(rendererConfigFromTobagoConfig);
+        final RenderersConfigImpl fallbackRenderersConfig = fallback.getRenderersConfigImpl();
+        if (fallbackRenderersConfig != null) {
+          renderersConfig.merge(fallbackRenderersConfig, false);
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("merge markupconfig from {} for {}", fallback.getName(), getName());
+          }
+        }
+      }
+      if (rendererConfigFromTobagoConfig != null) {
+        renderersConfig.merge(rendererConfigFromTobagoConfig, true);
+      }
+      renderersConfig.setMerged(true);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("{} {}", getName(), renderersConfig);
+      }
+    }
+  }
+
+  public void resolveResources() {
+    checkLocked();
+    final ThemeImpl fallback = getFallback();
+    if (fallback != null) {
+      fallback.resolveResources();
+      addResources(fallback.getProductionResources());
+      addResources(fallback.getResources());
+    }
+  }
+
+  public void setRenderersConfig(final RenderersConfigImpl renderersConfig) {
+    checkLocked();
+    this.renderersConfig = renderersConfig;
+  }
+
+  @Override
+  public RenderersConfig getRenderersConfig() {
+    return renderersConfig;
+  }
+
+  RenderersConfigImpl getRenderersConfigImpl() {
+    return renderersConfig;
+  }
+
+  public ThemeResources getResources() {
+    return resources;
+  }
+
+  public ThemeResources getProductionResources() {
+    return productionResources;
+  }
+
+  public void addResources(final ThemeResources themeResources) {
+    checkLocked();
+
+    if (themeResources.isProduction()) {
+      productionResources.merge(themeResources);
+    } else {
+      resources.merge(themeResources);
+    }
+  }
+
+  public void init() {
+    checkLocked();
+    productionScripts = new String[productionResources.getScriptList().size()];
+    for (int i = 0; i < productionResources.getScriptList().size(); i++) {
+      productionScripts[i] = productionResources.getScriptList().get(i).getName();
+    }
+    productionStyles = new String[productionResources.getStyleList().size()];
+    for (int i = 0; i < productionResources.getStyleList().size(); i++) {
+      productionStyles[i] = productionResources.getStyleList().get(i).getName();
+    }
+
+    scripts = new String[resources.getScriptList().size()];
+    for (int i = 0; i < resources.getScriptList().size(); i++) {
+      scripts[i] = resources.getScriptList().get(i).getName();
+    }
+    styles = new String[resources.getStyleList().size()];
+    for (int i = 0; i < resources.getStyleList().size(); i++) {
+      styles[i] = resources.getStyleList().get(i).getName();
+    }
+
+  }
+
+  @Override
+  public String[] getScriptResources(final boolean production) {
+    if (production) {
+      return productionScripts;
+    } else {
+      return scripts;
+    }
+  }
+
+  @Override
+  public String[] getStyleResources(final boolean production) {
+    if (production) {
+      return productionStyles;
+    } else {
+      return styles;
+    }
+  }
+
+  public boolean isVersioned() {
+    checkLocked();
+    return versioned;
+  }
+
+  public void setVersioned(final boolean versioned) {
+    checkLocked();
+    this.versioned = versioned;
+  }
+
+  @Override
+  public String getVersion() {
+    return version;
+  }
+
+  public void setVersion(final String version) {
+    checkLocked();
+    this.version = version;
+  }
+
+  public String toString() {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("Theme:  name='");
+    builder.append(name);
+    builder.append("' fallback=");
+    if (fallback != null) {
+      builder.append("'");
+      builder.append(fallback.getName());
+      builder.append("'");
+    } else {
+      builder.append("null");
+    }
+    builder.append(", \nproductionScripts=[");
+    for (String s : productionScripts != null ? productionScripts : new String[0]) {
+      builder.append("\n");
+      builder.append(s);
+    }
+    builder.append("], \nscripts=[");
+    for (String s : scripts != null ? scripts : new String[0]) {
+      builder.append("\n");
+      builder.append(s);
+    }
+    builder.append("], \nproductionStyles=[");
+    for (String s : productionStyles != null ? productionStyles : new String[0]) {
+      builder.append("\n");
+      builder.append(s);
+    }
+    builder.append("], \nstyles=[");
+    for (String s : styles != null ? styles : new String[0]) {
+      builder.append("\n");
+      builder.append(s);
+    }
+    if (renderersConfig != null) {
+      builder.append("\n");
+      for (final RendererConfig config : renderersConfig.getRendererConfigs()) {
+        builder.append(config);
+        builder.append("\n");
+      }
+    }
+    return builder.toString();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeResource.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeResource.java
new file mode 100644
index 0000000..927ff8b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeResource.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import java.io.Serializable;
+
+/**
+ * @since 1.5.0
+ */
+public class ThemeResource implements Serializable {
+
+  private String name;
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof ThemeResource)) {
+      return false;
+    }
+
+    final ThemeResource that = (ThemeResource) o;
+
+    return !(name != null ? !name.equals(that.name) : that.name != null);
+
+  }
+
+  @Override
+  public int hashCode() {
+    return name != null ? name.hashCode() : 0;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeResources.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeResources.java
new file mode 100644
index 0000000..b680494
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeResources.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages the script and style files for production and development stage.
+ *
+ * @since 1.5.0
+ */
+public final class ThemeResources implements Serializable {
+
+  private final boolean production;
+  private final List<ThemeScript> scriptList = new ArrayList<ThemeScript>();
+  private final List<ThemeScript> scriptExcludes = new ArrayList<ThemeScript>();
+  private final List<ThemeStyle> styleList = new ArrayList<ThemeStyle>();
+  private final List<ThemeStyle> styleExcludes = new ArrayList<ThemeStyle>();
+
+  public ThemeResources(boolean production) {
+    this.production = production;
+  }
+
+  public void merge(final ThemeResources toAddResources) {
+    if (this == toAddResources) {
+      return;
+    }
+    for (int i = toAddResources.scriptList.size() - 1; i >= 0; i--) {
+      final ThemeScript script = toAddResources.scriptList.get(i);
+      scriptList.remove(script);
+      if (!scriptExcludes.contains(script)) {
+        scriptList.add(0, script);
+      }
+    }
+    for (int i = toAddResources.styleList.size() - 1; i >= 0; i--) {
+      final ThemeStyle style = toAddResources.styleList.get(i);
+      styleList.remove(style);
+      if (!styleExcludes.contains(style)) {
+        styleList.add(0, style);
+      }
+    }
+  }
+
+  public boolean isProduction() {
+    return production;
+  }
+
+  public boolean addScript(final ThemeScript script, boolean exclude) {
+    return exclude ? scriptExcludes.add(script) : scriptList.add(script);
+  }
+
+  public boolean addStyle(final ThemeStyle style, boolean exclude) {
+    return exclude ? styleExcludes.add(style) : styleList.add(style);
+  }
+
+  public List<ThemeScript> getScriptList() {
+    return scriptList;
+  }
+
+  public List<ThemeStyle> getStyleList() {
+    return styleList;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeScript.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeScript.java
new file mode 100644
index 0000000..17fc51b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeScript.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+/**
+ * @since 1.5.0
+ */
+public final class ThemeScript extends ThemeResource {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeStyle.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeStyle.java
new file mode 100644
index 0000000..2bc6c20
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/ThemeStyle.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+/**
+ * @since 1.5.0
+ */
+public final class ThemeStyle extends ThemeResource {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoBundle.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoBundle.java
new file mode 100644
index 0000000..28c82a4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoBundle.java
@@ -0,0 +1,138 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.ResourceBundle;
+import java.util.Set;
+
+/**
+ * This class works like the Java resource bundle mechanism for a named resource bundle
+ * and adds the functionality of the tobago themes and also supports XML properties files.
+ * This class should be extended and used in the faces-config.xml.
+ *
+ * @since 1.5.0
+ */
+public class TobagoBundle extends ResourceBundle {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoBundle.class);
+
+  private String bundleName;
+  private ResourceBundle bundle;
+
+  public TobagoBundle(final String bundleName) {
+    this.bundleName = bundleName;
+    this.bundle = ResourceBundle.getBundle(bundleName, new XmlTobagoBundle.XMLResourceBundleControl());
+  }
+
+  @Override
+  protected Object handleGetObject(final String key) {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Searching for '{}' in bundle '{}'", key, bundleName);
+    }
+    return bundle.getObject(key);
+  }
+
+  @Override
+  public Enumeration<String> getKeys() {
+    return Collections.enumeration(Collections.<String>emptyList());
+  }
+
+  public String getBundleName() {
+    return bundleName;
+  }
+
+  public static class XmlTobagoBundle extends ResourceBundle {
+
+    private static final String XML = "xml";
+
+    private Properties props;
+
+    private XmlTobagoBundle(InputStream stream) throws IOException {
+      props = new Properties();
+      props.loadFromXML(stream);
+    }
+
+    protected Object handleGetObject(String key) {
+      return props.getProperty(key);
+    }
+
+    public Enumeration<String> getKeys() {
+      Set<String> handleKeys = props.stringPropertyNames();
+      return Collections.enumeration(handleKeys);
+    }
+
+    public static class XMLResourceBundleControl extends Control {
+
+      public List<String> getFormats(String baseName) {
+        return Collections.singletonList(XML);
+      }
+
+      public ResourceBundle newBundle(
+          String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
+          throws IllegalAccessException, InstantiationException,
+          IOException {
+
+        if ((baseName == null) || (locale == null) || (format == null) || (loader == null)) {
+          throw new NullPointerException();
+        }
+        ResourceBundle bundle = null;
+        if (!format.equals(XML)) {
+          return null;
+        }
+
+        String bundleName = toBundleName(baseName, locale);
+        String resourceName = toResourceName(bundleName, format);
+        URL url = loader.getResource(resourceName);
+        if (url == null) {
+          return null;
+        }
+        URLConnection connection = url.openConnection();
+        if (connection == null) {
+          return null;
+        }
+        if (reload) {
+          connection.setUseCaches(false);
+        }
+        InputStream stream = connection.getInputStream();
+        if (stream == null) {
+          return null;
+        }
+        BufferedInputStream bis = new BufferedInputStream(stream);
+        bundle = new XmlTobagoBundle(bis);
+        bis.close();
+
+        return bundle;
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoContext.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoContext.java
new file mode 100644
index 0000000..a018cb1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoContext.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.internal.util.CookieUtils;
+import org.apache.myfaces.tobago.util.VariableResolverUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.bean.ManagedBean;
+import javax.faces.bean.RequestScoped;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.HttpServletRequest;
+
+@ManagedBean
+@RequestScoped
+public class TobagoContext {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoContext.class);
+
+  public static final String BEAN_NAME = "tobagoContext";
+
+  private static final TobagoResourceBundle RESOURCE_BUNDLE = new TobagoResourceBundle();
+  private static final TobagoMessageBundle MESSAGE_BUNDLE = new TobagoMessageBundle();
+
+  private Theme theme;
+  private UserAgent userAgent;
+
+  public TobagoResourceBundle getResourceBundle() {
+    return RESOURCE_BUNDLE;
+  }
+
+  public TobagoMessageBundle getMessageBundle() {
+    return MESSAGE_BUNDLE;
+  }
+
+  public TobagoConfig getTobagoConfig() {
+    return TobagoConfig.getInstance(FacesContext.getCurrentInstance());
+  }
+
+  public Theme getTheme() {
+
+    if (theme == null) {
+      final FacesContext facesContext = FacesContext.getCurrentInstance();
+      final ExternalContext externalContext = facesContext.getExternalContext();
+
+      final String themeName;
+      Object request = externalContext.getRequest();
+      if (request instanceof HttpServletRequest) {
+        themeName = CookieUtils.getThemeNameFromCookie((HttpServletRequest) request);
+      } else {
+        themeName = null;
+      }
+
+      theme = getTobagoConfig().getTheme(themeName);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("theme='{}'", theme.getName());
+      }
+    }
+
+    return theme;
+  }
+
+  public void setTheme(Theme theme) {
+    this.theme = theme;
+  }
+
+  public UserAgent getUserAgent() {
+
+    if (userAgent == null) {
+      final FacesContext facesContext = FacesContext.getCurrentInstance();
+      final ExternalContext externalContext = facesContext.getExternalContext();
+
+      final String requestUserAgent = externalContext.getRequestHeaderMap().get("User-Agent");
+      userAgent = UserAgent.getInstance(requestUserAgent);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("userAgent='" + userAgent + "' from header " + "'User-Agent: " + requestUserAgent + "'");
+      }
+    }
+
+    return userAgent;
+  }
+
+  public void setUserAgent(UserAgent userAgent) {
+    this.userAgent = userAgent;
+  }
+
+  public static TobagoContext getInstance(FacesContext facesContext) {
+    return (TobagoContext) VariableResolverUtils.resolveVariable(facesContext, BEAN_NAME);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoMessageBundle.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoMessageBundle.java
new file mode 100644
index 0000000..420273b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoMessageBundle.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * This ResourceBundle encapsulate the messages (e. g. validation) of Tobago components.
+ * This class works like the Java resource bundle mechanism for the resource bundle {@value BUNDLE_NAME}.
+ * Supports XML properties files.
+ *
+ * @since 1.5.0
+ */
+public class TobagoMessageBundle extends TobagoBundle {
+
+  public static final String VAR = "tobagoMessageBundle";
+  public static final String BUNDLE_NAME = "org.apache.myfaces.tobago.context.TobagoMessage";
+
+  public TobagoMessageBundle() {
+    super(BUNDLE_NAME);
+  }
+
+
+  public static String getString(final FacesContext facesContext, final String key) {
+    return facesContext.getApplication().getResourceBundle(facesContext, VAR).getString(key);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoResourceBundle.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoResourceBundle.java
new file mode 100644
index 0000000..4fa73fc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TobagoResourceBundle.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * This ResourceBundle encapsulate string resources of Tobago components.
+ * This class works like the Java resource bundle mechanism for the resource bundle {@value BUNDLE_NAME}.
+ * Supports XML properties files.
+ */
+public class TobagoResourceBundle extends TobagoBundle {
+
+  public static final String VAR = "tobagoResourceBundle";
+  public static final String BUNDLE_NAME = "org.apache.myfaces.tobago.context.TobagoResource";
+
+  public TobagoResourceBundle() {
+    super(BUNDLE_NAME);
+  }
+
+  public static String getString(final FacesContext facesContext, final String key) {
+    return facesContext.getApplication().getResourceBundle(facesContext, VAR).getString(key);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TransientStateHolder.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TransientStateHolder.java
new file mode 100644
index 0000000..25d3d7c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/TransientStateHolder.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import java.io.Serializable;
+
+public class TransientStateHolder implements StateHolder, Serializable {
+
+  private static final long serialVersionUID = -5260593843885016768L;
+
+  private transient Object object;
+
+  public TransientStateHolder() {
+  }
+
+  public TransientStateHolder(final Object object) {
+    this.object = object;
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    // do nothing
+    return null;
+  }
+
+  public void put(final Object object) {
+    this.object = object;
+  }
+
+  public boolean isEmpty() {
+    return object == null;
+  }
+
+  public Object get() {
+    return object;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    // do nothing
+  }
+
+  @Override
+  public boolean isTransient() {
+    return true;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    // do nothing
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java
new file mode 100644
index 0000000..ebd64c8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/context/UserAgent.java
@@ -0,0 +1,390 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.apache.myfaces.tobago.internal.util.Deprecation;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public final class UserAgent implements Serializable {
+
+  private static final long serialVersionUID = 2L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(UserAgent.class);
+
+  public static final String DEFAULT_NAME = "standard";
+
+  public static final UserAgent DEFAULT = new UserAgent(null, null);
+
+  public static final UserAgent MSIE = new UserAgent("msie", null);
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MSIE_5_0 = new UserAgent("msie", "5_0");
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MSIE_5_5 = new UserAgent("msie", "5_5");
+
+  public static final UserAgent MSIE_6_0 = new UserAgent(
+      "msie", "6_0", EnumSet.noneOf(Capability.class), CspHeader.NOT_SUPPORTED, CsproHeader.NOT_SUPPORTED);
+
+  public static final UserAgent MSIE_7_0 = new UserAgent(
+      "msie", "7_0", EnumSet.noneOf(Capability.class), CspHeader.NOT_SUPPORTED, CsproHeader.NOT_SUPPORTED);
+
+  public static final UserAgent MSIE_7_0_COMPAT = new UserAgent(
+      "msie", "7_0", EnumSet.of(Capability.IE_COMPATIBILITY_MODE), CspHeader.NOT_SUPPORTED, CsproHeader.NOT_SUPPORTED);
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5. Misspelled. Use {@link #MSIE_7_0}
+   */
+  @Deprecated
+  public static final UserAgent MSIE_7_O = MSIE_7_0;
+
+  public static final UserAgent MSIE_8_0 = new UserAgent(
+      "msie", "8_0", EnumSet.of(Capability.CONTENT_TYPE_XHTML), CspHeader.NOT_SUPPORTED, CsproHeader.NOT_SUPPORTED);
+
+  public static final UserAgent MSIE_9_0 = new UserAgent(
+      "msie", "9_0", EnumSet.of(Capability.CONTENT_TYPE_XHTML), CspHeader.NOT_SUPPORTED, CsproHeader.NOT_SUPPORTED);
+
+  // CSP is not fully supported, only sandboxing
+  public static final UserAgent MSIE_10_0 = new UserAgent(
+      "msie", "10_0", EnumSet.of(Capability.CONTENT_TYPE_XHTML), CspHeader.X, CsproHeader.X);
+
+  // CSP is not fully supported, only sandboxing
+  public static final UserAgent MSIE_11_0 = new UserAgent(
+      "msie", "11_0", EnumSet.of(Capability.CONTENT_TYPE_XHTML), CspHeader.X, CsproHeader.X);
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MSIE_5_0_MAC = new UserAgent("msie", "5_0_mac");
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MSIE_6_0_MAC = new UserAgent("msie", "6_0_mac");
+
+
+  /**
+   * e. g. Opera 10
+   */
+  public static final UserAgent PRESTO = new UserAgent("presto", null, EnumSet.of(Capability.CONTENT_TYPE_XHTML));
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5. Please use {@link #PRESTO}.
+   */
+  public static final UserAgent OPERA = new UserAgent("opera", null);
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5. Please use {@link #PRESTO}.
+   */
+  @Deprecated
+  public static final UserAgent OPERA_5_0 = new UserAgent("opera", "5_0");
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5. Please use {@link #PRESTO}.
+   */
+  @Deprecated
+  public static final UserAgent OPERA_6_0 = new UserAgent("opera", "6_0");
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5. Please use {@link #PRESTO}.
+   */
+  @Deprecated
+  public static final UserAgent OPERA_7_11 = new UserAgent("opera", "7_11");
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MOZILLA = new UserAgent("mozilla", null);
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MOZILLA_4_7 = new UserAgent("mozilla", "4_7");
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MOZILLA_5_0 = new UserAgent("mozilla", "5_0");
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static final UserAgent MOZILLA_5_0_R1_6 = new UserAgent("mozilla", "5_0_r1_6");
+
+  /**
+   * e. g. Firefox
+   */
+  public static final UserAgent GECKO = new UserAgent("gecko", null, EnumSet.of(Capability.CONTENT_TYPE_XHTML));
+
+  /**
+   * e. g. Firefox 2.0
+   */
+  public static final UserAgent GECKO_1_8 = new UserAgent("gecko", "1_8", EnumSet.of(Capability.CONTENT_TYPE_XHTML),
+      CspHeader.NOT_SUPPORTED, CsproHeader.NOT_SUPPORTED);
+
+  /**
+   * e. g. Firefox 3.0, 3.5, 3.6
+   */
+  public static final UserAgent GECKO_1_9 = new UserAgent("gecko", "1_9", EnumSet.of(Capability.CONTENT_TYPE_XHTML),
+      CspHeader.NOT_SUPPORTED, CsproHeader.NOT_SUPPORTED);
+
+  /**
+   * e. g. Firefox 4 to 22
+   */
+  public static final UserAgent GECKO_2_0
+      = new UserAgent("gecko", null,
+      EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML), CspHeader.X, CsproHeader.X);
+
+  /**
+   * e. g. Firefox 23 or higher
+   */
+  public static final UserAgent GECKO_23_0
+      = new UserAgent("gecko", null,
+      EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML), CspHeader.STANDARD, CsproHeader.STANDARD);
+
+  /**
+   * e. g. Safari 4, Safari 5, Chrome
+   */
+  public static final UserAgent WEBKIT
+      = new UserAgent("webkit", null,
+      EnumSet.of(Capability.PLACEHOLDER, Capability.CONTENT_TYPE_XHTML), CspHeader.WEBKIT, CsproHeader.WEBKIT);
+
+  private final String name;
+
+  /**
+   * @deprecated Version shouldn't be used in the future. Use capability instead, even better
+   * use same code on the server when possible and use capability via JavaScript.
+   */
+  @Deprecated
+  private final String version;
+
+  private final EnumSet<Capability> capabilities;
+
+  private final CspHeader cspHeader;
+
+  private final CsproHeader csproHeader;
+
+  private UserAgent(final String name, final String version) {
+    this(name, version, EnumSet.of(Capability.CONTENT_TYPE_XHTML));
+  }
+
+  private UserAgent(final String name, final String version, final EnumSet<Capability> capabilities) {
+    this(name, version, capabilities, CspHeader.STANDARD, CsproHeader.STANDARD);
+  }
+
+  private UserAgent(
+      final String name, final String version, final EnumSet<Capability> capabilities, final CspHeader cspHeader,
+      final CsproHeader csproHeader) {
+    this.name = name;
+    this.version = version;
+    this.capabilities = capabilities;
+    this.cspHeader = cspHeader;
+    this.csproHeader = csproHeader;
+  }
+
+  public boolean hasCapability(final Capability capability) {
+    return capabilities.contains(capability);
+  }
+
+  public boolean isMsie() {
+    return MSIE.name.equals(name);
+  }
+
+  /**
+   * @deprecated no longer supported, since Tobago 3.0
+   */
+  @Deprecated
+  public boolean isMsie6() {
+    return MSIE_6_0.name.equals(name) && MSIE_6_0.version.equals(version);
+  }
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public boolean isMozilla() {
+    return MOZILLA.name.equals(name);
+  }
+
+  public List<String> getFallbackList() {
+    return getFallbackList(false);
+  }
+
+  private List<String> getFallbackList(final boolean reverseOrder) {
+    final List<String> list = new ArrayList<String>(3);
+    if (version != null) {
+      list.add(name + '_' + version);
+    }
+    if (name != null) {
+      list.add(name);
+    }
+    list.add(DEFAULT_NAME);
+    if (reverseOrder) {
+      Collections.reverse(list);
+    }
+    return list;
+  }
+
+  /**
+   * @return The HTTP header names for Content-Security-Policy.
+   */
+  public String[] getCspHeaders() {
+    return cspHeader.getNames();
+  }
+
+  /**
+   * @return The HTTP header name for Content-Security-Policy-Report-Only.
+   */
+  public String[] getCspReportOnlyHeaders() {
+    return csproHeader.getNames();
+  }
+
+  public static UserAgent getInstance(final String header) {
+    if (header == null) {
+      return DEFAULT;
+    }
+
+    if (header.contains("MSIE") || header.contains("Trident")) {
+      if (header.contains("MSIE 6.0")) {
+        return MSIE_6_0;
+      } else if (header.contains("MSIE 7.0")) {
+        if (header.contains("Trident")) {
+          return MSIE_7_0_COMPAT;
+        } else {
+          return MSIE_7_0;
+        }
+      } else if (header.contains("MSIE 8.0")) {
+        return MSIE_8_0;
+      } else if (header.contains("MSIE 9.0")) {
+        return MSIE_9_0;
+      } else if (header.contains("MSIE 10.0")) {
+        return MSIE_10_0;
+      } else if (header.contains("rv:11")) {
+        return MSIE_11_0;
+      } else {
+        return MSIE;
+      }
+    } else if (header.contains("AppleWebKit")) {
+      return WEBKIT;
+    } else if (header.contains("Gecko")) {
+      if (header.contains("rv:1.8")) {
+        return GECKO_1_8;
+      } else if (header.contains("rv:1.9")) {
+        return GECKO_1_9;
+      } else {
+        final int index = header.indexOf("rv:");
+        final StringTokenizer tokenizer = new StringTokenizer(header.substring(index + 3), " .");
+        final String versionString = tokenizer.nextToken();
+        try {
+          final int version = Integer.parseInt(versionString);
+          if (version >= 23) {
+            return GECKO_23_0;
+          } else if (version >= 2) {
+            return GECKO_2_0;
+          }
+        } catch (final NumberFormatException e) {
+          if (LOG.isDebugEnabled()) {
+            LOG.debug(header, e);
+          }
+        }
+        return GECKO;
+      }
+    } else if (header.contains("Presto")) {
+      return PRESTO;
+    }
+
+    return DEFAULT;
+  }
+
+  /**
+   * @deprecated no longer supported, since Tobago 1.5
+   */
+  @Deprecated
+  public static UserAgent getInstanceForId(final String id) {
+    Deprecation.LOG.error("Getting the user agent from its id is no longer supported! id='" + id + "'");
+    return DEFAULT;
+  }
+
+  /**
+   * @deprecated don't use toString() functionality, but for logging!
+   */
+  @Deprecated
+  public String toString() {
+    return version != null
+        ? name + '_' + version
+        : name;
+  }
+
+  private static enum CspHeader {
+
+    NOT_SUPPORTED(new String[] {}),
+    X(new String[] {"Content-Security-Policy", "X-Content-Security-Policy"}),
+    WEBKIT(new String[] {"Content-Security-Policy", "X-WebKit-CSP"}),
+    STANDARD(new String[] {"Content-Security-Policy"});
+
+    private String[] names;
+
+    private CspHeader(final String[] names) {
+      this.names = names;
+    }
+
+    public String[] getNames() {
+      return names;
+    }
+  }
+
+  private static enum CsproHeader {
+
+    NOT_SUPPORTED(new String[] {}),
+    X(new String[] {"Content-Security-Policy-Report-Only", "X-Content-Security-Policy-Report-Only"}),
+    WEBKIT(new String[] {"Content-Security-Policy-Report-Only", "X-WebKit-CSP-Report-Only"}),
+    STANDARD(new String[] {"Content-Security-Policy-Report-Only"});
+
+    private String[] names;
+
+    private CsproHeader(final String[] names) {
+      this.names = names;
+    }
+
+    public String[] getNames() {
+      return names;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/CurrencyConverter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/CurrencyConverter.java
new file mode 100644
index 0000000..a4667a0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/CurrencyConverter.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.convert;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import java.util.Currency;
+
+/**
+ * JSF converter for the java.util.Currency class.
+ */
+@org.apache.myfaces.tobago.apt.annotation.Converter(forClass = "java.util.Currency")
+public class CurrencyConverter implements Converter {
+
+  @Override
+  public Object getAsObject(final FacesContext facesContext, final UIComponent component, final String string)
+      throws ConverterException {
+    if (StringUtils.isBlank(string)) {
+      return null;
+    } else {
+      return Currency.getInstance(string);
+    }
+  }
+
+  @Override
+  public String getAsString(final FacesContext facesContext, final UIComponent component, final Object object)
+      throws ConverterException {
+    if (object == null) {
+      return null;
+    }
+    try {
+      return ((Currency) object).getCurrencyCode();
+    } catch (final ClassCastException e) {
+      throw new ConverterException("object='" + object + "'", e);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/DurationConverter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/DurationConverter.java
new file mode 100644
index 0000000..7251525
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/DurationConverter.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.convert;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import java.text.DecimalFormat;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+@org.apache.myfaces.tobago.apt.annotation.Converter(id = DurationConverter.CONVERTER_ID)
+public class DurationConverter implements Converter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DurationConverter.class);
+
+  public static final String CONVERTER_ID = "org.apache.myfaces.tobago.Duration";
+
+  private static enum Unit {
+    nano, milli, second, minute, hour, day, year
+  }
+
+  @Override
+  public String getAsString(
+      final FacesContext facesContext, final UIComponent component, final Object object)
+      throws ConverterException {
+    if (object == null || object instanceof String) {
+      return (String) object;
+    }
+    double aDouble = ((Number) object).doubleValue();
+    boolean negative = false;
+    if (aDouble < 0) {
+      negative = true;
+      aDouble = -aDouble;
+    }
+    final double factor = getUnitFactor(component);
+    aDouble = aDouble * factor;
+
+    final NumberFormat format = new DecimalFormat("00");
+    long value = Double.valueOf(aDouble).longValue();
+    final int seconds = (int) (value % 60);
+    value = value / 60;
+    final int minutes = (int) (value % 60);
+    value = value / 60;
+    final String string;
+    if (value > 0) {
+      string = (negative ? "-" : "") + value + ":"
+          + format.format(minutes) + ":"
+          + format.format(seconds);
+    } else {
+      string = (negative ? "-" : "") + minutes + ":"
+          + format.format(seconds);
+    }
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("string = '{}'", string);
+    }
+    return string;
+  }
+
+  @Override
+  public Object getAsObject(
+      final FacesContext facesContext, final UIComponent component, final String string)
+      throws ConverterException {
+    final boolean negative = string.indexOf('-') > -1;
+    final StringTokenizer tokenizer = new StringTokenizer(string, " :-");
+    final List<String> elements = new ArrayList<String>();
+    while (tokenizer.hasMoreTokens()) {
+      elements.add(tokenizer.nextToken());
+    }
+    int hours = 0;
+    final int minutes;
+    final int seconds;
+    switch (elements.size()) {
+      case 3:
+        hours = Integer.parseInt(elements.get(0));
+        minutes = Integer.parseInt(elements.get(1));
+        seconds = Integer.parseInt(elements.get(2));
+        break;
+      case 2:
+        minutes = Integer.parseInt(elements.get(0));
+        seconds = Integer.parseInt(elements.get(1));
+        break;
+      default:
+        throw new ConverterException("Cannot parse string='" + string + "'");
+    }
+    final double factor = getUnitFactor(component);
+    final long value = (long) (((hours * 60L + minutes) * 60L + seconds) / factor);
+    if (negative) {
+      return -value;
+    } else {
+      return value;
+    }
+  }
+
+  private static double getUnitFactor(final UIComponent component) {
+    final String unitString = ComponentUtils.getStringAttribute(component, Attributes.unit);
+    Unit unit;
+    try {
+      unit = Unit.valueOf(unitString);
+    } catch (Exception e) {
+      LOG.warn("Unsupported unit: '{}'", unitString);
+      unit = Unit.milli;
+    }
+    switch (unit) {
+      case nano:
+        return 0.000000001;
+      default:
+      case milli:
+        return 0.001;
+      case second:
+        return 1.0;
+      case minute:
+        return 60.0;
+      case hour:
+        return 3600.0;
+      case day:
+        return 86400.0;
+      case year:
+        return 31556736.0;
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/LocaleConverter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/LocaleConverter.java
new file mode 100644
index 0000000..4c094b8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/LocaleConverter.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.convert;
+
+import org.apache.myfaces.tobago.util.LocaleUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import java.util.Locale;
+
+@org.apache.myfaces.tobago.apt.annotation.Converter(forClass = "java.util.Locale")
+public class LocaleConverter implements Converter {
+
+
+  @Override
+  public Object getAsObject(
+      final FacesContext facesContext, final UIComponent component, final String value) {
+    final Locale locale = LocaleUtils.createLocale(value);
+    if (locale == null) {
+      throw new ConverterException("Can't parse " + value + " to a locale.");
+    }
+    return locale;
+  }
+
+  @Override
+  public String getAsString(
+      final FacesContext facesContext, final UIComponent component, final Object value) {
+    return value.toString();
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/MeasureConverter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/MeasureConverter.java
new file mode 100644
index 0000000..94a417e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/MeasureConverter.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.convert;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.layout.Measure;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+
+/**
+ * JSF converter for the org.apache.myfaces.tobago.layout.Measure class.
+ */
+@org.apache.myfaces.tobago.apt.annotation.Converter(forClass = "org.apache.myfaces.tobago.layout.Measure")
+public class MeasureConverter implements Converter {
+
+  @Override
+  public Object getAsObject(final FacesContext facesContext, final UIComponent component, final String string)
+      throws ConverterException {
+    if (StringUtils.isBlank(string)) {
+      return null;
+    } else {
+      return Measure.valueOf(string);
+    }
+  }
+
+  @Override
+  public String getAsString(final FacesContext facesContext, final UIComponent component, final Object object)
+      throws ConverterException {
+    if (object == null) {
+      return null;
+    }
+    try {
+      return ((Measure) object).serialize();
+    } catch (final ClassCastException e) {
+      throw new ConverterException("object='" + object + "'", e);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/ThemeConverter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/ThemeConverter.java
new file mode 100644
index 0000000..d5f4c7a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/convert/ThemeConverter.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.convert;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Theme;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+
+@org.apache.myfaces.tobago.apt.annotation.Converter(forClass = "org.apache.myfaces.tobago.context.Theme")
+public class ThemeConverter implements Converter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ThemeConverter.class);
+
+  public static final String CONVERTER_ID = "org.apache.myfaces.tobago.Theme";
+
+  @Override
+  public String getAsString(
+      final FacesContext facesContext, final UIComponent component, final Object object)
+      throws ConverterException {
+    try {
+      return ((Theme) object).getName();
+    } catch (final ClassCastException e) {
+      throw new ConverterException("object='" + object + "'", e);
+    }
+  }
+
+  @Override
+  public Object getAsObject(
+      final FacesContext facesContext, final UIComponent component, final String string)
+      throws ConverterException {
+    try {
+      return TobagoConfig.getInstance(facesContext).getTheme(string);
+    } catch (final Exception e) {
+      LOG.error("string='" + string + "'", e);
+      throw new ConverterException("string='" + string + "'", e);
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/el/ConstantMethodExpression.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/el/ConstantMethodExpression.java
new file mode 100644
index 0000000..c0b28ba
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/el/ConstantMethodExpression.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.el;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.MethodExpression;
+import javax.el.MethodInfo;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+
+public class ConstantMethodExpression extends MethodExpression implements StateHolder {
+
+  private String outcome;
+
+  private boolean transientFlag;
+
+  public ConstantMethodExpression() {
+  }
+
+  public ConstantMethodExpression(String outcome) {
+    this.outcome = outcome;
+  }
+
+  @Override
+  public MethodInfo getMethodInfo(ELContext context)
+      throws NullPointerException, ELException {
+    return null;
+  }
+
+  @Override
+  public Object invoke(ELContext context, Object[] params)
+      throws NullPointerException, ELException {
+    return outcome;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    ConstantMethodExpression that = (ConstantMethodExpression) o;
+
+    return !(outcome != null ? !outcome.equals(that.outcome) : that.outcome != null);
+
+  }
+
+  @Override
+  public int hashCode() {
+    return outcome.hashCode();
+  }
+
+  @Override
+  public String getExpressionString() {
+    return outcome;
+  }
+
+  @Override
+  public boolean isLiteralText() {
+    return true;
+  }
+
+  @Override
+  public Object saveState(FacesContext context) {
+    return outcome;
+  }
+
+  @Override
+  public void restoreState(FacesContext context, Object state) {
+    this.outcome = (String) state;
+  }
+
+  @Override
+  public void setTransient(final boolean transientFlag) {
+    this.transientFlag = transientFlag;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return transientFlag;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/el/UserWrapper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/el/UserWrapper.java
new file mode 100644
index 0000000..eba0ae3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/el/UserWrapper.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.el;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import java.security.Principal;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+public class UserWrapper {
+
+  private static final Logger LOG = LoggerFactory.getLogger(UserWrapper.class);
+
+  private Map roles;
+
+  public UserWrapper() {
+    roles = new RolesMap();
+  }
+
+  public Principal getPrincipal() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final Principal principal = facesContext.getExternalContext().getUserPrincipal();
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("getPrincipal(): {}", principal);
+    }
+    return principal;
+  }
+
+  public Map getRoles() {
+    return roles;
+  }
+
+  private static class RolesMap implements Map {
+
+    @Override
+    public Object get(final Object key) {
+      final String role = (String) key;
+      final FacesContext facesContext = FacesContext.getCurrentInstance();
+      final boolean inRole = facesContext.getExternalContext().isUserInRole(role);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("is in role '{}': {}", key, inRole);
+      }
+      return Boolean.valueOf(inRole);
+    }
+
+    @Override
+    public int size() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void clear() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean isEmpty() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean containsKey(final Object key) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public boolean containsValue(final Object value) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Collection values() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putAll(final Map t) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set entrySet() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set keySet() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object remove(final Object key) {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object put(final Object key, final Object value) {
+      throw new UnsupportedOperationException();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/AbstractResetInputActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/AbstractResetInputActionListener.java
new file mode 100644
index 0000000..96c5eca
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/AbstractResetInputActionListener.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.event.ActionListener;
+import java.util.Iterator;
+
+public abstract class AbstractResetInputActionListener implements ActionListener {
+
+  protected void resetChildren(final UIComponent component) {
+    final Iterator it = component.getFacetsAndChildren();
+    while (it.hasNext()) {
+      final UIComponent child = (UIComponent) it.next();
+      if (child instanceof EditableValueHolder) {
+        reset((EditableValueHolder) child);
+      }
+      resetChildren(child);
+    }
+  }
+
+  public static void reset(final EditableValueHolder editableValueHolder) {
+    editableValueHolder.setValue(null);
+    editableValueHolder.setSubmittedValue(null);
+    editableValueHolder.setLocalValueSet(false);
+    editableValueHolder.setValid(true);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/CollapsibleActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/CollapsibleActionListener.java
new file mode 100644
index 0000000..7005172
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/CollapsibleActionListener.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUICollapsiblePanel;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.ActionListener;
+
+public class CollapsibleActionListener implements ActionListener, StateHolder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CollapsibleActionListener.class);
+
+  private String forId;
+
+  private boolean transientFlag;
+
+  public CollapsibleActionListener() {
+    // for state holder
+  }
+
+  public CollapsibleActionListener(final String forId) {
+    this.forId = forId;
+  }
+
+  @Override
+  public void processAction(final ActionEvent actionEvent) throws AbortProcessingException {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final UIViewRoot viewRoot = facesContext.getViewRoot();
+    if (viewRoot != null) {
+      final String forClientId = ComponentUtils.evaluateClientId(facesContext, actionEvent.getComponent(), forId);
+
+      final UIComponent component = viewRoot.findComponent(forClientId);
+      if (component instanceof AbstractUICollapsiblePanel) {
+        ((AbstractUICollapsiblePanel) component).processState();
+      } else {
+        LOG.error("Wrong component class for id: '{}'. Type is {} but expected type is {}",
+            forClientId, component.getClass().getName(), AbstractUICollapsiblePanel.class.getName());
+      }
+    }
+  }
+
+  @Override
+  public Object saveState(FacesContext context) {
+    return forId;
+  }
+
+  @Override
+  public void restoreState(FacesContext context, Object state) {
+    this.forId = (String) state;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return transientFlag;
+  }
+
+  @Override
+  public void setTransient(boolean transientFlag) {
+    this.transientFlag = transientFlag;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/FacesEventWrapper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/FacesEventWrapper.java
new file mode 100644
index 0000000..fba4580
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/FacesEventWrapper.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+import javax.faces.event.PhaseId;
+
+public class FacesEventWrapper extends FacesEvent {
+
+  private static final long serialVersionUID = 1L;
+
+  private FacesEvent wrappedFacesEvent;
+
+  public FacesEventWrapper(final FacesEvent facesEvent, final UIComponent redirectComponent) {
+    super(redirectComponent);
+    wrappedFacesEvent = facesEvent;
+  }
+
+  @Override
+  public PhaseId getPhaseId() {
+    return wrappedFacesEvent.getPhaseId();
+  }
+
+  @Override
+  public void setPhaseId(final PhaseId phaseId) {
+    wrappedFacesEvent.setPhaseId(phaseId);
+  }
+
+  @Override
+  public void queue() {
+    wrappedFacesEvent.queue();
+  }
+
+  @Override
+  public String toString() {
+    return wrappedFacesEvent.toString();
+  }
+
+  @Override
+  public boolean isAppropriateListener(
+      final FacesListener faceslistener) {
+    return wrappedFacesEvent.isAppropriateListener(faceslistener);
+  }
+
+  @Override
+  public void processListener(final FacesListener faceslistener) {
+    wrappedFacesEvent.processListener(faceslistener);
+  }
+
+  public FacesEvent getWrappedFacesEvent() {
+    return wrappedFacesEvent;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionStateChangeListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionStateChangeListener.java
new file mode 100644
index 0000000..8825cad
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionStateChangeListener.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.apache.myfaces.tobago.util.FacesELUtils;
+
+import javax.el.MethodExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+
+public class MethodExpressionStateChangeListener implements SheetStateChangeListener, StateHolder {
+
+  private MethodExpression methodExpression;
+
+  private boolean isTransient = false;
+
+  public MethodExpressionStateChangeListener() {
+  }
+
+  public MethodExpressionStateChangeListener(final MethodExpression methodExpression) {
+    this.methodExpression = methodExpression;
+  }
+
+  @Override
+  public void processSheetStateChange(final SheetStateChangeEvent actionEvent) throws AbortProcessingException {
+    FacesELUtils.invokeMethodExpression(FacesContext.getCurrentInstance(), methodExpression, actionEvent);
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    methodExpression = (MethodExpression) state;
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    return methodExpression;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    isTransient = newTransientValue;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return isTransient;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTabChangeListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTabChangeListener.java
new file mode 100644
index 0000000..e999c12
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTabChangeListener.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.apache.myfaces.tobago.util.FacesELUtils;
+
+import javax.el.MethodExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+
+public class MethodExpressionTabChangeListener implements TabChangeListener, StateHolder {
+
+  private MethodExpression methodExpression;
+
+  private boolean isTransient = false;
+
+  public MethodExpressionTabChangeListener() {
+  }
+
+  public MethodExpressionTabChangeListener(final MethodExpression methodExpression) {
+    this.methodExpression = methodExpression;
+  }
+
+  @Override
+  public void processTabChange(final TabChangeEvent actionEvent) throws AbortProcessingException {
+     FacesELUtils.invokeMethodExpression(FacesContext.getCurrentInstance(), methodExpression, actionEvent);
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    methodExpression = (MethodExpression) state;
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    return methodExpression;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    isTransient = newTransientValue;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return isTransient;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTreeExpansionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTreeExpansionListener.java
new file mode 100644
index 0000000..e9aa9ce
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTreeExpansionListener.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.apache.myfaces.tobago.util.FacesELUtils;
+
+import javax.el.ELContext;
+import javax.el.MethodExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+
+
+public class MethodExpressionTreeExpansionListener implements TreeExpansionListener, StateHolder {
+
+  private MethodExpression methodExpression;
+
+  private boolean isTransient = false;
+
+  public MethodExpressionTreeExpansionListener() {
+  }
+
+  public MethodExpressionTreeExpansionListener(final MethodExpression methodExpression) {
+    this.methodExpression = methodExpression;
+  }
+
+  @Override
+  public void treeExpanded(final TreeExpansionEvent event) {
+    FacesELUtils.invokeMethodExpression(FacesContext.getCurrentInstance(), methodExpression, event);
+  }
+
+  private ELContext elContext() {
+    return FacesContext.getCurrentInstance().getELContext();
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    methodExpression = (MethodExpression) state;
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    return methodExpression;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    isTransient = newTransientValue;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return isTransient;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTreeSelectedListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTreeSelectedListener.java
new file mode 100644
index 0000000..be6c380
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/MethodExpressionTreeSelectedListener.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.apache.myfaces.tobago.util.FacesELUtils;
+
+import javax.el.ELContext;
+import javax.el.MethodExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+
+public class MethodExpressionTreeSelectedListener implements TreeSelectedListener, StateHolder {
+
+  private MethodExpression methodExpression;
+
+  private boolean isTransient = false;
+
+  public MethodExpressionTreeSelectedListener() {
+  }
+
+  public MethodExpressionTreeSelectedListener(final MethodExpression methodExpression) {
+    this.methodExpression = methodExpression;
+  }
+
+  @Override
+  public void treeSelected(final TreeSelectedEvent event) {
+    FacesELUtils.invokeMethodExpression(FacesContext.getCurrentInstance(), methodExpression, event);
+  }
+
+  private ELContext elContext() {
+    return FacesContext.getCurrentInstance().getELContext();
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    methodExpression = (MethodExpression) state;
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    return methodExpression;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    isTransient = newTransientValue;
+  }
+
+  @Override
+  public boolean isTransient() {
+    return isTransient;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/PageActionEvent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/PageActionEvent.java
new file mode 100644
index 0000000..27bac8b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/PageActionEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+
+import javax.faces.event.ActionEvent;
+import javax.faces.component.UIComponent;
+
+
+public class PageActionEvent extends ActionEvent {
+
+  private static final long serialVersionUID = 3364193750247386220L;
+
+  private SheetAction action;
+  private int value;
+
+  public PageActionEvent(final UIComponent component, final SheetAction action) {
+    super(component);
+    this.action = action;
+  }
+
+  /**
+   * Returns the action type ({@link SheetAction}).
+   */
+  public SheetAction getAction() {
+    return action;
+  }
+
+  public void setValue(final int value) {
+    this.value = value;
+  }
+
+  /**
+   * Returns the value for action types {@link SheetAction#toRow}
+   * and {@link SheetAction#toPage}.
+   */
+  public int getValue() {
+    return value;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ResetFormActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ResetFormActionListener.java
new file mode 100644
index 0000000..fe1936c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ResetFormActionListener.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ActionEvent;
+import java.io.Serializable;
+
+public class ResetFormActionListener extends AbstractResetInputActionListener implements Serializable{
+
+  @Override
+  public void processAction(final ActionEvent actionEvent) throws AbortProcessingException {
+    UIComponent component = actionEvent.getComponent();
+    while ((component = component.getParent()) != null) {
+      if (component instanceof UIForm) {
+        resetChildren(component);
+        return;
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ResetInputActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ResetInputActionListener.java
new file mode 100644
index 0000000..91b97c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ResetInputActionListener.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+import java.util.Collection;
+
+public class ResetInputActionListener extends AbstractResetInputActionListener implements StateHolder {
+
+  private String [] clientIds;
+
+  public ResetInputActionListener() {
+  }
+
+  public ResetInputActionListener(final String[] clientIds) {
+    this.clientIds = clientIds;
+  }
+
+  public ResetInputActionListener(final Collection<String> clientIds) {
+     this.clientIds = clientIds.toArray(new String[clientIds.size()]);
+  }
+
+  @Override
+  public void processAction(final ActionEvent event) {
+    for (final String clientId : clientIds) {
+      final UIComponent component = ComponentUtils.findComponent(event.getComponent(), clientId);
+      if (component != null) {
+        resetChildren(component);
+      }
+    }
+  }
+
+  @Override
+  public boolean isTransient() {
+    return false;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    // ignore
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    final Object[] values = (Object[]) state;
+    clientIds = (String[]) values[0];
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] values = new Object[1];
+    values[0] = clientIds;
+    return values;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetAction.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetAction.java
new file mode 100644
index 0000000..277ab29
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetAction.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+
+public enum SheetAction {
+
+  /**
+   * First page is requested
+   */
+  first,
+
+  /**
+   * Previous page is requested
+   */
+  prev,
+
+  /**
+   * Next page is requested
+   */
+  next,
+
+  /**
+   * Last page is requested
+   */
+  last,
+
+  /**
+   * A specified row is requested
+   */
+  toRow,
+
+  /**
+   * A specified page is requested
+   */
+  toPage,
+
+  /**
+   * Sorting
+   */
+  sort;
+
+  private String bundleKey;
+
+  SheetAction() {
+    this.bundleKey = "sheet" + StringUtils.firstToUpperCase(name());
+  }
+
+  public String getBundleKey() {
+    return bundleKey;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeEvent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeEvent.java
new file mode 100644
index 0000000..252fd77
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeEvent.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesListener;
+import javax.faces.event.ActionEvent;
+
+public class SheetStateChangeEvent extends ActionEvent {
+
+  private static final long serialVersionUID = 2875570768774425451L;
+
+  public SheetStateChangeEvent(final UIComponent uiComponent) {
+    super(uiComponent);
+  }
+
+  @Override
+  public boolean isAppropriateListener(final FacesListener facesListener) {
+    return facesListener instanceof SheetStateChangeListener;
+  }
+
+  @Override
+  public void processListener(final FacesListener facesListener) {
+    if (facesListener instanceof SheetStateChangeListener) {
+      ((SheetStateChangeListener) facesListener).processSheetStateChange(this);
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeListener.java
new file mode 100644
index 0000000..ab4dbda
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeListener.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.event.FacesListener;
+
+public interface SheetStateChangeListener extends FacesListener {
+
+  void processSheetStateChange(SheetStateChangeEvent sheetStateChangeEvent);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeSource.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeSource.java
new file mode 100644
index 0000000..f793d50
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeSource.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+public interface SheetStateChangeSource {
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  javax.faces.el.MethodBinding getStateChangeListener();
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  void setStateChangeListener(javax.faces.el.MethodBinding actionListener);
+
+  void addStateChangeListener(SheetStateChangeListener listener);
+
+  SheetStateChangeListener[] getStateChangeListeners();
+
+  void removeStateChangeListener(SheetStateChangeListener listener);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeSource2.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeSource2.java
new file mode 100644
index 0000000..c881625
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SheetStateChangeSource2.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.el.MethodExpression;
+
+public interface SheetStateChangeSource2 extends SheetStateChangeSource {
+
+  MethodExpression getStateChangeListenerExpression();
+
+  void setStateChangeListenerExpression(MethodExpression actionListener);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionEvent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionEvent.java
new file mode 100644
index 0000000..856c219
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionEvent.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.UIColumn;
+import javax.faces.component.UIData;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.PhaseId;
+
+public class SortActionEvent extends ActionEvent {
+
+  private static final long serialVersionUID = 4906962574581815720L;
+
+  private transient UIColumn column;
+
+  public SortActionEvent(final UIData sheet, final UIColumn column) {
+    super(sheet);
+    this.column = column;
+    setPhaseId(PhaseId.INVOKE_APPLICATION);
+  }
+
+  /**
+   * @return UIColumn The UIColumn object for which this event was triggered.
+   */
+  public UIColumn getColumn() {
+    return column;
+  }
+
+  public UIData getSheet() {
+    return (UIData) getComponent();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionSource.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionSource.java
new file mode 100644
index 0000000..00c02bc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionSource.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.el.MethodBinding;
+
+public interface SortActionSource {
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  MethodBinding getSortActionListener();
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  void setSortActionListener(MethodBinding actionListener);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionSource2.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionSource2.java
new file mode 100644
index 0000000..787c940
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/SortActionSource2.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.el.MethodExpression;
+
+public interface SortActionSource2 extends SortActionSource {
+
+  MethodExpression getSortActionListenerExpression();
+
+  void setSortActionListenerExpression(MethodExpression actionListener);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeEvent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeEvent.java
new file mode 100644
index 0000000..62f99c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeEvent.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.FacesListener;
+
+public class TabChangeEvent extends ActionEvent {
+
+  private static final long serialVersionUID = 422186716954088729L;
+
+  private Integer oldTabIndex;
+  private Integer newTabIndex;
+
+  public TabChangeEvent(final UIComponent uiComponent, final Integer oldTabIndex, final Integer newTabIndex) {
+    super(uiComponent);
+    this.oldTabIndex = oldTabIndex;
+    this.newTabIndex = newTabIndex;
+  }
+  
+  /**
+   * @deprecated Please use {@link #TabChangeEvent(UIComponent, Integer, Integer)}
+   */
+  @Deprecated
+  public TabChangeEvent(final UIComponent uiComponent, final Object oldState, final Object newState) {
+    super(uiComponent);
+    setOldState(oldState);
+    setNewState(newState);
+  }
+
+  @Override
+  public boolean isAppropriateListener(final FacesListener facesListener) {
+    return facesListener instanceof TabChangeListener;
+  }
+
+  @Override
+  public void processListener(final FacesListener facesListener) {
+    if (facesListener instanceof TabChangeListener) {
+      ((TabChangeListener) facesListener).processTabChange(this);
+    }
+  }
+
+  public int getOldTabIndex() {
+    return oldTabIndex;
+  }
+
+  public int getNewTabIndex() {
+    return newTabIndex;
+  }
+
+  /**
+   * @deprecated Please use {@link #getOldTabIndex()}
+   */
+  @Deprecated
+  public Object getOldState() {
+    return oldTabIndex;
+  }
+
+  /**
+   * @deprecated Not supported anymore
+   */
+  @Deprecated
+  public void setOldState(final Object oldTabIndex) {
+    this.oldTabIndex = oldTabIndex instanceof Integer ? (Integer) oldTabIndex : -1;
+  }
+
+  /**
+   * @deprecated Please use {@link #getNewTabIndex()}
+   */
+  @Deprecated
+  public Object getNewState() {
+    return newTabIndex;
+  }
+
+  /**
+   * @deprecated Not supported anymore
+   */
+  @Deprecated
+  public void setNewState(final Object newTabIndex) {
+    this.newTabIndex = newTabIndex instanceof Integer ? (Integer) newTabIndex : -1;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeListener.java
new file mode 100644
index 0000000..041404f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeListener.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.event.FacesListener;
+
+public interface TabChangeListener extends FacesListener {
+
+  void processTabChange(TabChangeEvent tabChangeEvent);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeSource.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeSource.java
new file mode 100644
index 0000000..44f8251
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeSource.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+public interface TabChangeSource {
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  javax.faces.el.MethodBinding getTabChangeListener();
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  void setTabChangeListener(javax.faces.el.MethodBinding actionListener);
+
+  void addTabChangeListener(TabChangeListener listener);
+
+  TabChangeListener[] getTabChangeListeners();
+
+  void removeTabChangeListener(TabChangeListener listener);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeSource2.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeSource2.java
new file mode 100644
index 0000000..fe87751
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TabChangeSource2.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.el.MethodExpression;
+
+public interface TabChangeSource2 extends TabChangeSource {
+
+  MethodExpression getTabChangeListenerExpression();
+
+  void setTabChangeListenerExpression(MethodExpression actionListener);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeExpansionEvent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeExpansionEvent.java
new file mode 100644
index 0000000..183015c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeExpansionEvent.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+
+public class TreeExpansionEvent extends FacesEvent {
+
+  private static final long serialVersionUID = 422186716954088729L;
+
+  private boolean oldExpanded;
+  private boolean newExpanded;
+
+  public TreeExpansionEvent(final UIComponent node, final boolean oldExpanded, final boolean newExpanded) {
+    super(node);
+    this.oldExpanded = oldExpanded;
+    this.newExpanded = newExpanded;
+  }
+
+  @Override
+  public boolean isAppropriateListener(final FacesListener facesListener) {
+    return facesListener instanceof TreeExpansionListener;
+  }
+
+  @Override
+  public void processListener(final FacesListener facesListener) {
+    if (facesListener instanceof TreeExpansionListener) {
+      if (oldExpanded && !newExpanded) {
+   //todo     ((TreeExpansionListener) facesListener).treeCollapsed(this);
+        ((TreeExpansionListener) facesListener).treeExpanded(this);
+      } else if (!oldExpanded && newExpanded) {
+        ((TreeExpansionListener) facesListener).treeExpanded(this);
+      } else {
+        // nothing to do
+      }
+    }
+  }
+
+  public boolean isOldExpanded() {
+    return oldExpanded;
+  }
+
+  public boolean isNewExpanded() {
+    return newExpanded;
+  }
+
+  @Override
+  public String toString() {
+    return new StringBuilder()
+        .append(super.toString())
+        .append("expanded=")
+        .append(newExpanded)
+        .toString();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeExpansionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeExpansionListener.java
new file mode 100644
index 0000000..5eedf7a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeExpansionListener.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.event.FacesListener;
+
+public interface TreeExpansionListener  extends FacesListener {
+
+  void treeExpanded(TreeExpansionEvent event);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeSelectedEvent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeSelectedEvent.java
new file mode 100644
index 0000000..9321888
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeSelectedEvent.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.FacesListener;
+
+public class TreeSelectedEvent extends FacesEvent {
+
+  private static final long serialVersionUID = 422186716954088729L;
+
+  private boolean oldSelected;
+  private boolean newSelected;
+
+  public TreeSelectedEvent(final UIComponent node, final boolean oldSelected, final boolean newSelected) {
+    super(node);
+    this.oldSelected = oldSelected;
+    this.newSelected = newSelected;
+  }
+
+  @Override
+  public boolean isAppropriateListener(final FacesListener facesListener) {
+    return facesListener instanceof TreeSelectedListener;
+  }
+
+  @Override
+  public void processListener(final FacesListener facesListener) {
+    if (facesListener instanceof TreeSelectedListener) {
+      if (oldSelected && !newSelected) {
+        ((TreeSelectedListener) facesListener).treeSelected(this);
+      } else if (!oldSelected && newSelected) {
+        ((TreeSelectedListener) facesListener).treeSelected(this);
+      } else {
+        // nothing to do
+      }
+    }
+  }
+
+  public boolean isOldSelected() {
+    return oldSelected;
+  }
+
+  public boolean isNewSelected() {
+    return newSelected;
+  }
+
+  @Override
+  public String toString() {
+    return super.toString() + "selected=" + newSelected;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeSelectedListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeSelectedListener.java
new file mode 100644
index 0000000..5ef63e0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/TreeSelectedListener.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import javax.faces.event.FacesListener;
+
+public interface TreeSelectedListener extends FacesListener {
+
+  void treeSelected(TreeSelectedEvent event);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionResetInputActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionResetInputActionListener.java
new file mode 100644
index 0000000..db3f2d0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionResetInputActionListener.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+
+public class ValueExpressionResetInputActionListener extends AbstractResetInputActionListener implements StateHolder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ValueExpressionResetInputActionListener.class);
+
+  private ValueExpression clientIdsExpression;
+
+  /**
+   * No-arg constructor used during restoreState
+   */
+  public ValueExpressionResetInputActionListener() {
+  }
+
+  public ValueExpressionResetInputActionListener(final ValueExpression clientIdsExpression) {
+    this.clientIdsExpression = clientIdsExpression;
+  }
+
+  @Override
+  public void processAction(final ActionEvent event) {
+    final Object obj = clientIdsExpression.getValue(FacesContext.getCurrentInstance().getELContext());
+    final String [] clientIds;
+    if (obj instanceof String[]) {
+      clientIds = (String[]) obj;
+    } else if (obj instanceof String) {
+      clientIds= StringUtils.split((String) obj, ", ");
+    } else {
+      LOG.error("Ignore unknown value of " + obj + " for reset.");
+      return;
+    }
+    for (final String clientId : clientIds) {
+      final UIComponent component = ComponentUtils.findComponent(event.getComponent(), clientId);
+      if (component != null) {
+        resetChildren(component);
+      }
+    }
+  }
+
+  @Override
+  public boolean isTransient() {
+    return false;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    final Object[] values = (Object[]) state;
+    clientIdsExpression = (ValueExpression) UIComponentBase.restoreAttachedState(context, values[0]);
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] values = new Object[1];
+    values[0] = UIComponentBase.saveAttachedState(context, clientIdsExpression);
+    return values;
+  }
+
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    // ignore
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionSheetStateChangeListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionSheetStateChangeListener.java
new file mode 100644
index 0000000..5ba6c3b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionSheetStateChangeListener.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+
+public class ValueExpressionSheetStateChangeListener implements SheetStateChangeListener, StateHolder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ValueExpressionSheetStateChangeListener.class);
+
+  private String type;
+  private ValueExpression valueExpression;
+
+  public ValueExpressionSheetStateChangeListener() {
+  }
+
+  public ValueExpressionSheetStateChangeListener(final String type, final ValueExpression valueExpression) {
+    this.type = type;
+    this.valueExpression = valueExpression;
+  }
+
+  @Override
+  public void processSheetStateChange(final SheetStateChangeEvent sheetStateChangeEvent) {
+    final SheetStateChangeListener handler = getSheetStateChangeListener();
+    if (handler != null) {
+      handler.processSheetStateChange(sheetStateChangeEvent);
+    } else {
+      LOG.error("Ignoring SheetStateChangeEvent. No SheetStateChangeListener found.");
+    }
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] state = new Object[2];
+    state[0] = UIComponentBase.saveAttachedState(context, valueExpression);
+    state[1] = type;
+    return state;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    final Object[] values = (Object[]) state;
+    valueExpression = (ValueExpression) UIComponentBase.restoreAttachedState(context, values[0]);
+    type = (String) values[1];
+
+  }
+
+  @Override
+  public boolean isTransient() {
+    return false;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    // ignore
+  }
+
+  private SheetStateChangeListener getSheetStateChangeListener() {
+    SheetStateChangeListener handler = null;
+    if (valueExpression != null) {
+      final Object obj = valueExpression.getValue(FacesContext.getCurrentInstance().getELContext());
+      if (obj != null && obj instanceof SheetStateChangeListener) {
+        handler = (SheetStateChangeListener) obj;
+      }
+    }
+    if (handler == null && type != null) {
+      handler = createSheetStateChangeListener(type);
+      if (handler != null && valueExpression != null) {
+        valueExpression.setValue(FacesContext.getCurrentInstance().getELContext(), handler);
+      }
+    }
+    return handler;
+  }
+
+  private SheetStateChangeListener createSheetStateChangeListener(final String className) {
+    try {
+      final Class clazz = getClass().getClassLoader().loadClass(className);
+      return ((SheetStateChangeListener) clazz.newInstance());
+    } catch (final Exception e) {
+      LOG.error("", e);
+    }
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionTabChangeListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionTabChangeListener.java
new file mode 100644
index 0000000..2879ff7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/event/ValueExpressionTabChangeListener.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.event;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+
+public class ValueExpressionTabChangeListener implements TabChangeListener, StateHolder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ValueExpressionTabChangeListener.class);
+
+  private String type;
+  private ValueExpression valueExpression;
+
+  public ValueExpressionTabChangeListener() {
+  }
+
+  public ValueExpressionTabChangeListener(final String type, final ValueExpression valueExpression) {
+    this.type = type;
+    this.valueExpression = valueExpression;
+  }
+
+  @Override
+  public void processTabChange(final TabChangeEvent tabChangeEvent) {
+    final TabChangeListener handler = getTabChangeListener();
+    if (handler != null) {
+      handler.processTabChange(tabChangeEvent);
+    } else {
+      LOG.error("Ignoring TabChangeEvent. No TabChangeListener found.");
+    }
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] state = new Object[2];
+    state[0] = UIComponentBase.saveAttachedState(context, valueExpression);
+    state[1] = type;
+    return state;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    final Object[] values = (Object[]) state;
+    valueExpression = (ValueExpression) UIComponentBase.restoreAttachedState(context, values[0]);
+    type = (String) values[1];
+
+  }
+
+  @Override
+  public boolean isTransient() {
+    return false;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    // ignore
+  }
+
+  private TabChangeListener getTabChangeListener() {
+    TabChangeListener handler = null;
+    if (valueExpression != null) {
+      final Object obj = valueExpression.getValue(FacesContext.getCurrentInstance().getELContext());
+      if (obj != null && obj instanceof TabChangeListener) {
+        handler = (TabChangeListener) obj;
+      }
+    }
+    if (handler == null && type != null) {
+      handler = createTabChangeListener(type);
+      if (handler != null && valueExpression != null) {
+        valueExpression.setValue(FacesContext.getCurrentInstance().getELContext(), handler);
+      }
+    }
+    return handler;
+  }
+
+  private TabChangeListener createTabChangeListener(final String className) {
+    try {
+      final Class clazz = getClass().getClassLoader().loadClass(className);
+      return ((TabChangeListener) clazz.newInstance());
+    } catch (final Exception e) {
+      LOG.error("", e);
+    }
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/AttributeHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/AttributeHandler.java
new file mode 100644
index 0000000..36c408c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/AttributeHandler.java
@@ -0,0 +1,356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.el.ConstantMethodExpression;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.el.ELException;
+import javax.el.ExpressionFactory;
+import javax.el.MethodExpression;
+import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.component.ActionSource;
+import javax.faces.component.ActionSource2;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.ValueHolder;
+import javax.faces.convert.Converter;
+import javax.faces.event.MethodExpressionActionListener;
+import javax.faces.event.MethodExpressionValueChangeListener;
+import javax.faces.validator.MethodExpressionValidator;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagConfig;
+import javax.faces.view.facelets.TagException;
+import javax.faces.view.facelets.TagHandler;
+import java.beans.IntrospectionException;
+import java.beans.PropertyDescriptor;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class AttributeHandler extends TagHandler {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AttributeHandler.class);
+
+  private final TagAttribute name;
+
+  private final TagAttribute value;
+
+  private final TagAttribute mode;
+
+  public AttributeHandler(final TagConfig config) {
+    super(config);
+    this.name = getRequiredAttribute(Attributes.name.getName());
+    this.value = getRequiredAttribute(Attributes.value.getName());
+    this.mode = getAttribute(Attributes.mode.getName());
+  }
+
+  @Override
+  public void apply(final FaceletContext faceletContext, final UIComponent parent) throws ELException {
+    if (parent == null) {
+      throw new TagException(tag, "Parent UIComponent was null");
+    }
+
+    if (ComponentHandler.isNew(parent)) {
+
+      if (mode != null) {
+        if ("isNotSet".equals(mode.getValue())) {
+          boolean result = false;
+          String expressionString = value.getValue();
+          if (!value.isLiteral()) {
+            while (isSimpleExpression(expressionString)) {
+              if (isMethodOrValueExpression(expressionString)) {
+                final ValueExpression expression
+                    = faceletContext.getVariableMapper().resolveVariable(removeElParenthesis(expressionString));
+                if (expression == null) {
+                  result = true;
+                  break;
+                } else {
+                  expressionString = expression.getExpressionString();
+                }
+              } else {
+                result = false;
+                break;
+              }
+            }
+          } else {
+            result = StringUtils.isEmpty(expressionString);
+          }
+          parent.getAttributes().put(name.getValue(), result);
+        } else if ("isSet".equals(mode.getValue())) {
+          boolean result = true;
+          String expressionString = value.getValue();
+          if (!value.isLiteral()) {
+            while (isSimpleExpression(expressionString)) {
+              if (isMethodOrValueExpression(expressionString)) {
+                final ValueExpression expression
+                    = faceletContext.getVariableMapper().resolveVariable(removeElParenthesis(expressionString));
+                if (expression == null) {
+                  result = false;
+                  break;
+                } else {
+                  expressionString = expression.getExpressionString();
+                }
+              } else {
+                result = true;
+                break;
+              }
+            }
+          } else {
+            result = StringUtils.isNotEmpty(expressionString);
+          }
+          parent.getAttributes().put(name.getValue(), result);
+        } else if ("action".equals(mode.getValue())) {
+          String expressionString = value.getValue();
+          while (isSimpleExpression(expressionString)) {
+            if (isMethodOrValueExpression(expressionString)) {
+              final ValueExpression expression
+                  = faceletContext.getVariableMapper().resolveVariable(removeElParenthesis(expressionString));
+              if (expression == null) {
+                // when the action hasn't been set while using a composition.
+                if (LOG.isDebugEnabled()) {
+                  LOG.debug("Variable can't be resolved: value='" + expressionString + "'");
+                }
+                expressionString = null;
+                break;
+              } else {
+                expressionString = expression.getExpressionString();
+              }
+            } else {
+              break;
+            }
+          }
+          if (expressionString != null) {
+            final ExpressionFactory expressionFactory = faceletContext.getExpressionFactory();
+            final MethodExpression action = new TagMethodExpression(value, expressionFactory.createMethodExpression(
+                faceletContext, expressionString, String.class, ComponentUtils.ACTION_ARGS));
+            ((ActionSource2) parent).setActionExpression(action);
+          }
+        } else if ("actionListener".equals(mode.getValue())) {
+          String expressionString = value.getValue();
+          while (isSimpleExpression(expressionString)) {
+            if (isMethodOrValueExpression(expressionString)) {
+              final ValueExpression expression
+                  = faceletContext.getVariableMapper().resolveVariable(removeElParenthesis(expressionString));
+              if (expression == null) {
+                if (LOG.isDebugEnabled()) {
+                  // when the action hasn't been set while using a composition.
+                  LOG.debug("Variable can't be resolved: value='" + expressionString + "'");
+                }
+                expressionString = null;
+                break;
+              } else {
+                expressionString = expression.getExpressionString();
+              }
+            } else {
+              LOG.warn("Only expressions are supported mode=actionListener value='" + expressionString + "'");
+              expressionString = null;
+              break;
+            }
+          }
+          if (expressionString != null) {
+            final ExpressionFactory expressionFactory = faceletContext.getExpressionFactory();
+            final MethodExpression actionListener
+                = new TagMethodExpression(value, expressionFactory.createMethodExpression(
+                faceletContext, expressionString, null, ComponentUtils.ACTION_LISTENER_ARGS));
+            ((ActionSource) parent).addActionListener(new MethodExpressionActionListener(actionListener));
+          }
+        } else if ("actionFromValue".equals(mode.getValue())) {
+          if (!value.isLiteral()) {
+            final String result = value.getValue(faceletContext);
+            parent.getAttributes().put(name.getValue(), new ConstantMethodExpression(result));
+          }
+        } else if ("valueIfSet".equals(mode.getValue())) {
+          String expressionString = value.getValue();
+          String lastExpressionString = null;
+          while (isMethodOrValueExpression(expressionString) && isSimpleExpression(expressionString)) {
+            final ValueExpression expression
+                = faceletContext.getVariableMapper().resolveVariable(removeElParenthesis(expressionString));
+            if (expression != null) {
+              lastExpressionString = expressionString;
+              expressionString = expression.getExpressionString();
+            } else {
+              // restore last value
+              expressionString = lastExpressionString;
+              break;
+            }
+          }
+          if (expressionString != null) {
+            final String attributeName = name.getValue(faceletContext);
+            if (containsMethodOrValueExpression(expressionString)) {
+              final ValueExpression expression = value.getValueExpression(faceletContext, Object.class);
+              parent.setValueExpression(attributeName, expression);
+            } else {
+              final Object literalValue = getValue(faceletContext, parent, expressionString, attributeName);
+              parent.getAttributes().put(attributeName, literalValue);
+            }
+          }
+        } else {
+          throw new FacesException("Type " + mode + " not supported");
+        }
+      } else {
+
+        final Attributes nameValue = Attributes.valueOfFailsafe(name.getValue(faceletContext));
+        if (Attributes.rendered == nameValue) {
+          if (value.isLiteral()) {
+            parent.setRendered(value.getBoolean(faceletContext));
+          } else {
+            parent.setValueExpression(nameValue.getName(), value.getValueExpression(faceletContext, Boolean.class));
+          }
+        } else if (Attributes.markup == nameValue) {
+          if (parent instanceof Visual) {
+            if (value.isLiteral()) {
+              ((Visual) parent).setMarkup(Markup.valueOf(value.getValue()));
+            } else {
+              final ValueExpression expression = value.getValueExpression(faceletContext, Object.class);
+              parent.setValueExpression(nameValue.getName(), expression);
+            }
+          } else {
+            LOG.error("Component is not instanceof Visual. Instance is: " + parent.getClass().getName());
+          }
+        } else if (parent instanceof EditableValueHolder && Attributes.validator == nameValue) {
+          final MethodExpression methodExpression
+              = getMethodExpression(faceletContext, null, ComponentUtils.VALIDATOR_ARGS);
+          if (methodExpression != null) {
+            ((EditableValueHolder) parent).addValidator(new MethodExpressionValidator(methodExpression));
+          }
+        } else if (parent instanceof EditableValueHolder && Attributes.valueChangeListener == nameValue) {
+          final MethodExpression methodExpression =
+              getMethodExpression(faceletContext, null, ComponentUtils.VALUE_CHANGE_LISTENER_ARGS);
+          if (methodExpression != null) {
+            ((EditableValueHolder) parent).addValueChangeListener(
+                new MethodExpressionValueChangeListener(methodExpression));
+          }
+        } else if (parent instanceof ValueHolder && Attributes.converter == nameValue) {
+          setConverter(faceletContext, parent, nameValue.getName());
+        } else if (parent instanceof ActionSource && Attributes.action.equals(nameValue)) {
+          final MethodExpression action = getMethodExpression(faceletContext, String.class, ComponentUtils.ACTION_ARGS);
+          if (action != null) {
+            ((ActionSource2) parent).setActionExpression(action);
+          }
+        } else if (parent instanceof ActionSource && Attributes.actionListener == nameValue) {
+          final MethodExpression action
+              = getMethodExpression(faceletContext, null, ComponentUtils.ACTION_LISTENER_ARGS);
+          if (action != null) {
+            ((ActionSource) parent).addActionListener(new MethodExpressionActionListener(action));
+          }
+        } else if (nameValue != null && !parent.getAttributes().containsKey(nameValue.getName())) {
+          if (value.isLiteral()) {
+            parent.getAttributes().put(nameValue.getName(), value.getValue());
+          } else {
+            parent.setValueExpression(nameValue.getName(), value.getValueExpression(faceletContext, Object.class));
+          }
+        } else if (nameValue == null) {
+          LOG.warn("Null value for {}", name);
+        }
+      }
+    }
+  }
+
+  private boolean isMethodOrValueExpression(final String string) {
+    return (string.startsWith("${") || string.startsWith("#{")) && string.endsWith("}");
+  }
+
+  private boolean containsMethodOrValueExpression(final String string) {
+    return (string.contains("${") || string.contains("#{")) && string.contains("}");
+  }
+
+  private boolean isSimpleExpression(final String string) {
+    return string.indexOf('.') < 0 && string.indexOf('[') < 0;
+  }
+
+  private String removeElParenthesis(final String string) {
+    return string.substring(2, string.length() - 1);
+  }
+
+  private ValueExpression getExpression(final FaceletContext faceletContext) {
+    final String myValue = removeElParenthesis(value.getValue());
+    return faceletContext.getVariableMapper().resolveVariable(myValue);
+  }
+
+  private MethodExpression getMethodExpression(
+      final FaceletContext faceletContext, final Class returnType, final Class[] args) {
+    // in a composition may be we get the method expression string from the current variable mapper
+    // the expression can be empty
+    // in this case return nothing
+    if (value.getValue().startsWith("${")) {
+      final ValueExpression expression = getExpression(faceletContext);
+      if (expression != null) {
+        final ExpressionFactory expressionFactory = faceletContext.getExpressionFactory();
+        return new TagMethodExpression(value, expressionFactory.createMethodExpression(faceletContext,
+            expression.getExpressionString(), returnType, args));
+      } else {
+        return null;
+      }
+    } else {
+      return value.getMethodExpression(faceletContext, returnType, args);
+    }
+  }
+
+  private Object getValue(
+      final FaceletContext faceletContext, final UIComponent parent, final String expressionString,
+      final String attributeName) {
+    Class type = Object.class;
+    try {
+      type = PropertyUtils.getReadMethod(
+          new PropertyDescriptor(attributeName, parent.getClass())).getReturnType();
+    } catch (final IntrospectionException e) {
+      LOG.warn("Can't determine expected type", e);
+    }
+    final ExpressionFactory expressionFactory = faceletContext.getExpressionFactory();
+    final ValueExpression valueExpression = expressionFactory
+        .createValueExpression(faceletContext, expressionString, type);
+    return valueExpression.getValue(faceletContext);
+  }
+
+  private void setConverter(final FaceletContext faceletContext, final UIComponent parent, final String nameValue) {
+    // in a composition may be we get the converter expression string from the current variable mapper
+    // the expression can be empty
+    // in this case return nothing
+    if (value.getValue().startsWith("${")) {
+      final ValueExpression expression = getExpression(faceletContext);
+      if (expression != null) {
+        setConverter(faceletContext, parent, nameValue, expression);
+      }
+    } else {
+      setConverter(faceletContext, parent, nameValue, value.getValueExpression(faceletContext, Object.class));
+    }
+  }
+
+  private void setConverter(
+      final FaceletContext faceletContext, final UIComponent parent, final String nameValue,
+      final ValueExpression expression) {
+    if (expression.isLiteralText()) {
+      final Converter converter =
+          faceletContext.getFacesContext().getApplication().createConverter(expression.getExpressionString());
+      ((ValueHolder) parent).setConverter(converter);
+    } else {
+      parent.setValueExpression(nameValue, expression);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ContentTypeRule.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ContentTypeRule.java
new file mode 100644
index 0000000..1b3fea9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ContentTypeRule.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.validator.FileItemValidator;
+
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+public class ContentTypeRule extends MetaRule {
+
+  public static final ContentTypeRule INSTANCE = new ContentTypeRule();
+
+  @Override
+  public Metadata applyRule(final String name, final TagAttribute attribute, final MetadataTarget metadataTarget) {
+    if ("contentType".equals(name)) {
+      return new ContentTypeRuleMapper(attribute);
+    }
+    return null;
+  }
+
+  static final class ContentTypeRuleMapper extends Metadata {
+
+    private final TagAttribute attribute;
+
+    public ContentTypeRuleMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      final String[] components = ComponentUtils.splitList(attribute.getValue(ctx));
+      ((FileItemValidator) instance).setContentType(components);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ConverterHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ConverterHandler.java
new file mode 100644
index 0000000..65d80ab
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ConverterHandler.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import javax.el.ELException;
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.component.ValueHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagAttributeException;
+import javax.faces.view.facelets.TagConfig;
+import javax.faces.view.facelets.TagException;
+import javax.faces.view.facelets.TagHandler;
+import java.io.IOException;
+
+public class ConverterHandler extends TagHandler {
+
+  private final TagAttribute converterId;
+
+  private final TagAttribute binding;
+
+  public ConverterHandler(final TagConfig config) {
+    super(config);
+    binding = getAttribute("binding");
+    converterId = getAttribute("type");
+  }
+
+  @Override
+  public void apply(final FaceletContext faceletContext, final UIComponent parent)
+      throws IOException, ELException {
+    if (parent instanceof ValueHolder) {
+      if (ComponentHandler.isNew(parent)) {
+        final ValueHolder valueHolder = (ValueHolder) parent;
+        Converter converter = null;
+        ValueExpression valueExpression = null;
+        if (binding != null) {
+          valueExpression = binding.getValueExpression(faceletContext, Converter.class);
+          converter = (Converter) valueExpression.getValue(faceletContext);
+        }
+        if (converter == null) {
+          try {
+            converter = FacesContext.getCurrentInstance().getApplication().createConverter(
+                (String) converterId.getValueExpression(faceletContext, String.class).getValue(faceletContext));
+          } catch (final Exception e) {
+            throw new TagAttributeException(tag, converterId, e.getCause());
+          }
+          if (valueExpression != null) {
+            valueExpression.setValue(faceletContext, converter);
+          }
+        }
+        if (converter != null) {
+          valueHolder.setConverter(converter);
+        }
+        // TODO else LOG.warn?
+      }
+    } else {
+      throw new TagException(tag, "Parent is not of type ValueHolder, type is: " + parent);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/DataAttributeHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/DataAttributeHandler.java
new file mode 100644
index 0000000..a2ee62d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/DataAttributeHandler.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.el.ELException;
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagConfig;
+import javax.faces.view.facelets.TagException;
+import javax.faces.view.facelets.TagHandler;
+
+public final class DataAttributeHandler extends TagHandler {
+
+  private final TagAttribute name;
+
+  private final TagAttribute value;
+
+  public DataAttributeHandler(final TagConfig config) {
+    super(config);
+    this.name = getRequiredAttribute(Attributes.name.getName());
+    this.value = getRequiredAttribute(Attributes.value.getName());
+  }
+
+  @Override
+  public void apply(final FaceletContext faceletContext, final UIComponent parent) throws ELException {
+    if (parent == null) {
+      throw new TagException(tag, "Parent UIComponent was null");
+    }
+
+    if (ComponentHandler.isNew(parent)) {
+
+      final Object attributeName = name.isLiteral()
+          ? (Object) name.getValue(faceletContext)
+          : name.getValueExpression(faceletContext, Object.class);
+      final Object attributeValue = value.isLiteral()
+          ? (Object) value.getValue(faceletContext)
+          : value.getValueExpression(faceletContext, Object.class);
+      ComponentUtils.putDataAttribute(parent, attributeName, attributeValue);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/DefaultResourceResolver.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/DefaultResourceResolver.java
new file mode 100644
index 0000000..d5fe7d3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/DefaultResourceResolver.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import javax.faces.FacesException;
+import javax.faces.context.FacesContext;
+import javax.faces.view.facelets.ResourceResolver;
+import java.io.IOException;
+import java.net.URL;
+
+/*
+ * Was copied from MyFaces-Impl, because there is no JSF base class.
+ */
+public class DefaultResourceResolver extends ResourceResolver {
+
+  public DefaultResourceResolver() {
+    super();
+  }
+
+  @Override
+  public URL resolveUrl(final String path) {
+    try {
+      return Resource.getResourceUrl(FacesContext.getCurrentInstance(), path);
+    } catch (final IOException e) {
+      throw new FacesException(e);
+    }
+  }
+
+  public String toString() {
+    return "DefaultResourceResolver";
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/EventHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/EventHandler.java
new file mode 100644
index 0000000..fefd35e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/EventHandler.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.UIEvent;
+import org.apache.myfaces.tobago.internal.behavior.EventBehavior;
+
+import javax.el.MethodExpression;
+import javax.faces.component.PartialStateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.AjaxBehavior;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.faces.event.AjaxBehaviorListener;
+import javax.faces.view.BehaviorHolderAttachedObjectHandler;
+import javax.faces.view.facelets.ComponentConfig;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagAttributeException;
+import javax.faces.view.facelets.TagException;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This tag creates an instance of AjaxBehavior, and associates it with the nearest
+ * parent UIComponent that implements ClientBehaviorHolder interface. This tag can
+ * be used on single or composite components.
+ * <p>
+ * Unless otherwise specified, all attributes accept static values or EL expressions.
+ * </p>
+ * <p>
+ * According to the documentation, the tag handler implementing this tag should meet
+ * the following conditions:
+ * </p>
+ * <ul>
+ * <li>Since this tag attach objects to UIComponent instances, and those instances
+ * implements Behavior interface, this component should implement
+ * BehaviorHolderAttachedObjectHandler interface.</li>
+ * <li>f:ajax does not support binding property. In theory we should do something similar
+ * to f:convertDateTime tag does: extends from ConverterHandler and override setAttributes
+ * method, but in this case BehaviorTagHandlerDelegate has binding property defined, so
+ * if we extend from BehaviorHandler we add binding support to f:ajax.</li>
+ * <li>This tag works as a attached object handler, but note on the api there is no component
+ * to define a target for a behavior. See comment inside apply() method.</li>
+ * </ul>
+ *
+ * @since 3.0.0
+ */
+public class EventHandler extends TobagoComponentHandler implements BehaviorHolderAttachedObjectHandler {
+
+  public static final Class<?>[] AJAX_BEHAVIOR_LISTENER_SIG = new Class<?>[]{AjaxBehaviorEvent.class};
+
+  private final TagAttribute event;
+
+// todo (see original AjaxHandler impl)  private final boolean _wrapMode;
+
+  public EventHandler(ComponentConfig config) {
+    super(config);
+    event = getAttribute(Attributes.event.getName());
+  }
+
+  public void apply(FaceletContext ctx, UIComponent parent)
+      throws IOException {
+
+    super.apply(ctx, parent);
+
+    //Apply only if we are creating a new component
+    if (!ComponentHandler.isNew(parent)) {
+      return;
+    }
+    if (parent instanceof ClientBehaviorHolder) {
+      //Apply this handler directly over the parent
+      applyAttachedObject(ctx.getFacesContext(), parent);
+//todo      } else if (UIComponent.isCompositeComponent(parent)) {
+//todo        FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(ctx);
+      // It is supposed that for composite components, this tag should
+      // add itself as a target, but note that on whole api does not exists
+      // some tag that expose client behaviors as targets for composite
+      // components. In RI, there exists a tag called composite:clientBehavior,
+      // but does not appear on spec or javadoc, maybe because this could be
+      // understand as an implementation detail, after all there exists a key
+      // called AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY that could be
+      // used to create a tag outside jsf implementation to attach targets.
+//todo        mctx.addAttachedObjectHandler(parent, this);
+    } else {
+      throw new TagException(this.tag,
+          "Parent is not composite component or of type ClientBehaviorHolder, type is: "
+              + parent);
+    }
+  }
+
+  /**
+   * ViewDeclarationLanguage.retargetAttachedObjects uses it to check
+   * if the the target to be processed is applicable for this handler
+   */
+  public String getEventName() {
+    if (event == null) {
+      return null;
+    } else {
+      return event.getValue();
+    }
+  }
+
+  /**
+   * This method should create an AjaxBehavior object and attach it to the
+   * parent component.
+   * <p>
+   * Also, it should check if the parent can apply the selected AjaxBehavior
+   * to the selected component through ClientBehaviorHolder.getEventNames() or
+   * ClientBehaviorHolder.getDefaultEventName()
+   */
+  public void applyAttachedObject(FacesContext context, UIComponent parent) {
+    // Retrieve the current FaceletContext from FacesContext object
+    FaceletContext faceletContext = (FaceletContext) context
+        .getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);
+
+    // cast to a ClientBehaviorHolder
+    ClientBehaviorHolder cvh = (ClientBehaviorHolder) parent;
+
+    String eventName = getEventName();
+    if (eventName == null) {
+      eventName = cvh.getDefaultEventName();
+      if (eventName == null) {
+        throw new TagAttributeException(event, "eventName could not be defined for f:ajax tag with no wrap mode.");
+      }
+    } else if (!cvh.getEventNames().contains(eventName)) {
+      throw new TagAttributeException(event, "event it is not a valid eventName defined for this component");
+    }
+
+    Map<String, List<ClientBehavior>> clientBehaviors = cvh.getClientBehaviors();
+
+    List<ClientBehavior> clientBehaviorList = clientBehaviors.get(eventName);
+    if (clientBehaviorList != null && !clientBehaviorList.isEmpty()) {
+      for (ClientBehavior cb : clientBehaviorList) {
+        if (cb instanceof AjaxBehavior) {
+          // The most inner one has been applied, so according to
+          // jsf 2.0 spec section 10.4.1.1 it is not necessary to apply
+          // this one, because the inner one has precendece over
+          // the outer one.
+          return;
+        }
+      }
+    }
+
+    EventBehavior ajaxBehavior = createBehavior(context);
+
+    cvh.addClientBehavior(eventName, ajaxBehavior);
+  }
+
+  protected EventBehavior createBehavior(FacesContext context) {
+    return (EventBehavior) context.getApplication().createBehavior(EventBehavior.BEHAVIOR_ID);
+  }
+
+  @Override
+  public void onComponentCreated(FaceletContext faceletContext, UIComponent component, UIComponent parent) {
+    super.onComponentCreated(faceletContext, component, parent);
+
+    final UIEvent event = (UIEvent) component;
+    if (event.getEvent() == null) {
+      final ClientBehaviorHolder cvh = (ClientBehaviorHolder) parent;
+      event.setEvent(ClientBehaviors.valueOf(cvh.getDefaultEventName()));
+    }
+  }
+
+  /**
+   * The documentation says this attribute should not be used since it is not
+   * taken into account. Instead, getEventName is used on
+   * ViewDeclarationLanguage.retargetAttachedObjects.
+   */
+  public String getFor() {
+    return null;
+  }
+
+  /**
+   * Wraps a method expression in a AjaxBehaviorListener
+   */
+  public static final class AjaxBehaviorListenerImpl implements
+      AjaxBehaviorListener, PartialStateHolder {
+    private MethodExpression expression;
+    private boolean transientBoolean;
+    private boolean initialStateMarked;
+
+    public AjaxBehaviorListenerImpl() {
+    }
+
+    public AjaxBehaviorListenerImpl(MethodExpression expr) {
+      expression = expr;
+    }
+
+    public void processAjaxBehavior(AjaxBehaviorEvent event)
+        throws AbortProcessingException {
+      expression.invoke(FacesContext.getCurrentInstance().getELContext(),
+          new Object[]{event});
+    }
+
+    public boolean isTransient() {
+      return transientBoolean;
+    }
+
+    public void restoreState(FacesContext context, Object state) {
+      if (state == null) {
+        return;
+      }
+      expression = (MethodExpression) state;
+    }
+
+    public Object saveState(FacesContext context) {
+      if (initialStateMarked()) {
+        return null;
+      }
+      return expression;
+    }
+
+    public void setTransient(boolean newTransientValue) {
+      transientBoolean = newTransientValue;
+    }
+
+    public void clearInitialState() {
+      initialStateMarked = false;
+    }
+
+    public boolean initialStateMarked() {
+      return initialStateMarked;
+    }
+
+    public void markInitialState() {
+      initialStateMarked = true;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/FixCharacterEncodingFilter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/FixCharacterEncodingFilter.java
new file mode 100644
index 0000000..f0c0f09
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/FixCharacterEncodingFilter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.FilterChain;
+import javax.servlet.annotation.WebFilter;
+import java.io.IOException;
+
+@WebFilter(urlPatterns = "/*")
+public class FixCharacterEncodingFilter implements Filter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(FixCharacterEncodingFilter.class);
+
+  @Override
+  public void init(final FilterConfig filterConfig) throws ServletException {
+    if (LOG.isInfoEnabled()) {
+      LOG.info("Filter initialized: Setting characterEncoding to UTF-8 to all requests.");
+    }
+  }
+
+  @Override
+  public void doFilter(
+      final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain)
+      throws IOException, ServletException {
+    if (servletRequest.getCharacterEncoding() == null) {
+      servletRequest.setCharacterEncoding("UTF-8");
+    }
+    filterChain.doFilter(servletRequest, servletResponse);
+  }
+
+  @Override
+  public void destroy() {
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/MetaInfResourcesClasspathResourceResolver.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/MetaInfResourcesClasspathResourceResolver.java
new file mode 100644
index 0000000..a69e486
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/MetaInfResourcesClasspathResourceResolver.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+
+/**
+ * <p>
+ * Provides facelets from the directory "META-INF/resources/" of any jar file in the classpath.
+ * With the Servlet 3.0 specification this is no longer needed.
+ * </p>
+ * <p>
+ * To configure this ResourceResolver put this code into the web.xml file:
+ * </p>
+ * <pre>
+ *  &lt;context-param&gt;
+ *    &lt;param-name&gt;javax.faces.FACELETS_RESOURCE_RESOLVER&lt;/param-name&gt;
+ *    &lt;param-value&gt;
+ *        org.apache.myfaces.tobago.facelets.MetaInfResourcesClasspathResourceResolver
+ *    &lt;/param-value&gt;
+ *  &lt;/context-param&gt;
+ * </pre>
+ */
+public class MetaInfResourcesClasspathResourceResolver extends DefaultResourceResolver {
+
+  private static final Logger LOG = LoggerFactory.getLogger(MetaInfResourcesClasspathResourceResolver.class);
+
+  public MetaInfResourcesClasspathResourceResolver() {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("MetaInfResourcesClasspathResourceResolver is configured to resolve resources.");
+    }
+  }
+
+  @Override
+  public URL resolveUrl(String path) {
+    URL url = super.resolveUrl(path);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("default   url='" + url + "'");
+    }
+    if (url == null) {
+      if (path.startsWith("/")) {
+        path = path.substring(1);
+      }
+      path = "META-INF/resources/" + path;
+
+      url = Thread.currentThread().getContextClassLoader().getResource(path);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("classpath url='" + url + "'");
+      }
+    }
+    return url;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ResetInputActionListenerHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ResetInputActionListenerHandler.java
new file mode 100644
index 0000000..1de5b58
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ResetInputActionListenerHandler.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.event.ResetFormActionListener;
+import org.apache.myfaces.tobago.event.ResetInputActionListener;
+import org.apache.myfaces.tobago.event.ValueExpressionResetInputActionListener;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.el.ValueExpression;
+import javax.faces.component.ActionSource;
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagConfig;
+import javax.faces.view.facelets.TagException;
+import javax.faces.view.facelets.TagHandler;
+import java.io.IOException;
+
+public class ResetInputActionListenerHandler extends TagHandler {
+
+  private final TagAttribute execute;
+
+  public ResetInputActionListenerHandler(final TagConfig config) {
+    super(config);
+    execute = getAttribute(Attributes.execute.getName());
+  }
+
+  @Override
+  public void apply(final FaceletContext faceletContext, final UIComponent parent) throws IOException {
+    if (parent instanceof ActionSource) {
+      if (ComponentHandler.isNew(parent)) {
+        final ActionSource actionSource = (ActionSource) parent;
+        if (execute == null) {
+          actionSource.addActionListener(new ResetFormActionListener());
+        } else if (execute.isLiteral())  {
+          actionSource.addActionListener(new ResetInputActionListener(ComponentUtils.splitList(execute.getValue())));
+        } else {
+          final ValueExpression forValueExpression = execute.getValueExpression(faceletContext, String.class);
+          actionSource.addActionListener(new ValueExpressionResetInputActionListener(forValueExpression));
+        }
+      }
+    } else {
+      throw new TagException(tag, "Parent is not of type ActionSource, type is: " + parent);
+    }
+  }
+}
+
+
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/Resource.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/Resource.java
new file mode 100644
index 0000000..a6b109c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/Resource.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletContext;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLStreamHandler;
+
+/*
+ * Was copied from MyFaces-Impl, because there is no JSF base class.
+ */
+public final class Resource {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Resource.class);
+
+  private Resource() {
+  }
+
+  /**
+   * Get an URL of an internal resource. First, {@link javax.faces.context.ExternalContext#getResource(String)} is
+   * checked for an non-null URL return value. In the case of a null return value (as it is the case for Weblogic 8.1
+   * for a packed war), a URL with a special URL handler is constructed, which can be used for <em>opening</em> a
+   * serlvet resource later. Internally, this special URL handler will call
+   * {@link javax.servlet.ServletContext#getResourceAsStream(String)} when an inputstream is requested.
+   * This works even on Weblogic 8.1
+   *
+   * @param ctx  the faces context from which to retrieve the resource
+   * @param path an URL path
+   * @return an url representing the URL and on which getInputStream() can be called to get the resource
+   */
+  public static URL getResourceUrl(final FacesContext ctx, final String path) throws MalformedURLException {
+    final ExternalContext externalContext = ctx.getExternalContext();
+    URL url = externalContext.getResource(path);
+    if (LOG.isTraceEnabled()) {
+      LOG.trace("Resource-Url from external context: " + url);
+    }
+    if (url == null) {
+      // This might happen on Servlet container which doesnot return
+      // anything
+      // for getResource() (like weblogic 8.1 for packaged wars) we
+      // are trying
+      // to use an own URL protocol in order to use
+      // ServletContext.getResourceAsStream()
+      // when opening the url
+      if (resourceExist(externalContext, path)) {
+        url = getUrlForResourceAsStream(externalContext, path);
+      }
+    }
+    return url;
+  }
+
+  // This method could be used above to provide a 'fail fast' if a
+  // resource
+  // doesnt exist. Otherwise, the URL will fail on the first access.
+  private static boolean resourceExist(final ExternalContext externalContext, final String path) {
+    if ("/".equals(path)) {
+      // The root context exists always
+      return true;
+    }
+    final Object ctx = externalContext.getContext();
+    if (ctx instanceof ServletContext) {
+      final ServletContext servletContext = (ServletContext) ctx;
+      final InputStream stream = servletContext.getResourceAsStream(path);
+      if (stream != null) {
+        try {
+          stream.close();
+        } catch (final IOException e) {
+          // Ignore here, since we donnot wanted to read from this
+          // resource anyway
+        }
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Construct URL with special URLStreamHandler for proxying
+  // ServletContext.getResourceAsStream()
+  private static URL getUrlForResourceAsStream(final ExternalContext externalContext, final String path)
+      throws MalformedURLException {
+    final URLStreamHandler handler = new URLStreamHandler() {
+      @Override
+      protected URLConnection openConnection(final URL u) throws IOException {
+        final String file = u.getFile();
+        return new URLConnection(u) {
+          @Override
+          public void connect() throws IOException {
+          }
+
+          @Override
+          public InputStream getInputStream() throws IOException {
+            if (LOG.isTraceEnabled()) {
+              LOG.trace("Opening internal url to " + file);
+            }
+            final Object ctx = externalContext.getContext();
+            // Or maybe fetch the external context afresh ?
+            // Object ctx =
+            // FacesContext.getCurrentInstance().getExternalContext().getContext();
+
+            if (ctx instanceof ServletContext) {
+              final ServletContext servletContext = (ServletContext) ctx;
+              final InputStream stream = servletContext.getResourceAsStream(file);
+              if (stream == null) {
+                throw new FileNotFoundException("Cannot open resource " + file);
+              }
+              return stream;
+            } else {
+              throw new IOException("Cannot open resource for an context of "
+                  + (ctx != null ? ctx.getClass() : null));
+            }
+          }
+        };
+      }
+    };
+    return new URL("internal", null, 0, path, handler);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ScriptHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ScriptHandler.java
new file mode 100644
index 0000000..00f4493
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/ScriptHandler.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.ComponentConfig;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+
+public class ScriptHandler extends ComponentHandler {
+
+  public ScriptHandler(final ComponentConfig config) {
+    super(config);
+  }
+
+  @Override
+  public void onComponentCreated(final FaceletContext context, final UIComponent component, final UIComponent parent) {
+  }
+
+  @Override
+  public void applyNextHandler(final FaceletContext ctx, final UIComponent c) {
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SegmentLayoutRule.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SegmentLayoutRule.java
new file mode 100644
index 0000000..276c963
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SegmentLayoutRule.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.UISegmentLayout;
+import org.apache.myfaces.tobago.layout.ColumnPartition;
+
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+public class SegmentLayoutRule extends MetaRule {
+
+  public static final SegmentLayoutRule INSTANCE = new SegmentLayoutRule();
+
+  @Override
+  public Metadata applyRule(final String name, final TagAttribute attribute, final MetadataTarget metadataTarget) {
+    if (metadataTarget.isTargetInstanceOf(UISegmentLayout.class)) {
+      if (attribute.isLiteral()) {
+        Attributes a = Attributes.valueOfFailsafe(name);
+        if (Attributes.extraSmall == a) {
+          return new ExtraSmallMapper(attribute);
+        }
+        if (Attributes.small == a) {
+          return new SmallMapper(attribute);
+        }
+        if (Attributes.medium == a) {
+          return new MediumMapper(attribute);
+        }
+        if (Attributes.large == a) {
+          return new LargeMapper(attribute);
+        }
+      }
+    }
+    return null;
+  }
+
+  static final class ExtraSmallMapper extends Metadata {
+    private final TagAttribute attribute;
+
+    ExtraSmallMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      final UISegmentLayout gridLayout = (UISegmentLayout) instance;
+      gridLayout.setExtraSmall(ColumnPartition.valueOf(attribute.getValue()));
+    }
+  }
+
+  static final class SmallMapper extends Metadata {
+    private final TagAttribute attribute;
+
+    SmallMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      final UISegmentLayout gridLayout = (UISegmentLayout) instance;
+      gridLayout.setSmall(ColumnPartition.valueOf(attribute.getValue()));
+    }
+  }
+
+  static final class MediumMapper extends Metadata {
+    private final TagAttribute attribute;
+
+    MediumMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      final UISegmentLayout gridLayout = (UISegmentLayout) instance;
+      gridLayout.setMedium(ColumnPartition.valueOf(attribute.getValue()));
+    }
+  }
+
+  static final class LargeMapper extends Metadata {
+    private final TagAttribute attribute;
+
+    LargeMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      final UISegmentLayout gridLayout = (UISegmentLayout) instance;
+      gridLayout.setLarge(ColumnPartition.valueOf(attribute.getValue()));
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SheetStateChangeSourceRule.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SheetStateChangeSourceRule.java
new file mode 100644
index 0000000..5a1b97a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SheetStateChangeSourceRule.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.event.SheetStateChangeSource;
+import org.apache.myfaces.tobago.event.SheetStateChangeSource2;
+
+import javax.faces.event.ActionEvent;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+public class SheetStateChangeSourceRule extends MetaRule {
+
+  static final Class[] ACTION_LISTENER = new Class[]{ActionEvent.class};
+
+  public static final SheetStateChangeSourceRule INSTANCE = new SheetStateChangeSourceRule();
+
+  @Override
+  public Metadata applyRule(final String name, final TagAttribute attribute, final MetadataTarget metadataTarget) {
+    if (metadataTarget.isTargetInstanceOf(SheetStateChangeSource.class)) {
+      if ("stateChangeListener".equals(name)) {
+        return new SheetStateChangeListenerMapper(attribute);
+      }
+    }
+    return null;
+  }
+
+  static final class SheetStateChangeListenerMapper extends Metadata {
+
+    private final TagAttribute attribute;
+
+    public SheetStateChangeListenerMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      ((SheetStateChangeSource2) instance).setStateChangeListenerExpression(
+          attribute.getMethodExpression(ctx, null, SheetStateChangeSourceRule.ACTION_LISTENER));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SortActionSourceRule.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SortActionSourceRule.java
new file mode 100644
index 0000000..1f6b7c4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SortActionSourceRule.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.event.SortActionSource;
+import org.apache.myfaces.tobago.event.SortActionSource2;
+
+import javax.faces.event.ActionEvent;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+public class SortActionSourceRule extends MetaRule {
+
+  static final Class[] ACTION_LISTENER = new Class[]{ActionEvent.class};
+
+  public static final SortActionSourceRule INSTANCE = new SortActionSourceRule();
+
+  @Override
+  public Metadata applyRule(final String name, final TagAttribute attribute,
+                            final MetadataTarget metadataTarget) {
+    if (metadataTarget.isTargetInstanceOf(SortActionSource.class)) {
+      if ("sortActionListener".equals(name)) {
+        return new SortActionListenerMapper(attribute);
+      }
+    }
+    return null;
+  }
+
+  static final class SortActionListenerMapper extends Metadata {
+
+    private final TagAttribute attribute;
+
+    public SortActionListenerMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      ((SortActionSource2) instance).setSortActionListenerExpression(
+          attribute.getMethodExpression(ctx, null, SortActionSourceRule.ACTION_LISTENER));
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SpanHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SpanHandler.java
new file mode 100644
index 0000000..a43f9fd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SpanHandler.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.Attributes;
+
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagConfig;
+import javax.faces.view.facelets.TagHandler;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * @since 3.0.0
+ */
+public class SpanHandler extends TagHandler {
+
+  private final TagAttribute column;
+  private final TagAttribute row;
+
+  public SpanHandler(final TagConfig config) {
+    super(config);
+    column = getAttribute(Attributes.column.getName());
+    row = getAttribute(Attributes.row.getName());
+  }
+
+  @Override
+  public void apply(final FaceletContext faceletContext, UIComponent parent) throws IOException {
+    final Map<String, Object> attributes = parent.getAttributes();
+
+    if (column != null) {
+      if (column.isLiteral()) {
+        attributes.put(Attributes.column.getName(), Integer.valueOf(column.getValue()));
+      } else {
+        parent.setValueExpression(Attributes.column.getName(),
+            column.getValueExpression(faceletContext, Integer.TYPE));
+      }
+    }
+
+    if (row != null) {
+      if (row.isLiteral()) {
+        attributes.put(Attributes.row.getName(), Integer.valueOf(row.getValue()));
+      } else {
+        parent.setValueExpression(Attributes.row.getName(),
+            row.getValueExpression(faceletContext, Integer.TYPE));
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SuggestMethodRule.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SuggestMethodRule.java
new file mode 100644
index 0000000..0d419a1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SuggestMethodRule.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.InputSuggest2;
+import org.apache.myfaces.tobago.internal.component.AbstractUISuggest;
+import org.apache.myfaces.tobago.model.SuggestFilter;
+
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+public class SuggestMethodRule extends MetaRule {
+
+  public static final Class[] SUGGEST_METHOD = new Class[]{javax.faces.component.UIInput.class};
+
+  public static final SuggestMethodRule INSTANCE = new SuggestMethodRule();
+
+  @Override
+  public Metadata applyRule(final String name, final TagAttribute attribute, final MetadataTarget metadataTarget) {
+
+    if (metadataTarget.isTargetInstanceOf(InputSuggest2.class)) {
+      if ("suggestMethod".equals(name)) {
+        return new SuggestMethodMapper(attribute);
+      }
+    }
+    if (metadataTarget.isTargetInstanceOf(AbstractUISuggest.class)) {
+      if (attribute.isLiteral()) {
+        if ("filter".equals(name)) {
+          return new SuggestFilterMapper(attribute);
+        }
+      }
+    }
+    return null;
+  }
+
+  static final class SuggestMethodMapper extends Metadata {
+    private final TagAttribute attribute;
+
+    public SuggestMethodMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      ((InputSuggest2) instance).setSuggestMethodExpression(
+          attribute.getMethodExpression(ctx, null, SuggestMethodRule.SUGGEST_METHOD));
+    }
+  }
+
+  static final class SuggestFilterMapper extends Metadata {
+    private final TagAttribute attribute;
+
+    SuggestFilterMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      ((AbstractUISuggest) instance).setFilter(SuggestFilter.parse(attribute.getValue()));
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SupportsMarkupRule.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SupportsMarkupRule.java
new file mode 100644
index 0000000..fb0fc28
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/SupportsMarkupRule.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.context.Markup;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+public class SupportsMarkupRule extends MetaRule {
+
+  public static final SupportsMarkupRule INSTANCE = new SupportsMarkupRule();
+
+  @Override
+  public Metadata applyRule(final String name, final TagAttribute attribute, final MetadataTarget metadataTarget) {
+    if (metadataTarget.isTargetInstanceOf(Visual.class)) {
+      Attributes a = Attributes.valueOfFailsafe(name);
+      if (Attributes.markup == a) {
+        return new SupportsMarkupMapper(attribute);
+      }
+    }
+    return null;
+  }
+
+  static final class SupportsMarkupMapper extends Metadata {
+
+    private final TagAttribute attribute;
+
+    public SupportsMarkupMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      if (attribute.isLiteral()) {
+        ((Visual) instance).setMarkup(Markup.valueOf(attribute.getValue()));
+      } else {
+        final ValueExpression expression = attribute.getValueExpression(ctx, Object.class);
+        ((UIComponent) instance).setValueExpression(Attributes.markup.getName(), expression);
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TabChangeListenerHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TabChangeListenerHandler.java
new file mode 100644
index 0000000..814c870
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TabChangeListenerHandler.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.event.TabChangeListener;
+import org.apache.myfaces.tobago.event.TabChangeSource2;
+import org.apache.myfaces.tobago.event.ValueExpressionTabChangeListener;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.TagAttribute;
+import javax.faces.view.facelets.TagAttributeException;
+import javax.faces.view.facelets.TagConfig;
+import javax.faces.view.facelets.TagException;
+import javax.faces.view.facelets.TagHandler;
+import java.io.IOException;
+
+public class TabChangeListenerHandler extends TagHandler {
+
+  private Class listenerType;
+
+  private final TagAttribute type;
+
+  private final TagAttribute binding;
+
+
+  public TabChangeListenerHandler(final TagConfig config) {
+    super(config);
+    binding = getAttribute("binding");
+    type = getAttribute("type");
+    if (type != null) {
+      if (!type.isLiteral()) {
+        throw new TagAttributeException(tag, type, "Must be literal");
+      }
+      try {
+        this.listenerType = Class.forName(type.getValue());
+      } catch (final Exception e) {
+        throw new TagAttributeException(tag, type, e);
+      }
+    }
+  }
+
+  @Override
+  public void apply(final FaceletContext faceletContext, final UIComponent parent) throws IOException {
+    if (parent instanceof TabChangeSource2) {
+      // only process if parent was just created
+      if (parent.getParent() == null) {
+        final TabChangeSource2 changeSource = (TabChangeSource2) parent;
+        TabChangeListener listener = null;
+        ValueExpression valueExpression = null;
+        if (binding != null) {
+          valueExpression = binding.getValueExpression(faceletContext, TabChangeListener.class);
+          listener = (TabChangeListener) valueExpression.getValue(faceletContext);
+        }
+        if (listener == null) {
+          try {
+            listener = (TabChangeListener) listenerType.newInstance();
+          } catch (final Exception e) {
+            throw new TagAttributeException(tag, type, e.getCause());
+          }
+          if (valueExpression != null) {
+            valueExpression.setValue(faceletContext, listener);
+          }
+        }
+        if (valueExpression != null) {
+          changeSource.addTabChangeListener(
+              new ValueExpressionTabChangeListener(type.getValue(), valueExpression));
+        } else {
+          changeSource.addTabChangeListener(listener);
+        }
+      }
+    } else {
+      throw new TagException(tag, "Parent is not of type TabChangeSource, type is: " + parent);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TabChangeSourceRule.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TabChangeSourceRule.java
new file mode 100644
index 0000000..3c1c386
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TabChangeSourceRule.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.event.TabChangeEvent;
+import org.apache.myfaces.tobago.event.TabChangeSource2;
+
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRule;
+import javax.faces.view.facelets.Metadata;
+import javax.faces.view.facelets.MetadataTarget;
+import javax.faces.view.facelets.TagAttribute;
+
+public class TabChangeSourceRule extends MetaRule {
+  static final Class[] ACTION_LISTENER = new Class[]{TabChangeEvent.class};
+  public static final TabChangeSourceRule INSTANCE = new TabChangeSourceRule();
+
+  @Override
+  public Metadata applyRule(final String name, final TagAttribute attribute, final MetadataTarget metadataTarget) {
+    if (metadataTarget.isTargetInstanceOf(TabChangeSource2.class)) {
+      if ("tabChangeListener".equals(name)) {
+        return new TabChangeListenerMapper(attribute);
+      }
+    }
+    return null;
+  }
+
+  static final class TabChangeListenerMapper extends Metadata {
+
+    private final TagAttribute attribute;
+
+    public TabChangeListenerMapper(final TagAttribute attribute) {
+      this.attribute = attribute;
+    }
+
+    @Override
+    public void applyMetadata(final FaceletContext ctx, final Object instance) {
+      ((TabChangeSource2) instance).setTabChangeListenerExpression(
+          attribute.getMethodExpression(ctx, null, TabChangeSourceRule.ACTION_LISTENER));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TagMethodExpression.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TagMethodExpression.java
new file mode 100644
index 0000000..ea47861
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TagMethodExpression.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import javax.el.ELContext;
+import javax.el.ELException;
+import javax.el.MethodExpression;
+import javax.el.MethodInfo;
+import javax.el.MethodNotFoundException;
+import javax.el.PropertyNotFoundException;
+import javax.faces.FacesWrapper;
+import javax.faces.view.facelets.TagAttribute;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+/*
+ * Was copied from MyFaces-Impl.
+ */
+
+/**
+ * Jacob Hookom
+ */
+public final class TagMethodExpression extends MethodExpression
+    implements Externalizable, FacesWrapper<MethodExpression> {
+
+  private static final long serialVersionUID = 1L;
+
+  private String attr;
+  private MethodExpression orig;
+
+  public TagMethodExpression() {
+    super();
+  }
+
+  public TagMethodExpression(final TagAttribute attr, final MethodExpression orig) {
+    this.attr = attr.toString();
+    this.orig = orig;
+  }
+
+  @Override
+  public MethodInfo getMethodInfo(final ELContext context) {
+    try {
+      return this.orig.getMethodInfo(context);
+    } catch (final PropertyNotFoundException pnfe) {
+      throw new PropertyNotFoundException(this.attr + ": " + pnfe.getMessage(), pnfe.getCause());
+    } catch (final MethodNotFoundException mnfe) {
+      throw new MethodNotFoundException(this.attr + ": " + mnfe.getMessage(), mnfe.getCause());
+    } catch (final ELException e) {
+      throw new ELException(this.attr + ": " + e.getMessage(), e.getCause());
+    }
+  }
+
+  @Override
+  public Object invoke(final ELContext context, final Object[] params) {
+    try {
+      return this.orig.invoke(context, params);
+    } catch (final PropertyNotFoundException pnfe) {
+      throw new PropertyNotFoundException(this.attr + ": " + pnfe.getMessage(), pnfe.getCause());
+    } catch (final MethodNotFoundException mnfe) {
+      throw new MethodNotFoundException(this.attr + ": " + mnfe.getMessage(), mnfe.getCause());
+    } catch (final ELException e) {
+      throw new ELException(this.attr + ": " + e.getMessage(), e.getCause());
+    }
+  }
+
+  @Override
+  public String getExpressionString() {
+    return this.orig.getExpressionString();
+  }
+
+  public boolean equals(final Object obj) {
+    return this.orig.equals(obj);
+  }
+
+  public int hashCode() {
+    return this.orig.hashCode();
+  }
+
+  @Override
+  public boolean isLiteralText() {
+    return this.orig.isLiteralText();
+  }
+
+  @Override
+  public void writeExternal(final ObjectOutput out) throws IOException {
+    out.writeObject(this.orig);
+    out.writeUTF(this.attr);
+  }
+
+  @Override
+  public void readExternal(final ObjectInput in) throws IOException, ClassNotFoundException {
+    this.orig = (MethodExpression) in.readObject();
+    this.attr = in.readUTF();
+  }
+
+  public String toString() {
+    return this.attr + ": " + this.orig;
+  }
+
+  @Override
+  public MethodExpression getWrapped() {
+    return this.orig;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TobagoComponentHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TobagoComponentHandler.java
new file mode 100644
index 0000000..185a652
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TobagoComponentHandler.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.component.InputSuggest;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.event.SheetStateChangeSource;
+import org.apache.myfaces.tobago.event.SortActionSource;
+import org.apache.myfaces.tobago.event.TabChangeSource;
+import org.apache.myfaces.tobago.internal.component.AbstractUISegmentLayout;
+import org.apache.myfaces.tobago.internal.config.TobagoConfigImpl;
+
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+import javax.faces.view.facelets.ComponentConfig;
+import javax.faces.view.facelets.ComponentHandler;
+import javax.faces.view.facelets.FaceletContext;
+import javax.faces.view.facelets.MetaRuleset;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class TobagoComponentHandler extends ComponentHandler {
+
+  public TobagoComponentHandler(final ComponentConfig componentConfig) {
+    super(componentConfig);
+  }
+
+  @Override
+  protected MetaRuleset createMetaRuleset(final Class aClass) {
+    final MetaRuleset metaRuleset = super.createMetaRuleset(aClass);
+    if (SortActionSource.class.isAssignableFrom(aClass)) {
+      metaRuleset.addRule(SortActionSourceRule.INSTANCE);
+    }
+    if (AbstractUISegmentLayout.class.isAssignableFrom(aClass)) {
+      metaRuleset.addRule(SegmentLayoutRule.INSTANCE);
+    }
+    if (TabChangeSource.class.isAssignableFrom(aClass)) {
+      metaRuleset.addRule(TabChangeSourceRule.INSTANCE);
+    }
+    if (SheetStateChangeSource.class.isAssignableFrom(aClass)) {
+      metaRuleset.addRule(SheetStateChangeSourceRule.INSTANCE);
+    }
+    if (Visual.class.isAssignableFrom(aClass)) {
+      metaRuleset.addRule(SupportsMarkupRule.INSTANCE);
+    }
+    if (InputSuggest.class.isAssignableFrom(aClass)) {
+      metaRuleset.addRule(SuggestMethodRule.INSTANCE);
+    }
+
+    return metaRuleset;
+  }
+
+  @Override
+  public void onComponentPopulated(
+      final FaceletContext context, final UIComponent component, final UIComponent parent) {
+
+    // TODO call only if component was created
+    if (component instanceof EditableValueHolder) {
+      addDefaultValidators(context.getFacesContext(), (EditableValueHolder) component);
+    }
+  }
+
+  private void addDefaultValidators(final FacesContext context, final EditableValueHolder component) {
+    final TobagoConfigImpl tobagoConfig = (TobagoConfigImpl) TobagoConfig.getInstance(context);
+    final Map<String, String> validatorInfoMap = tobagoConfig.getDefaultValidatorInfo();
+    if (validatorInfoMap.isEmpty()) {
+      return;
+    }
+    final Validator[] validators = component.getValidators();
+    if (validators.length > 0) {
+      final Set<String> classNames = new HashSet<String>();
+      // collect classNames of validators
+      for (Validator validator : validators) {
+        classNames.add(validator.getClass().getName());
+      }
+      for (Map.Entry<String, String> entry : validatorInfoMap.entrySet()) {
+        if (!classNames.contains(entry.getValue())) {
+          component.addValidator(context.getApplication().createValidator((String) entry.getKey()));
+        }
+      }
+    } else {
+      for (String next : validatorInfoMap.keySet()) {
+        component.addValidator(context.getApplication().createValidator(next));
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TobagoValidateHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TobagoValidateHandler.java
new file mode 100644
index 0000000..e429465
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/facelets/TobagoValidateHandler.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.facelets;
+
+import org.apache.myfaces.tobago.validator.FileItemValidator;
+
+import javax.faces.view.facelets.MetaRuleset;
+import javax.faces.view.facelets.ValidatorConfig;
+import javax.faces.view.facelets.ValidatorHandler;
+
+public class TobagoValidateHandler extends ValidatorHandler {
+
+  public TobagoValidateHandler(final ValidatorConfig config) {
+    super(config);
+  }
+
+  @Override
+  protected MetaRuleset createMetaRuleset(final Class aClass) {
+    final MetaRuleset metaRuleset = super.createMetaRuleset(aClass);
+    if (FileItemValidator.class.isAssignableFrom(aClass)) {
+      metaRuleset.addRule(ContentTypeRule.INSTANCE);
+    }
+    return metaRuleset;
+  }
+}
+
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxInternalUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxInternalUtils.java
new file mode 100644
index 0000000..9058f5d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxInternalUtils.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.ajax;
+
+
+import org.apache.myfaces.tobago.internal.util.ResponseUtils;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * XXX this must be refactored, because of TOBAGO-1524 (see TOBAGO-1563)
+ * @deprecated
+ */
+@Deprecated
+public final class AjaxInternalUtils {
+
+  private AjaxInternalUtils() {
+  }
+
+  public static boolean redirect(final FacesContext facesContext, final String url) throws IOException {
+    redirect((HttpServletResponse) facesContext.getExternalContext().getResponse(), url);
+    facesContext.responseComplete();
+    return true;
+  }
+
+  public static void redirect(final HttpServletResponse response, final String url) throws IOException {
+    final Writer writer = response.getWriter();
+    final String contentType = "application/json; charset=UTF-8";
+    ResponseUtils.ensureContentTypeHeader(response, contentType);
+    ResponseUtils.ensureNoCacheHeader(response);
+    redirectInternal(writer, url);
+  }
+
+  private static void redirectInternal(final Writer writer, final String url) throws IOException {
+    writer.write("{\n  \"tobagoAjaxResponse\": true,\n");
+    writer.write("  \"responseCode\": 302,\n");
+    writer.write("  \"location\": \"");
+    writer.write(url);
+    writer.write("\"\n}\n");
+    writer.flush();
+  }
+
+  public static void requestNavigationReload(FacesContext facesContext) throws IOException {
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    final String pathPrefix = externalContext.getRequestContextPath() + externalContext.getRequestServletPath();
+    final HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
+    final String contentType = "application/json; charset=UTF-8";
+    ResponseUtils.ensureContentTypeHeader(response, contentType);
+    ResponseUtils.ensureNoCacheHeader(response);
+    final Writer writer = response.getWriter();
+    writer.write("{\n  \"tobagoAjaxResponse\": true,\n");
+    writer.write("  \"responseCode\": " + /*AjaxResponseRenderer.CODE_RELOAD_REQUIRED*/ 309 + ",\n");
+    writer.write("  \"location\": \"");
+    writer.write(pathPrefix + facesContext.getViewRoot().getViewId());
+    writer.write("\"\n}\n");
+    writer.flush();
+    facesContext.responseComplete();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java
new file mode 100644
index 0000000..ead8c5a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationListener.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.ajax;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+/**
+ * XXX this must be refactored, because of TOBAGO-1524 (see TOBAGO-1563)
+ * @deprecated
+ */
+@Deprecated
+public class AjaxNavigationListener implements PhaseListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AjaxNavigationListener.class);
+
+  @Override
+  public void afterPhase(final PhaseEvent phaseEvent) {
+    final FacesContext facesContext = phaseEvent.getFacesContext();
+    debug(facesContext);
+    if (!facesContext.getResponseComplete()) {
+      if (phaseEvent.getPhaseId() == PhaseId.RESTORE_VIEW) {
+        AjaxNavigationState.afterRestoreView(facesContext);
+      } else if (phaseEvent.getPhaseId() == PhaseId.INVOKE_APPLICATION) {
+        AjaxNavigationState.afterInvokeApplication(facesContext);
+      }
+    }
+    debug(facesContext);
+  }
+
+  @Override
+  public void beforePhase(final PhaseEvent phaseEvent) {
+    final FacesContext facesContext = phaseEvent.getFacesContext();
+    debug(facesContext);
+    if (!facesContext.getResponseComplete() && phaseEvent.getPhaseId() == PhaseId.RESTORE_VIEW) {
+      AjaxNavigationState.beforeRestoreView(facesContext);
+    }
+    debug(facesContext);
+  }
+
+  private void debug(FacesContext facesContext) {
+    if (LOG.isTraceEnabled()) {
+      LOG.trace("### debug getRenderResponse = {}", facesContext.getRenderResponse());
+      if (facesContext.getViewRoot() != null) {
+        LOG.trace("### debug getViewId = {}", facesContext.getViewRoot().getViewId());
+      }
+    }
+  }
+
+  @Override
+  public PhaseId getPhaseId() {
+    return PhaseId.ANY_PHASE;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java
new file mode 100644
index 0000000..2ca3bf5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/ajax/AjaxNavigationState.java
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.ajax;
+
+import org.apache.myfaces.tobago.util.AjaxUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.application.ViewExpiredException;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ExceptionQueuedEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * XXX this must be refactored, because of TOBAGO-1524 (see TOBAGO-1563)
+ * @deprecated
+ */
+@Deprecated
+public final class AjaxNavigationState {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AjaxNavigationState.class);
+
+  private static final String SESSION_KEY = "tobago-AjaxNavigationState";
+
+  private static final String VIEW_ROOT_KEY = "tobago-AjaxNavigationState-VIEW_ROOT_KEY";
+
+  private UIViewRoot viewRoot;
+
+  private Map<String, List<FacesMessage>> messages;
+
+  private AjaxNavigationState(final FacesContext facesContext) {
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    externalContext.getSessionMap().put(SESSION_KEY, this);
+    viewRoot = facesContext.getViewRoot();
+    messages = new HashMap<String, List<FacesMessage>>();
+    final Iterator<String> iterator = facesContext.getClientIdsWithMessages();
+    while (iterator.hasNext()) {
+      addFacesMessages(facesContext, iterator.next());
+    }
+    if (LOG.isTraceEnabled()) {
+      LOG.trace("Saved viewRoot.getViewId() = \"{}\"", viewRoot.getViewId());
+      for (final Map.Entry<String, List<FacesMessage>> entry : messages.entrySet()) {
+        for (final FacesMessage message : entry.getValue()) {
+          LOG.trace("Saved message \"{}\" : \"{}\"", entry.getKey(), message);
+        }
+      }
+    }
+  }
+
+  private void addFacesMessages(final FacesContext facesContext, final String clientId) {
+    final Iterator<FacesMessage> facesMessages = facesContext.getMessages(clientId);
+    while (facesMessages.hasNext()) {
+      addFacesMessage(clientId, facesMessages.next());
+    }
+  }
+
+  private void addFacesMessage(final String clientId, final FacesMessage facesMessage) {
+    List<FacesMessage> facesMessages = messages.get(clientId);
+    if (facesMessages == null) {
+      facesMessages = new ArrayList<FacesMessage>();
+      messages.put(clientId, facesMessages);
+    }
+    facesMessages.add(facesMessage);
+  }
+
+  private void restoreView(final FacesContext facesContext) {
+    facesContext.setViewRoot(viewRoot);
+    for (final Map.Entry<String, List<FacesMessage>> entry : messages.entrySet()) {
+      for (final FacesMessage facesMessage : entry.getValue()) {
+        facesContext.addMessage(entry.getKey(), facesMessage);
+      }
+    }
+    facesContext.renderResponse();
+    if (LOG.isTraceEnabled()) {
+      LOG.trace("Restored viewRoot.getViewId() = \"{}\"", viewRoot.getViewId());
+      for (final Map.Entry<String, List<FacesMessage>> entry : messages.entrySet()) {
+        for (final FacesMessage message : entry.getValue()) {
+          LOG.trace("Restored message \"{}\" : \"{}\"", entry.getKey(), message);
+        }
+      }
+    }
+
+  }
+
+  public static void storeIncomingView(final FacesContext facesContext) {
+    final UIViewRoot viewRoot = facesContext.getViewRoot();
+    if (LOG.isTraceEnabled()) {
+      if (viewRoot != null) {
+        LOG.trace("incoming viewId = '{}'", viewRoot.getViewId());
+      } else {
+        LOG.trace("incoming viewRoot is null");
+      }
+    }
+    facesContext.getExternalContext().getRequestMap().put(AjaxNavigationState.VIEW_ROOT_KEY, viewRoot);
+  }
+
+  public static boolean isNavigation(final FacesContext facesContext) {
+
+    final UIViewRoot viewRoot = facesContext.getViewRoot();
+    if (viewRoot != null) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("current viewId = '{}'", viewRoot.getViewId());
+      }
+    } else {
+      LOG.warn("current viewRoot is null");
+      return false;
+    }
+
+    final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
+    final UIViewRoot incomingViewRoot = (UIViewRoot) requestMap.get(VIEW_ROOT_KEY);
+    if (viewRoot != incomingViewRoot) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("requesting full page reload because of navigation to {} from {}",
+            viewRoot.getViewId(), incomingViewRoot.getViewId());
+      }
+      return true;
+    }
+    return false;
+  }
+
+  public static void beforeRestoreView(final FacesContext facesContext) {
+    if (facesContext.getExternalContext().getSessionMap().get(AjaxNavigationState.SESSION_KEY) != null) {
+      // restoreView phase and afterPhaseListener are executed even if renderResponse is set
+      // so we can't call navigationState.restoreView(...) here in before Phase
+      // set empty UIViewRoot to prevent executing restore state logic
+      facesContext.setViewRoot(new UIViewRoot());
+    }
+  }
+
+  public static void afterRestoreView(final FacesContext facesContext) {
+    if (isViewExpiredExceptionThrown(facesContext)) {
+      try {
+        facesContext.getExceptionHandler().handle();
+      } catch (ViewExpiredException e) {
+        LOG.debug("Caught: " + e.getMessage(), e);
+        try {
+          final ExternalContext externalContext = facesContext.getExternalContext();
+          final String url = externalContext.getRequestContextPath()
+                       + externalContext.getRequestServletPath() + externalContext.getRequestPathInfo();
+          AjaxInternalUtils.redirect(facesContext, url);
+          facesContext.responseComplete();
+        } catch (IOException e1) {
+          LOG.error("Caught: " + e1.getMessage(), e);
+        }
+      }
+    }
+
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    if (externalContext.getSessionMap().get(AjaxNavigationState.SESSION_KEY) == null) {
+      storeIncomingView(facesContext);
+    } else {
+      final AjaxNavigationState navigationState
+          = (AjaxNavigationState) externalContext.getSessionMap().remove(AjaxNavigationState.SESSION_KEY);
+      navigationState.restoreView(facesContext);
+      LOG.trace("force render requested navigation view");
+    }
+  }
+
+  private static boolean isViewExpiredExceptionThrown(FacesContext facesContext) {
+    final Iterator<ExceptionQueuedEvent> eventIterator
+        = facesContext.getExceptionHandler().getUnhandledExceptionQueuedEvents().iterator();
+    if (eventIterator.hasNext()) {
+      Throwable throwable = eventIterator.next().getContext().getException();
+      if (throwable instanceof ViewExpiredException) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static void afterInvokeApplication(FacesContext facesContext) {
+    if (AjaxUtils.isAjaxRequest(facesContext) && isNavigation(facesContext)) {
+      try {
+        facesContext.getExternalContext().getSessionMap().put(SESSION_KEY, new AjaxNavigationState(facesContext));
+        AjaxInternalUtils.requestNavigationReload(facesContext);
+      } catch (IOException e) {
+        LOG.error("Caught: " + e.getMessage(), e);
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/AttachedListStateWrapper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/AttachedListStateWrapper.java
new file mode 100644
index 0000000..d059779
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/AttachedListStateWrapper.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.behavior;
+
+import java.io.Serializable;
+import java.util.List;
+
+// todo: clean up (is a copy of MyFaces, but not all stuff is refactored)
+
+/**
+ * @since 3.0.0
+ */
+class AttachedListStateWrapper implements Serializable {
+
+  private static final long serialVersionUID = -3958718149793179776L;
+
+  private List<Object> wrappedStateList;
+
+  public AttachedListStateWrapper(List<Object> wrappedStateList) {
+    this.wrappedStateList = wrappedStateList;
+  }
+
+  public List<Object> getWrappedStateList() {
+    return wrappedStateList;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/AttachedStateWrapper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/AttachedStateWrapper.java
new file mode 100644
index 0000000..321b669
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/AttachedStateWrapper.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.behavior;
+
+import java.io.Serializable;
+
+// todo: clean up (is a copy of MyFaces, but not all stuff is refactored)
+
+class AttachedStateWrapper implements Serializable {
+
+  private static final long serialVersionUID = 4948301780259917764L;
+
+  private Class<?> clazz;
+  private Object wrappedStateObject;
+
+  /**
+   * @param clazz              null means wrappedStateObject is a List of state objects
+   */
+  public AttachedStateWrapper(Class<?> clazz, Object wrappedStateObject) {
+    if (wrappedStateObject != null && !(wrappedStateObject instanceof Serializable)) {
+      throw new IllegalArgumentException("Attached state for Object of type " + clazz + " (Class "
+          + wrappedStateObject.getClass().getName() + ") is not serializable");
+    }
+    this.clazz = clazz;
+    this.wrappedStateObject = wrappedStateObject;
+  }
+
+  public Class<?> getClazz() {
+    return clazz;
+  }
+
+  public Object getWrappedStateObject() {
+    return wrappedStateObject;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/DeltaStateHelper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/DeltaStateHelper.java
new file mode 100644
index 0000000..61cf1bc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/DeltaStateHelper.java
@@ -0,0 +1,763 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.behavior;
+
+import javax.el.ValueExpression;
+import javax.faces.component.StateHelper;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponentBase;
+import javax.faces.context.FacesContext;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+// todo: clean up (is a copy of MyFaces, but not all stuff is refactored)
+
+/**
+ * A delta enabled state holder implementing the StateHolder Interface.
+ * <p>
+ * Components implementing the PartalStateHolder interface have an initial state
+ * and delta states, the initial state is the one holding all root values
+ * and deltas store differences to the initial states
+ * </p>
+ * <p>
+ * For components not implementing partial state saving only the initial states are
+ * of importance, everything is stored and restored continously there
+ * </p>
+ * <p>
+ * The state helper seems to have three internal storage mechanisms:
+ * one being a list which stores plain values,
+ * one being a key value pair which stores key values in maps
+ * add serves the plain list type while put serves the
+ * key value type,
+ * the third is the value which has to be stored plainly as is!
+ * </p>
+ * In other words, this map can be seen as a composite map. It has two maps:
+ * initial state map and delta map.
+ * <p>
+ * If delta map is used (method component.initialStateMarked() ),
+ * base or initial state map cannot be changed, since all changes
+ * should be tracked on delta map.
+ * </p>
+ * <p>
+ * The intention of this class is just hold property values
+ * and do a clean separation between initial state and delta.
+ * </p>
+ * <p>
+ * The code from this class comes from a refactor of
+ * org.apache.myfaces.trinidad.bean.util.PropertyHashMap
+ * </p>
+ * <p>
+ * The context from this class comes and that should be taken into account
+ * is this:
+ * </p>
+ * <p>
+ * First request:
+ * </p>
+ * <ul>
+ * <li> A new template is created (using
+ * javax.faces.view.ViewDeclarationLanguage.buildView method)
+ * and component.markInitialState is called from its related TagHandler classes
+ * (see javax.faces.view.facelets.ComponentHandler ).
+ * When this method is executed, the component tree was populated from the values
+ * set in the facelet abstract syntax tree (or in other words composition of
+ * facelets templates). </li>
+ * <li> From this point all updates on the variables are considered "delta". </li>
+ * <li> SaveState, if initialStateMarked is true, only delta is saved. </li>
+ * </ul>
+ * <p>
+ * Second request (and next ones)
+ * </p>
+ * <ul>
+ * <li> A new template is created and component.markInitialState is called from
+ * its related TagHandler classes again. In this way, components like c:forEach
+ * or c:if, that add or remove components could notify about this and handle
+ * them properly (see javax.faces.view.StateManagementStrategy). Note that a
+ * component restored using this method is no different as the same component
+ * at the first request at the same time. </li>
+ * <li> A call for restoreState is done, passing the delta as object value. If no
+ * delta, the state is complete and no call is triggered. </li>
+ * <li> Lifecycle occur, changing the necessary stuff. </li>
+ * <li> SaveState, if initialStateMarked is true, only delta is saved. </li>
+ * </ul>
+ * <p>
+ * From the previous analysis, the following conclusions arise:
+ * <ul>
+ * <li>This class only needs to keep track of delta changes, so when
+ * restoreState/saveState is called, the right objects are passed.</li>
+ * <li>UIComponent.clearInitialState is used to reset the partial
+ * state holder to a non delta state, so the state to be saved by
+ * saveState is no longer a delta instead is a full state. If a call
+ * to clearInitialState occur it is not expected a call for
+ * UIComponent.markInitialState occur on the current request.</li>
+ * <li>The state is handled in the same way on UIData, so components
+ * inside UIData share its state on all rows. There is no way to save
+ * delta per row.</li>
+ * <li>The map backed by method put(Serializable,String,Object) is
+ * a replacement of UIComponentBase.attributesMap and UIComponent.bindings map.
+ * Note that on jsf 1.2, instances saved on attributesMap should not be
+ * StateHolder, but on jsf 2.0 it is possible to have it. PartialStateHolder
+ * instances are not handled in this map, or in other words delta state is not
+ * handled in this classes (markInitialState and clearInitialState is not propagated).</li>
+ * <li>The list backed by method add(Serializable,Object) should be (is not) a
+ * replacement of UIComponentBase.facesListeners, but note that StateHelper
+ * does not implement PartialStateHolder, and facesListener could have instances
+ * of that class that needs to be notified when UIComponent.markInitialState or
+ * UIComponent.clearInitialState is called, or in other words facesListeners
+ * should deal with PartialStateHolder instances.</li>
+ * <li>The list backed by method add(Serializable,Object) is
+ * a replacement of UIViewRoot.phaseListeners list. Note that instances of
+ * PhaseListener are not expected to implement StateHolder or PartialStateHolder.</li>
+ * </ul>
+ * </p>
+ * <p>
+ * NOTE: The current implementation of StateHelper on RI does not handle
+ * stateHolder values internally. To prevent problems when developers create
+ * custom components we should do this too. But anyway, the code that
+ * handle this case should be let here as comment, if some day this feature
+ * is provided. Note than stateHolder aware properties like converter,
+ * validator or listeners should deal with StateHolder or PartialStateHolder
+ * on component classes.
+ * <p>
+ * </p>
+ *
+ * @since 3.0.0
+ */
+class DeltaStateHelper<A extends EventBehavior> implements StateHelper {
+
+  /**
+   * We need to hold a component instance because:
+   * <p>
+   * - The component is the one who knows if we are on initial or delta mode
+   * - eval assume calls to component.ValueExpression
+   */
+  private A target;
+
+  /**
+   * This map holds the full current state
+   */
+  private Map<Serializable, Object> fullState;
+
+  /**
+   * This map only keep track of delta changes to be saved
+   */
+  private Map<Serializable, Object> deltas;
+
+  /**
+   * This map keep track of StateHolder keys, to be saved when
+   * saveState is called.
+   */
+  //private Set<Serializable> _stateHolderKeys;
+
+  private boolean transientBoolean = false;
+
+  public DeltaStateHelper(A target) {
+    super();
+    this.target = target;
+    fullState = new HashMap<Serializable, Object>();
+    deltas = null;
+    //_stateHolderKeys = new HashSet<Serializable>();
+  }
+
+  /**
+   * Used to create delta map on demand
+   *
+   * @return
+   */
+  private boolean createDeltas() {
+    if (isInitialStateMarked()) {
+      if (deltas == null) {
+        deltas = new HashMap<Serializable, Object>(2);
+      }
+      return true;
+    }
+
+    return false;
+  }
+
+  protected boolean isInitialStateMarked() {
+    return target.initialStateMarked();
+  }
+
+  public void add(Serializable key, Object value) {
+    if (createDeltas()) {
+      //Track delta case
+      Map<Object, Boolean> deltaListMapValues = (Map<Object, Boolean>) deltas
+          .get(key);
+      if (deltaListMapValues == null) {
+        deltaListMapValues = new DeltaStateHelper.InternalDeltaListMap<Object, Boolean>(
+            3);
+        deltas.put(key, deltaListMapValues);
+      }
+      deltaListMapValues.put(value, Boolean.TRUE);
+    }
+
+    //Handle change on full map
+    List<Object> fullListValues = (List<Object>) fullState.get(key);
+    if (fullListValues == null) {
+      fullListValues = new DeltaStateHelper.InternalList<Object>(3);
+      fullState.put(key, fullListValues);
+    }
+    fullListValues.add(value);
+  }
+
+  public Object eval(Serializable key) {
+    Object returnValue = fullState.get(key);
+    if (returnValue != null) {
+      return returnValue;
+    }
+    ValueExpression expression = target.getValueExpression(key
+        .toString());
+    if (expression != null) {
+      return expression.getValue(FacesContext.getCurrentInstance()
+          .getELContext());
+    }
+    return null;
+  }
+
+  public Object eval(Serializable key, Object defaultValue) {
+    Object returnValue = fullState.get(key);
+    if (returnValue != null) {
+      return returnValue;
+    }
+    ValueExpression expression = target.getValueExpression(key
+        .toString());
+    if (expression != null) {
+      return expression.getValue(FacesContext.getCurrentInstance()
+          .getELContext());
+    }
+    return defaultValue;
+  }
+
+  public Object get(Serializable key) {
+    return fullState.get(key);
+  }
+
+  public Object put(Serializable key, Object value) {
+    Object returnValue = null;
+    if (createDeltas()) {
+      if (deltas.containsKey(key)) {
+        returnValue = deltas.put(key, value);
+        fullState.put(key, value);
+      } else if (value == null && !fullState.containsKey(key)) {
+        returnValue = null;
+      } else {
+        deltas.put(key, value);
+        returnValue = fullState.put(key, value);
+      }
+    } else {
+            /*
+            if (value instanceof StateHolder)
+            {
+                _stateHolderKeys.add(key);
+            }
+            */
+      returnValue = fullState.put(key, value);
+    }
+    return returnValue;
+  }
+
+  public Object put(Serializable key, String mapKey, Object value) {
+    boolean returnSet = false;
+    Object returnValue = null;
+    if (createDeltas()) {
+      //Track delta case
+      Map<String, Object> mapValues = (Map<String, Object>) deltas
+          .get(key);
+      if (mapValues == null) {
+        mapValues = new DeltaStateHelper.InternalMap<String, Object>();
+        deltas.put(key, mapValues);
+      }
+      if (mapValues.containsKey(mapKey)) {
+        returnValue = mapValues.put(mapKey, value);
+        returnSet = true;
+      } else {
+        mapValues.put(mapKey, value);
+      }
+    }
+
+    //Handle change on full map
+    Map<String, Object> mapValues = (Map<String, Object>) fullState
+        .get(key);
+    if (mapValues == null) {
+      mapValues = new DeltaStateHelper.InternalMap<String, Object>();
+      fullState.put(key, mapValues);
+    }
+    if (returnSet) {
+      mapValues.put(mapKey, value);
+    } else {
+      returnValue = mapValues.put(mapKey, value);
+    }
+    return returnValue;
+  }
+
+  public Object remove(Serializable key) {
+    Object returnValue = null;
+    if (createDeltas()) {
+      if (deltas.containsKey(key)) {
+        // Keep track of the removed values using key/null pair on the delta map
+        returnValue = deltas.put(key, null);
+        fullState.remove(key);
+      } else {
+        // Keep track of the removed values using key/null pair on the delta map
+        deltas.put(key, null);
+        returnValue = fullState.remove(key);
+      }
+    } else {
+      returnValue = fullState.remove(key);
+    }
+    return returnValue;
+  }
+
+  public Object remove(Serializable key, Object valueOrKey) {
+    // Comment by lu4242 : The spec javadoc says if it is a Collection
+    // or Map deal with it. But the intention of this method is work
+    // with add(?,?) and put(?,?,?), this ones return instances of
+    // InternalMap and InternalList to prevent mixing, so to be
+    // consistent we'll cast to those classes here.
+
+    Object collectionOrMap = fullState.get(key);
+    Object returnValue = null;
+    if (collectionOrMap instanceof DeltaStateHelper.InternalMap) {
+      if (createDeltas()) {
+        returnValue = removeValueOrKeyFromMap(deltas, key,
+            valueOrKey, true);
+        removeValueOrKeyFromMap(fullState, key, valueOrKey, false);
+      } else {
+        returnValue = removeValueOrKeyFromMap(fullState, key,
+            valueOrKey, false);
+      }
+    } else if (collectionOrMap instanceof DeltaStateHelper.InternalList) {
+      if (createDeltas()) {
+        returnValue = removeValueOrKeyFromCollectionDelta(deltas,
+            key, valueOrKey);
+        removeValueOrKeyFromCollection(fullState, key, valueOrKey);
+      } else {
+        returnValue = removeValueOrKeyFromCollection(fullState, key,
+            valueOrKey);
+      }
+    }
+    return returnValue;
+  }
+
+  private static Object removeValueOrKeyFromCollectionDelta(
+      Map<Serializable, Object> stateMap, Serializable key,
+      Object valueOrKey) {
+    Object returnValue = null;
+    Map<Object, Boolean> c = (Map<Object, Boolean>) stateMap.get(key);
+    if (c != null) {
+      if (c.containsKey(valueOrKey)) {
+        returnValue = valueOrKey;
+      }
+      c.put(valueOrKey, Boolean.FALSE);
+    }
+    return returnValue;
+  }
+
+  private static Object removeValueOrKeyFromCollection(
+      Map<Serializable, Object> stateMap, Serializable key,
+      Object valueOrKey) {
+    Object returnValue = null;
+    Collection c = (Collection) stateMap.get(key);
+    if (c != null) {
+      if (c.remove(valueOrKey)) {
+        returnValue = valueOrKey;
+      }
+      if (c.isEmpty()) {
+        stateMap.remove(key);
+      }
+    }
+    return returnValue;
+  }
+
+  private static Object removeValueOrKeyFromMap(
+      Map<Serializable, Object> stateMap, Serializable key,
+      Object valueOrKey, boolean delta) {
+    if (valueOrKey == null) {
+      return null;
+    }
+
+    Object returnValue = null;
+    Map<String, Object> map = (Map<String, Object>) stateMap.get(key);
+    if (map != null) {
+      if (delta) {
+        // Keep track of the removed values using key/null pair on the delta map
+        returnValue = map.put((String) valueOrKey, null);
+      } else {
+        returnValue = map.remove(valueOrKey);
+      }
+
+      if (map.isEmpty()) {
+        //stateMap.remove(key);
+        stateMap.put(key, null);
+      }
+    }
+    return returnValue;
+  }
+
+  public boolean isTransient() {
+    return transientBoolean;
+  }
+
+  /**
+   * Serializing cod
+   * the serialized data structure consists of key value pairs unless the value itself is an internal array
+   * or a map in case of an internal array or map the value itself is another array with its initial value
+   * myfaces.InternalArray, myfaces.internalMap
+   * <p>
+   * the internal Array is then mapped to another array
+   * <p>
+   * the internal Map again is then mapped to a map with key value pairs
+   */
+  public Object saveState(FacesContext context) {
+    Map serializableMap = (isInitialStateMarked()) ? deltas : fullState;
+
+    if (serializableMap == null || serializableMap.size() == 0) {
+      return null;
+    }
+
+        /*
+        int stateHolderKeyCount = 0;
+        if (isInitalStateMarked())
+        {
+            for (Iterator<Serializable> it = _stateHolderKeys.iterator(); it.hasNext();)
+            {
+                Serializable key = it.next();
+                if (!deltas.containsKey(key))
+                {
+                    stateHolderKeyCount++;
+                }
+            }
+        }*/
+
+    Map.Entry<Serializable, Object> entry;
+    //entry == key, value, key, value
+    Object[] retArr = new Object[serializableMap.entrySet().size() * 2];
+    //Object[] retArr = new Object[serializableMap.entrySet().size() * 2 + stateHolderKeyCount];
+
+    Iterator<Map.Entry<Serializable, Object>> it = serializableMap.entrySet().iterator();
+    int cnt = 0;
+    while (it.hasNext()) {
+      entry = it.next();
+      retArr[cnt] = entry.getKey();
+
+      Object value = entry.getValue();
+
+      // The condition in which the call to saveAttachedState
+      // is to handle List, StateHolder or non Serializable instances.
+      // we check it here, to prevent unnecessary calls.
+      if (value instanceof StateHolder || value instanceof List || !(value instanceof Serializable)) {
+        Object savedValue = saveAttachedState(context, value);
+        retArr[cnt + 1] = savedValue;
+      } else {
+        retArr[cnt + 1] = value;
+      }
+      cnt += 2;
+    }
+
+        /*
+        if (isInitalStateMarked())
+        {
+            for (Iterator<Serializable> it2 = _stateHolderKeys.iterator(); it.hasNext();)
+            {
+                Serializable key = it2.next();
+                if (!deltas.containsKey(key))
+                {
+                    retArr[cnt] = key;
+                    Object value = fullState.get(key);
+                    if (value instanceof PartialStateHolder)
+                    {
+                        //Could contain delta, save it as _AttachedDeltaState
+                        PartialStateHolder holder = (PartialStateHolder) value;
+                        if (holder.isTransient())
+                        {
+                            retArr[cnt + 1] = null;
+                        }
+                        else
+                        {
+                            retArr[cnt + 1] = new _AttachedDeltaWrapper(value.getClass(), holder.saveState(context));
+                        }
+                    }
+                    else
+                    {
+                        //Save everything
+                        retArr[cnt + 1] = saveAttachedState(context, fullState.get(key));
+                    }
+                    cnt += 2;
+                }
+            }
+        }
+        */
+    return retArr;
+  }
+
+  public void restoreState(FacesContext context, Object state) {
+    if (state == null) {
+      return;
+    }
+
+    Object[] serializedState = (Object[]) state;
+
+    if (!isInitialStateMarked() && !fullState.isEmpty()) {
+      fullState.clear();
+      if (deltas != null) {
+        deltas.clear();
+      }
+    }
+
+    for (int cnt = 0; cnt < serializedState.length; cnt += 2) {
+      Serializable key = (Serializable) serializedState[cnt];
+      Object savedValue = restoreAttachedState(context,
+          serializedState[cnt + 1]);
+
+      if (isInitialStateMarked()) {
+        if (savedValue instanceof DeltaStateHelper.InternalDeltaListMap) {
+          for (Map.Entry<Object, Boolean> mapEntry : ((Map<Object, Boolean>) savedValue)
+              .entrySet()) {
+            boolean addOrRemove = mapEntry.getValue();
+            if (addOrRemove) {
+              //add
+              this.add(key, mapEntry.getKey());
+            } else {
+              //remove
+              this.remove(key, mapEntry.getKey());
+            }
+          }
+        } else if (savedValue instanceof DeltaStateHelper.InternalMap) {
+          for (Map.Entry<String, Object> mapEntry : ((Map<String, Object>) savedValue)
+              .entrySet()) {
+            this.put(key, mapEntry.getKey(), mapEntry.getValue());
+          }
+                /*
+                else if (savedValue instanceof _AttachedDeltaWrapper)
+                {
+                    AttachedStateWrapper wrapper = (AttachedStateWrapper) savedValue;
+                    //Restore delta state
+                    ((PartialStateHolder)fullState.get(key)).restoreState(context, wrapper.getWrappedStateObject());
+                    //Add this key as StateHolder key
+                    _stateHolderKeys.add(key);
+                }
+                */
+        } else {
+          put(key, savedValue);
+        }
+      } else {
+        put(key, savedValue);
+      }
+    }
+  }
+
+  public void setTransient(boolean transientValue) {
+    transientBoolean = transientValue;
+  }
+
+  //We use our own data structures just to make sure
+  //nothing gets mixed up internally
+  static class InternalMap<K, V> extends HashMap<K, V> implements StateHolder {
+    public InternalMap() {
+      super();
+    }
+
+    public InternalMap(int initialCapacity, float loadFactor) {
+      super(initialCapacity, loadFactor);
+    }
+
+    public InternalMap(Map<? extends K, ? extends V> m) {
+      super(m);
+    }
+
+    public InternalMap(int initialSize) {
+      super(initialSize);
+    }
+
+    public boolean isTransient() {
+      return false;
+    }
+
+    public void setTransient(boolean newTransientValue) {
+      // No op
+    }
+
+    public void restoreState(FacesContext context, Object state) {
+      Object[] listAsMap = (Object[]) state;
+      for (int cnt = 0; cnt < listAsMap.length; cnt += 2) {
+        this.put((K) listAsMap[cnt], (V) UIComponentBase.restoreAttachedState(context, listAsMap[cnt + 1]));
+      }
+    }
+
+    public Object saveState(FacesContext context) {
+      int cnt = 0;
+      Object[] mapArr = new Object[this.size() * 2];
+      for (Map.Entry<K, V> entry : this.entrySet()) {
+        mapArr[cnt] = entry.getKey();
+        Object value = entry.getValue();
+
+        if (value instanceof StateHolder || value instanceof List || !(value instanceof Serializable)) {
+          mapArr[cnt + 1] = saveAttachedState(context, value);
+        } else {
+          mapArr[cnt + 1] = value;
+        }
+        cnt += 2;
+      }
+      return mapArr;
+    }
+  }
+
+  /**
+   * Map used to keep track of list changes
+   */
+  static class InternalDeltaListMap<K, V> extends DeltaStateHelper.InternalMap<K, V> {
+
+    public InternalDeltaListMap() {
+      super();
+    }
+
+    public InternalDeltaListMap(int initialCapacity, float loadFactor) {
+      super(initialCapacity, loadFactor);
+    }
+
+    public InternalDeltaListMap(int initialSize) {
+      super(initialSize);
+    }
+
+    public InternalDeltaListMap(Map<? extends K, ? extends V> m) {
+      super(m);
+    }
+  }
+
+  static class InternalList<T> extends ArrayList<T> implements StateHolder {
+    public InternalList() {
+      super();
+    }
+
+    public InternalList(Collection<? extends T> c) {
+      super(c);
+    }
+
+    public InternalList(int initialSize) {
+      super(initialSize);
+    }
+
+    public boolean isTransient() {
+      return false;
+    }
+
+    public void setTransient(boolean newTransientValue) {
+    }
+
+    public void restoreState(FacesContext context, Object state) {
+      Object[] listAsArr = (Object[]) state;
+      //since all other options would mean dual iteration
+      //we have to do it the hard way
+      for (Object elem : listAsArr) {
+        add((T) restoreAttachedState(context, elem));
+      }
+    }
+
+    public Object saveState(FacesContext context) {
+      Object[] values = new Object[size()];
+      for (int i = 0; i < size(); i++) {
+        Object value = get(i);
+
+        if (value instanceof StateHolder || value instanceof List || !(value instanceof Serializable)) {
+          values[i] = saveAttachedState(context, value);
+        } else {
+          values[i] = value;
+        }
+      }
+      return values;
+    }
+  }
+
+  private static Object saveAttachedState(FacesContext context, Object attachedObject) {
+    if (context == null) {
+      throw new NullPointerException("context");
+    }
+
+    if (attachedObject == null) {
+      return null;
+    }
+    // StateHolder interface should take precedence over
+    // List children
+    if (attachedObject instanceof StateHolder) {
+      StateHolder holder = (StateHolder) attachedObject;
+      if (holder.isTransient()) {
+        return null;
+      }
+
+      return new AttachedStateWrapper(attachedObject.getClass(), holder.saveState(context));
+    } else if (attachedObject instanceof List) {
+      List<Object> lst = new ArrayList<Object>(((List<?>) attachedObject).size());
+      for (Object item : (List<?>) attachedObject) {
+        if (item != null) {
+          lst.add(saveAttachedState(context, item));
+        }
+      }
+
+      return new AttachedListStateWrapper(lst);
+    } else if (attachedObject instanceof Serializable) {
+      return attachedObject;
+    } else {
+      return new AttachedStateWrapper(attachedObject.getClass(), null);
+    }
+  }
+
+  private static Object restoreAttachedState(FacesContext context, Object stateObj) throws IllegalStateException {
+    if (context == null) {
+      throw new NullPointerException("context");
+    }
+    if (stateObj == null) {
+      return null;
+    }
+    if (stateObj instanceof AttachedListStateWrapper) {
+      List<Object> lst = ((AttachedListStateWrapper) stateObj).getWrappedStateList();
+      List<Object> restoredList = new ArrayList<Object>(lst.size());
+      for (Object item : lst) {
+        restoredList.add(restoreAttachedState(context, item));
+      }
+      return restoredList;
+    } else if (stateObj instanceof AttachedStateWrapper) {
+      Class<?> clazz = ((AttachedStateWrapper) stateObj).getClazz();
+      Object restoredObject;
+      try {
+        restoredObject = clazz.newInstance();
+      } catch (InstantiationException e) {
+        throw new RuntimeException("Could not restore StateHolder of type " + clazz.getName()
+            + " (missing no-args constructor?)", e);
+      } catch (IllegalAccessException e) {
+        throw new RuntimeException(e);
+      }
+      if (restoredObject instanceof StateHolder) {
+        AttachedStateWrapper wrapper = (AttachedStateWrapper) stateObj;
+        Object wrappedState = wrapper.getWrappedStateObject();
+
+        StateHolder holder = (StateHolder) restoredObject;
+        holder.restoreState(context, wrappedState);
+      }
+      return restoredObject;
+    } else {
+      return stateObj;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/EventBehavior.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/EventBehavior.java
new file mode 100644
index 0000000..163c464
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/behavior/EventBehavior.java
@@ -0,0 +1,315 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.behavior;
+
+import javax.el.ValueExpression;
+import javax.faces.component.StateHelper;
+import javax.faces.component.behavior.ClientBehaviorBase;
+import javax.faces.component.behavior.ClientBehaviorHint;
+import javax.faces.component.behavior.FacesBehavior;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AjaxBehaviorListener;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Set;
+
+// todo: clean up (is a copy of MyFaces, but not all stuff is refactored)
+
+/**
+ * @since 3.0.0
+ */
+@FacesBehavior(value = EventBehavior.BEHAVIOR_ID)
+public class EventBehavior extends ClientBehaviorBase {
+
+  /**
+   * not needed anymore but enforced by the spec
+   * theoretically a
+   *
+   * FacesBehavior(value = "javax.faces.behavior.Ajax")
+   * could do it
+   */
+  public static final String BEHAVIOR_ID = "org.apache.myfaces.tobago.behavior.Event";
+
+  private static final String ATTR_EXECUTE = "execute";
+  private static final String ATTR_ON_ERROR = "onerror";
+  private static final String ATTR_ON_EVENT = "onevent";
+  private static final String ATTR_RENDER = "render";
+  private static final String ATTR_DISABLED = "disabled";
+  private static final String ATTR_IMMEDIATE = "immediate";
+
+  /**
+   * special render and execute targets
+   */
+  private static final String VAL_FORM = "@form";
+  private static final String VAL_ALL = "@all";
+  private static final String VAL_THIS = "@this";
+  private static final String VAL_NONE = "@none";
+
+  private static final Collection<String> VAL_FORM_LIST = Collections.singletonList(VAL_FORM);
+  private static final Collection<String> VAL_ALL_LIST = Collections.singletonList(VAL_ALL);
+  private static final Collection<String> VAL_THIS_LIST = Collections.singletonList(VAL_THIS);
+  private static final Collection<String> VAL_NONE_LIST = Collections.singletonList(VAL_NONE);
+
+  //To enable delta state saving we need this one
+  private DeltaStateHelper<EventBehavior> stateHelper = null;
+
+  //private Map<String, ValueExpression> _valueExpressions
+  //        = new HashMap<String, ValueExpression>();
+
+  public EventBehavior() {
+    super();
+  }
+
+  public void addAjaxBehaviorListener(AjaxBehaviorListener listener) {
+    super.addBehaviorListener(listener);
+  }
+
+  public void removeAjaxBehaviorListener(AjaxBehaviorListener listener) {
+    removeBehaviorListener(listener);
+  }
+
+  public Collection<String> getExecute() {
+    // we have to evaluate the real value in this method,
+    // because the value of the ValueExpression might
+    // change (almost sure it does!)
+    return evalForCollection(ATTR_EXECUTE);
+  }
+
+  public void setExecute(Collection<String> execute) {
+    getStateHelper().put(ATTR_EXECUTE, execute);
+  }
+
+  public String getOnerror() {
+    return (String) getStateHelper().eval(ATTR_ON_ERROR);
+  }
+
+  public void setOnerror(String onError) {
+    getStateHelper().put(ATTR_ON_ERROR, onError);
+  }
+
+  public String getOnevent() {
+    return (String) getStateHelper().eval(ATTR_ON_EVENT);
+  }
+
+  public void setOnevent(String onEvent) {
+    getStateHelper().put(ATTR_ON_EVENT, onEvent);
+  }
+
+  public Collection<String> getRender() {
+    // we have to evaluate the real value in this method,
+    // because the value of the ValueExpression might
+    // change (almost sure it does!)
+    return evalForCollection(ATTR_RENDER);
+  }
+
+  public void setRender(Collection<String> render) {
+    getStateHelper().put(ATTR_RENDER, render);
+  }
+
+  @SuppressWarnings("unchecked")
+  public ValueExpression getValueExpression(String name) {
+    //return getValueExpressionMap().get(name);
+    if (name == null) {
+      throw new NullPointerException("name can not be null");
+    }
+
+    Map<String, Object> bindings = (Map<String, Object>) getStateHelper().
+        get(EventBehavior.PropertyKeys.bindings);
+    if (bindings != null) {
+      return (ValueExpression) bindings.get(name);
+    } else {
+      return null;
+    }
+  }
+
+  public void setValueExpression(String name, ValueExpression expression) {
+        /*
+        if (item == null)
+        {
+            getValueExpressionMap().remove(name);
+            getStateHelper().remove(name);
+        }
+        else
+        {
+            getValueExpressionMap().put(name, item);
+        }
+        */
+    if (name == null) {
+      throw new NullPointerException("name");
+    }
+
+    if (expression == null) {
+      getStateHelper().remove(EventBehavior.PropertyKeys.bindings, name);
+    } else {
+      getStateHelper().put(EventBehavior.PropertyKeys.bindings, name, expression);
+    }
+  }
+
+  public boolean isDisabled() {
+    Boolean retVal = (Boolean) getStateHelper().eval(ATTR_DISABLED);
+    retVal = (retVal == null) ? false : retVal;
+    return retVal;
+  }
+
+  public void setDisabled(boolean disabled) {
+    getStateHelper().put(ATTR_DISABLED, disabled);
+  }
+
+  public boolean isImmediate() {
+    Boolean retVal = (Boolean) getStateHelper().eval(ATTR_IMMEDIATE);
+    retVal = (retVal == null) ? false : retVal;
+    return retVal;
+  }
+
+  public void setImmediate(boolean immediate) {
+    getStateHelper().put(ATTR_IMMEDIATE, immediate);
+  }
+
+  public boolean isImmediateSet() {
+    return (getStateHelper().get(ATTR_IMMEDIATE) != null) || (getValueExpression(ATTR_IMMEDIATE) != null);
+  }
+
+  @Override
+  public Set<ClientBehaviorHint> getHints() {
+    return EnumSet.of(ClientBehaviorHint.SUBMITTING);
+  }
+
+  @Override
+  public String getRendererType() {
+    return BEHAVIOR_ID;
+  }
+
+  @Override
+  public void restoreState(FacesContext facesContext, Object o) {
+    if (o == null) {
+      return;
+    }
+    Object[] values = (Object[]) o;
+    if (values[0] != null) {
+      super.restoreState(facesContext, values[0]);
+    }
+    getStateHelper().restoreState(facesContext, values[1]);
+  }
+
+  private StateHelper getStateHelper() {
+    return getStateHelper(true);
+  }
+
+  /**
+   * returns a delta state saving enabled state helper
+   * for the current component
+   *
+   * @param create if true a state helper is created if not already existing
+   * @return an implementation of the StateHelper interface or null if none exists and create is set to false
+   */
+  private StateHelper getStateHelper(boolean create) {
+    if (stateHelper != null) {
+      return stateHelper;
+    }
+    if (create) {
+      stateHelper = new DeltaStateHelper<EventBehavior>(this);
+    }
+    return stateHelper;
+  }
+
+  @Override
+  public Object saveState(FacesContext facesContext) {
+    if (initialStateMarked()) {
+      Object parentSaved = super.saveState(facesContext);
+      Object stateHelperSaved = null;
+      StateHelper stateHelper = getStateHelper(false);
+      if (stateHelper != null) {
+        stateHelperSaved = stateHelper.saveState(facesContext);
+      }
+
+      if (parentSaved == null && stateHelperSaved == null) {
+        //No values
+        return null;
+      }
+      return new Object[]{parentSaved, stateHelperSaved};
+    } else {
+      Object[] values = new Object[2];
+      values[0] = super.saveState(facesContext);
+      StateHelper stateHelper = getStateHelper(false);
+      if (stateHelper != null) {
+        values[1] = stateHelper.saveState(facesContext);
+      }
+      return values;
+    }
+  }
+
+  //private Map<String, ValueExpression> getValueExpressionMap()
+  //{
+  //    return _valueExpressions;
+  //}
+
+  /**
+   * Invokes eval on the getStateHelper() and tries to get a
+   * Collection out of the result.
+   *
+   * @param attributeName
+   * @return
+   */
+  @SuppressWarnings("unchecked")
+  private Collection<String> evalForCollection(String attributeName) {
+    Object value = getStateHelper().eval(attributeName);
+    if (value == null) {
+      return Collections.<String>emptyList();
+    } else if (value instanceof Collection) {
+      return (Collection<String>) value;
+    } else if (value instanceof String) {
+      return getCollectionFromSpaceSplitString((String) value);
+    } else {
+      throw new IllegalArgumentException("Type " + value.getClass()
+          + " not supported for attribute " + attributeName);
+    }
+  }
+
+  /**
+   * Splits the String based on spaces and returns the
+   * resulting Strings as Collection.
+   *
+   * @param stringValue
+   * @return
+   */
+  private Collection<String> getCollectionFromSpaceSplitString(String stringValue) {
+    //@special handling for @all, @none, @form and @this
+    if (stringValue.equals(VAL_FORM)) {
+      return VAL_FORM_LIST;
+    } else if (stringValue.equals(VAL_ALL)) {
+      return VAL_ALL_LIST;
+    } else if (stringValue.equals(VAL_NONE)) {
+      return VAL_NONE_LIST;
+    } else if (stringValue.equals(VAL_THIS)) {
+      return VAL_THIS_LIST;
+    }
+
+    // not one of the "normal" values - split it and return the Collection
+    String[] arrValue = stringValue.split(" ");
+    return Arrays.asList(arrValue);
+  }
+
+  private enum PropertyKeys {
+    bindings,
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIBar.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIBar.java
new file mode 100644
index 0000000..aa4459e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIBar.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIBar extends AbstractUIPanelBase {
+
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIBox.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIBox.java
new file mode 100644
index 0000000..9f80f5c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIBox.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIBox extends AbstractUICollapsiblePanel {
+
+  public abstract String getLabel();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIButton.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIButton.java
new file mode 100644
index 0000000..705ccf7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIButton.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIButton extends AbstractUICommand {
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIButtons.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIButtons.java
new file mode 100644
index 0000000..878ab29
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIButtons.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIButtons extends AbstractUIPanelBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICollapsiblePanel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICollapsiblePanel.java
new file mode 100644
index 0000000..4238214
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICollapsiblePanel.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.model.CollapseMode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUICollapsiblePanel extends AbstractUIPanelBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUICollapsiblePanel.class);
+
+  private transient Boolean submittedCollapsed;
+
+  @Override
+  public void processDecodes(final FacesContext facesContext) {
+    if (isNormalLifecycle()) {
+      super.processDecodes(facesContext);
+    } else {
+      decode(facesContext);
+      final UIComponent bar = getFacet(Facets.BAR); // XXX is from Box or Section
+      if (bar != null) {
+        bar.processDecodes(facesContext);
+      }
+    }
+  }
+
+  @Override
+  public void processValidators(final FacesContext facesContext) {
+    if (isNormalLifecycle()) {
+      super.processValidators(facesContext);
+    } else {
+      final UIComponent bar = getFacet(Facets.BAR); // XXX is from Box or Section
+      if (bar != null) {
+        bar.processValidators(facesContext);
+      }
+    }
+  }
+
+  @Override
+  public void processUpdates(final FacesContext facesContext) {
+    if (isNormalLifecycle()) {
+      super.processUpdates(facesContext);
+    } else {
+      final UIComponent bar = getFacet(Facets.BAR); // XXX is from Box or Section
+      if (bar != null) {
+        bar.processUpdates(facesContext);
+      }
+    }
+  }
+
+  public boolean isNormalLifecycle() {
+    return getCollapsedMode() == CollapseMode.hidden || !isCollapsed();
+  }
+
+  public abstract boolean isCollapsed();
+
+  public abstract void setCollapsed(final boolean collapsed);
+
+  public abstract CollapseMode getCollapsedMode();
+
+  public void setSubmittedCollapsed(Boolean submittedCollapsed) {
+    this.submittedCollapsed = submittedCollapsed;
+  }
+
+  public void processState() {
+    if (submittedCollapsed != null) {
+      final ValueExpression valueExpression = getValueExpression(Attributes.collapsed.name());
+      if (valueExpression != null) {
+        valueExpression.setValue(FacesContext.getCurrentInstance().getELContext(), submittedCollapsed);
+      } else {
+        setCollapsed(submittedCollapsed);
+      }
+      submittedCollapsed = null;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumn.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumn.java
new file mode 100644
index 0000000..9cfcd5c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumn.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIColumn extends AbstractUIColumnBase {
+
+//  public abstract Measure getWidth();
+
+  public abstract String getLabel();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnBase.java
new file mode 100644
index 0000000..9f619a3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnBase.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.component.UIColumn;
+
+public abstract class AbstractUIColumnBase extends UIColumn implements Visual {
+
+  public boolean isResizable() {
+    return false;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnNode.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnNode.java
new file mode 100644
index 0000000..d6a22d0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnNode.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+/**
+ * @since Tobago 2.0.0
+ */
+public abstract class AbstractUIColumnNode extends AbstractUITreeNodeBase implements Visual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnSelector.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnSelector.java
new file mode 100644
index 0000000..5d43bd0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIColumnSelector.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIColumnSelector extends AbstractUIColumn {
+
+/* TBD
+  @Override
+  public Measure getWidth() {
+    return null;
+  }
+*/
+
+  @Override
+  public String getLabel() {
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICommand.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICommand.java
new file mode 100644
index 0000000..680623a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICommand.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.component.SupportsAccessKey;
+import org.apache.myfaces.tobago.component.UIEvent;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UICommand;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUICommand extends AbstractUICommandBase
+    implements SupportsAccessKey, Visual, ClientBehaviorHolder, SupportFieldId {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUICommand.class);
+
+  enum PropertyKeys {
+    disabled,
+  }
+
+  // todo: transient
+  private Boolean parentOfCommands;
+
+  public boolean isParentOfCommands() {
+    if (parentOfCommands == null) {
+      parentOfCommands = false;
+      for (UIComponent child : getChildren()) {
+        if (child.isRendered()
+            && !(child instanceof UIEvent)
+            && (child instanceof UICommand || child instanceof UIInput)) {
+          parentOfCommands = true;
+          break;
+        }
+      }
+    }
+    return parentOfCommands;
+  }
+
+  @Override
+  public abstract String getLabel();
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    if(isParentOfCommands()) {
+      return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "command";
+    } else {
+      return getClientId(facesContext);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICommandBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICommandBase.java
new file mode 100644
index 0000000..1e0f4ce
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUICommandBase.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.event.CollapsibleActionListener;
+import org.apache.myfaces.tobago.internal.util.AuthorizationHelper;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.el.MethodExpression;
+import javax.faces.component.UICommand;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PostAddToViewEvent;
+import java.util.Iterator;
+import java.util.List;
+
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
+public abstract class AbstractUICommandBase extends UICommand
+    implements ComponentSystemEventListener {
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) {
+    super.processEvent(event);
+
+    if (event instanceof PostAddToViewEvent) {
+      final List<AbstractUIOperation> list = ComponentUtils.findDescendantList(this, AbstractUIOperation.class);
+      for (AbstractUIOperation operation : list) {
+        addActionListener(new CollapsibleActionListener(operation.getFor()));
+      }
+    }
+  }
+
+  @Override
+  public void processDecodes(final FacesContext context) {
+    // Skip processing if our rendered flag is false
+    if (!isRendered()) {
+      return;
+    }
+
+    // Process this component itself
+    try {
+      decode(context);
+    } catch (final RuntimeException e) {
+      context.renderResponse();
+      throw e;
+    }
+
+    final Iterator kids = getFacetsAndChildren();
+    while (kids.hasNext()) {
+      final UIComponent kid = (UIComponent) kids.next();
+      kid.processDecodes(context);
+    }
+  }
+
+  @Override
+  public void queueEvent(final FacesEvent facesEvent) {
+    // fix for TOBAGO-262
+    super.queueEvent(facesEvent);
+    if (this == facesEvent.getSource()) {
+      if (isImmediate()) {
+        facesEvent.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
+      } else {
+        facesEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
+      }
+    }
+  }
+
+  @Override
+  public boolean isRendered() {
+    return super.isRendered() && isAllowed();
+  }
+
+  /**
+   Flag indicating that this element is disabled.
+   <br>Default: <code>false</code>
+   */
+  public boolean isDisabled() {
+
+    if (!isAllowed()) {
+      return true;
+    }
+
+    Boolean bool = (Boolean) getStateHelper().eval(AbstractUICommand.PropertyKeys.disabled);
+    if (bool != null) {
+      return bool;
+    }
+    return false;
+  }
+
+  private boolean isAllowed() {
+    final FacesContext facesContext = getFacesContext();
+    // todo: get from configuration tobago-config.xml
+    if (true) {
+      final AuthorizationHelper authorizationHelper = AuthorizationHelper.getInstance(facesContext);
+      final MethodExpression actionExpression = getActionExpression();
+      if (actionExpression != null) {
+        final boolean authorized =
+            authorizationHelper.isAuthorized(facesContext, actionExpression.getExpressionString());
+        if (!authorized) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  public void setDisabled(boolean disabled) {
+    getStateHelper().put(AbstractUICommand.PropertyKeys.disabled, disabled);
+  }
+
+  public abstract String getTarget();
+
+  public abstract boolean isTransition();
+
+  public abstract boolean isOmit();
+
+  public abstract void setOmit(boolean omit);
+
+  public abstract String getConfirmation();
+
+  public abstract String getLink();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java
new file mode 100644
index 0000000..20a3391
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIData.java
@@ -0,0 +1,314 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.Selectable;
+import org.apache.myfaces.tobago.model.SelectedState;
+import org.apache.myfaces.tobago.model.TreeDataModel;
+import org.apache.myfaces.tobago.model.TreeNodeDataModel;
+import org.apache.myfaces.tobago.model.TreePath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.FacesException;
+import javax.faces.component.ContextCallback;
+import javax.faces.component.UIComponent;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.context.FacesContext;
+import javax.faces.model.DataModel;
+import javax.swing.tree.TreeNode;
+import java.io.IOException;
+import java.util.List;
+
+public abstract class AbstractUIData extends javax.faces.component.UIData implements Visual {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUIData.class);
+
+  /**
+   * @deprecated Since 2.0.0. The marked concept has been replaced by "selected".
+   */
+  @Deprecated
+  public static final String SUFFIX_MARKED = "marked";
+  public static final String SUFFIX_SELECTED = "selected";
+  public static final String SUFFIX_EXPANDED = "expanded";
+
+  /**
+   * Only for tree model.
+   */
+  private boolean initialized;
+
+  /**
+   * Only for tree model, other models come from the parent UIData.
+   */
+  private TreeDataModel dataModel;
+
+  public boolean isTreeModel() {
+    init();
+    return dataModel != null;
+  }
+
+  public TreeDataModel getTreeDataModel() {
+    if (isTreeModel()) {
+      return dataModel;
+    } else {
+      LOG.warn("Not a tree model");
+      return null;
+    }
+  }
+
+  @Override
+  protected DataModel getDataModel() {
+    init();
+
+    if (dataModel != null) {
+      return dataModel;
+    } else {
+      return super.getDataModel();
+    }
+  }
+
+  private void init() {
+    if (!initialized) {
+      final Object value = getValue();
+      final boolean showRoot = isShowRoot();
+      createTreeDataModel(value, showRoot);
+
+      initialized = true;
+    }
+  }
+
+  /**
+   * @deprecated since Tobago 3.0.0, please use {@link #getSelectable}
+   */
+  public Selectable getSelectableAsEnum() {
+    return getSelectable();
+  }
+
+  public abstract Selectable getSelectable();
+
+  /**
+   * Creates the TreeDataModel which should be used.
+   * Override this method to use a custom model for an unsupported tree model.
+   * (Currently Tobago supports {@link TreeNode} out of the box.
+   *
+   * @param value    The reference to the data model
+   *                 (comes from the value attribute of the {@link javax.faces.component.UIData})
+   * @param showRoot comes from the showRoot attribute.
+   */
+  protected void createTreeDataModel(final Object value, final boolean showRoot) {
+    // TODO: use a factory
+    if (value instanceof TreeNode) {
+      dataModel = new TreeNodeDataModel((TreeNode) value, showRoot, getExpandedState());
+    }
+  }
+
+  @Override
+  public void encodeBegin(final FacesContext context) throws IOException {
+    initialized = false;
+    init();
+    if (dataModel != null) {
+      dataModel.reset();
+    }
+    super.encodeBegin(context);
+  }
+
+  public abstract ExpandedState getExpandedState();
+
+  public abstract SelectedState getSelectedState();
+
+  /**
+   * @deprecated The name of this method is ambiguous.
+   * You may use the inverse of {@link #isRowsUnlimited()}. Deprecated since 1.5.5.
+   */
+  @Deprecated
+  public boolean hasRows() {
+    return getRows() != 0;
+  }
+
+  public boolean isRowVisible() {
+    init();
+    if (dataModel != null) {
+      return dataModel.isRowVisible();
+    } else {
+      return super.getDataModel().isRowAvailable();
+    }
+  }
+
+  public String getRowClientId() {
+    init();
+    return dataModel != null ? dataModel.getRowClientId() : null;
+  }
+
+  public String getRowParentClientId() {
+    init();
+    return dataModel != null ? dataModel.getRowParentClientId() : null;
+  }
+
+  public abstract boolean isShowRoot();
+
+  public boolean isShowRootJunction() {
+    return false;
+  }
+
+  /**
+   * @return Is the (maximum) number of rows to display set to zero?
+   */
+  public boolean isRowsUnlimited() {
+    return getRows() == 0;
+  }
+
+  /**
+   * The value describes, if the UIData renderer creates container elements to hold the row information.
+   * This information is important for the TreeNodeRenderer to set the visible state in the output or not.
+   * Typically the Sheet returns true and a Tree returns false, because the sheet renders the HTML TR tags,
+   * the the sheet also is responsible for the visible state.
+   */
+  public boolean isRendersRowContainer() {
+    return false;
+  }
+
+  @Override
+  public boolean invokeOnComponent(
+      final FacesContext facesContext, final String clientId, final ContextCallback callback)
+      throws FacesException {
+    // we may need setRowIndex on UISheet
+    final int oldRowIndex = getRowIndex();
+    try {
+      final String sheetId = getClientId(facesContext);
+      if (clientId.startsWith(sheetId)) {
+        String idRemainder = clientId.substring(sheetId.length());
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("idRemainder = '" + idRemainder + "'");
+        }
+        if (idRemainder.matches("^:\\d+:.*")) {
+          idRemainder = idRemainder.substring(1);
+          final int idx = idRemainder.indexOf(":");
+          try {
+            final int rowIndex = Integer.parseInt(idRemainder.substring(0, idx));
+            if (LOG.isDebugEnabled()) {
+              LOG.debug("set rowIndex = '" + rowIndex + "'");
+            }
+            setRowIndex(rowIndex);
+          } catch (final NumberFormatException e) {
+            LOG.warn("idRemainder = '" + idRemainder + "'", e);
+          }
+        } else {
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("no match for '^:\\d+:.*'");
+          }
+        }
+      }
+
+      return super.invokeOnComponent(facesContext, clientId, callback);
+
+    } finally {
+      // we should reset rowIndex on UISheet
+      setRowIndex(oldRowIndex);
+    }
+  }
+
+  /**
+   * @return The TreePath of the current row index.
+   */
+  public TreePath getPath() {
+    if (isTreeModel()) {
+      return ((TreeDataModel) getDataModel()).getPath();
+    } else {
+      LOG.warn("Not a tree model");
+      return null;
+    }
+  }
+
+  /**
+   * @return Is the current row index representing a folder.
+   */
+  public boolean isFolder() {
+    if (isTreeModel()) {
+      return ((TreeDataModel) getDataModel()).isFolder();
+    } else {
+      LOG.warn("Not a tree model");
+      return false;
+    }
+  }
+
+  public List<Integer> getRowIndicesOfChildren() {
+    if (isTreeModel()) {
+      return dataModel.getRowIndicesOfChildren();
+    } else {
+      LOG.warn("Not a tree model");
+      return null;
+    }
+  }
+
+  /**
+   * This is, because we need to visit the UIRow for each row, which is not done in the base implementation.
+   */
+  @Override
+  public boolean visitTree(VisitContext context, VisitCallback callback) {
+
+    if (super.visitTree(context, callback)) {
+      return true;
+    }
+
+    // save the current row index
+    int oldRowIndex = getRowIndex();
+    // set row index to -1 to process the facets and to get the rowless clientId
+    setRowIndex(-1);
+    // push the Component to EL
+    pushComponentToEL(context.getFacesContext(), this);
+
+    try {
+      // iterate over the rows
+      int rowsToProcess = getRows();
+      // if getRows() returns 0, all rows have to be processed
+      if (rowsToProcess == 0) {
+        rowsToProcess = getRowCount();
+      }
+      int rowIndex = getFirst();
+      for (int rowsProcessed = 0; rowsProcessed < rowsToProcess; rowsProcessed++, rowIndex++) {
+        setRowIndex(rowIndex);
+        if (!isRowAvailable()) {
+          return false;
+        }
+        // visit the children of every child of the UIData that is an instance of UIColumn
+        for (int i = 0, childCount = getChildCount(); i < childCount; i++) {
+          UIComponent child = getChildren().get(i);
+          if (child instanceof AbstractUIRow) {
+            if (child.visitTree(context, callback)) {
+              return true;
+            }
+
+          }
+        }
+      }
+    } finally {
+      // pop the component from EL and restore the old row index
+      popComponentFromEL(context.getFacesContext());
+      setRowIndex(oldRowIndex);
+    }
+
+    // Return false to allow the visiting to continue
+    return false;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIDate.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIDate.java
new file mode 100644
index 0000000..d16df73
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIDate.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.internal.util.DateFormatUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.DateTimeConverter;
+import java.util.Date;
+
+public abstract class AbstractUIDate extends AbstractUIInput {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUIDate.class);
+
+  public String getPattern() {
+    final FacesContext facesContext = getFacesContext();
+    Converter converter = ComponentUtils.getConverter(facesContext, this, getSubmittedValue());
+    if (!(converter instanceof DateTimeConverter)) {
+      // hack for prototyping, if there is no value behind the component.
+      converter = facesContext.getApplication().createConverter(Date.class);
+      if (LOG.isWarnEnabled()) {
+        LOG.warn("Can't find a converter to get a pattern in component {}! Using default.",
+            getClientId(facesContext));
+      }
+    }
+    return DateFormatUtils.findPattern((DateTimeConverter) converter);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIEvent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIEvent.java
new file mode 100644
index 0000000..199ab7c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIEvent.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+
+public abstract class AbstractUIEvent extends AbstractUICommandBase {
+
+  public abstract ClientBehaviors getEvent();
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFigure.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFigure.java
new file mode 100644
index 0000000..d1a162f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFigure.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIFigure extends AbstractUIPanelBase {
+
+  public abstract String getLabel();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
new file mode 100644
index 0000000..cedb3e1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFile.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.util.MessageUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIInput;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.Part;
+
+public abstract class AbstractUIFile extends UIInput implements SupportsLabelLayout, Visual, ClientBehaviorHolder,
+    SupportFieldId {
+
+  @Override
+  public void validate(final FacesContext facesContext) {
+    if (isRequired()) {
+      if (getSubmittedValue() instanceof Part) {
+        final Part file = (Part) getSubmittedValue();
+        if (file == null || file.getName().length() == 0) {
+          addErrorMessage(facesContext);
+          setValid(false);
+        }
+      } else {
+        addErrorMessage(facesContext);
+        setValid(false);
+      }
+    }
+    super.validate(facesContext);
+  }
+
+  private void addErrorMessage(final FacesContext facesContext) {
+    MessageUtils.addMessage(
+        facesContext, this, FacesMessage.SEVERITY_ERROR, REQUIRED_MESSAGE_ID, new Object[]{getId()});
+  }
+
+  public abstract boolean isDisabled();
+
+  public abstract boolean isReadonly();
+
+  public abstract boolean isMultiple();
+
+  public abstract Integer getTabIndex();
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    if (getLabelLayout() == LabelLayout.skip) {
+      return getClientId(facesContext);
+    } else {
+      return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "real";
+    }
+  }
+
+  public boolean isLabelLayoutSkip() {
+    return getLabelLayout() == LabelLayout.skip;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlexLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlexLayout.java
new file mode 100644
index 0000000..d45175e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlexLayout.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+/**
+ * A layout manager which uses the CSS flex feature.
+ *
+ * @since 3.0.0
+ */
+public abstract class AbstractUIFlexLayout extends AbstractUILayoutBase implements Visual {
+
+  public static final String COMPONENT_FAMILY = "org.apache.myfaces.tobago.FlexLayout";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlowLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlowLayout.java
new file mode 100644
index 0000000..d8ed034
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFlowLayout.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+public abstract class AbstractUIFlowLayout extends AbstractUILayoutBase implements Visual {
+
+  public static final String COMPONENT_FAMILY = "org.apache.myfaces.tobago.FlowLayout";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIForm.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIForm.java
new file mode 100644
index 0000000..a8b61a8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIForm.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIForm extends AbstractUIFormBase {
+
+  public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.Form";
+
+  public abstract boolean isInline();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFormBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFormBase.java
new file mode 100644
index 0000000..4cc44db
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIFormBase.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.util.AjaxUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIForm;
+import javax.faces.context.FacesContext;
+import java.util.Iterator;
+
+public abstract class AbstractUIFormBase extends UIForm {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUIFormBase.class);
+
+  @Override
+  public void processDecodes(final FacesContext facesContext) {
+
+    // Process this component first
+    // to know the active actionId
+    // for the following children
+    decode(facesContext);
+
+    final Iterator kids = getFacetsAndChildren();
+    while (kids.hasNext()) {
+      final UIComponent kid = (UIComponent) kids.next();
+      kid.processDecodes(facesContext);
+    }
+  }
+
+  @Override
+  public void setSubmitted(final boolean b) {
+    super.setSubmitted(b);
+
+    // set submitted for all subforms
+    for (final AbstractUIForm subForm : ComponentUtils.findSubForms(this)) {
+      subForm.setSubmitted(b);
+    }
+  }
+
+  @Override
+  public void processValidators(final FacesContext facesContext) {
+    // if we're not the submitted form, only process subforms.
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("processValidators for form: {}", getClientId(facesContext));
+    }
+    if (isSubmitted() || AjaxUtils.isAjaxRequest(facesContext)) {
+      // Process all facets and children of this component
+      final Iterator kids = getFacetsAndChildren();
+      while (kids.hasNext()) {
+        final UIComponent kid = (UIComponent) kids.next();
+        kid.processValidators(facesContext);
+      }
+    } else {
+      for (final AbstractUIForm subForm : ComponentUtils.findSubForms(this)) {
+        subForm.processValidators(facesContext);
+      }
+    }
+  }
+
+  @Override
+  public void processUpdates(final FacesContext facesContext) {
+    // if we're not the submitted form, only process subforms.
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("processUpdates for form: {}", getClientId(facesContext));
+    }
+    if (isSubmitted() || AjaxUtils.isAjaxRequest(facesContext)) {
+      // Process all facets and children of this component
+      final Iterator kids = getFacetsAndChildren();
+      while (kids.hasNext()) {
+        final UIComponent kid = (UIComponent) kids.next();
+        kid.processUpdates(facesContext);
+      }
+    } else {
+      for (final AbstractUIForm subForm : ComponentUtils.findSubForms(this)) {
+        subForm.processUpdates(facesContext);
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIGridLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIGridLayout.java
new file mode 100644
index 0000000..448c435
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIGridLayout.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.internal.layout.Grid;
+import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
+import org.apache.myfaces.tobago.internal.layout.OriginCell;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PreRenderComponentEvent;
+import java.util.List;
+
+@ListenerFor(systemEventClass = PreRenderComponentEvent.class)
+public abstract class AbstractUIGridLayout extends AbstractUILayoutBase
+    implements Visual, ComponentSystemEventListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUIGridLayout.class);
+
+  public static final String COMPONENT_FAMILY = "org.apache.myfaces.tobago.GridLayout";
+
+  private Grid grid;
+
+  /**
+   * Initialize the grid and remove the current width and height values from the component, recursively.
+   */
+  @Override
+  public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
+
+    super.processEvent(event);
+
+    if (!isRendered()) {
+      return;
+    }
+
+    if (event instanceof PreRenderComponentEvent) {
+
+      grid = new Grid(LayoutTokens.parse(getColumns()), LayoutTokens.parse(getRows()));
+
+      final List<UIComponent> components = LayoutUtils.findLayoutChildren(this);
+      for (final UIComponent component : components) {
+        final int columnSpan = ComponentUtils.getIntAttribute(component, Attributes.column, 1);
+        final int rowSpan = ComponentUtils.getIntAttribute(component, Attributes.row, 1);
+        grid.add(new OriginCell(component), columnSpan, rowSpan);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("\n" + grid);
+        }
+      }
+    }
+  }
+
+  public abstract String getRows();
+
+  public abstract void setRows(String rows);
+
+  public abstract String getColumns();
+
+  public abstract void setColumns(String columns);
+
+  public abstract boolean isRigid();
+
+  public Grid getGrid() {
+    return grid;
+  }
+
+  public String toString() {
+    final StringBuilder builder = new StringBuilder();
+    builder.append(getClass().getSimpleName()).append("#");
+    builder.append(getClientId(FacesContext.getCurrentInstance()));
+    builder.append("\n");
+    if (grid != null) {
+      builder.append(StringUtils.repeat("  ", 4));
+      builder.append("horiz.: ");
+      final LayoutTokens rows = grid.getRows();
+      for (int i = 0; i < rows.getSize(); i++) {
+        if (i != 0) {
+          builder.append(StringUtils.repeat("  ", 4 + 4));
+        }
+        builder.append(rows.get(i));
+        builder.append("\n");
+      }
+      builder.append(StringUtils.repeat("  ", 4));
+      builder.append("verti.: ");
+      final LayoutTokens columns = grid.getColumns();
+      for (int i = 0; i < columns.getSize(); i++) {
+        if (i != 0) {
+          builder.append(StringUtils.repeat("  ", 4 + 4));
+        }
+        builder.append(columns.get(i));
+        builder.append("\n");
+      }
+    }
+    builder.setLength(builder.length() - 1);
+    return builder.toString();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIHidden.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIHidden.java
new file mode 100644
index 0000000..597162c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIHidden.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.UIInput;
+
+public abstract class AbstractUIHidden extends UIInput {
+
+  public abstract boolean isDisabled();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIImage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIImage.java
new file mode 100644
index 0000000..d57c80d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIImage.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.component.UIGraphic;
+
+public abstract class AbstractUIImage extends UIGraphic
+    implements Visual {
+
+  public abstract boolean isDisabled();
+  public abstract String getAlt();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIIn.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIIn.java
new file mode 100644
index 0000000..6631fde
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIIn.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUIIn extends AbstractUIInput {
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIInput.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIInput.java
new file mode 100644
index 0000000..650225b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIInput.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.component.SupportsAccessKey;
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUIInput extends javax.faces.component.UIInput
+    implements SupportsAccessKey, SupportsLabelLayout, Visual, ClientBehaviorHolder, SupportFieldId {
+
+  public abstract Integer getTabIndex();
+
+  public abstract boolean isFocus();
+
+  public abstract boolean isDisabled();
+
+  public abstract boolean isReadonly();
+
+  public abstract String getPlaceholder();
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    final UIComponent before = getFacet(Facets.before.name());
+    final UIComponent after = getFacet(Facets.after.name());
+
+    if (getLabelLayout() == LabelLayout.skip && before == null && after==null) {
+      return getClientId(facesContext);
+    } else {
+      return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "field";
+    }
+  }
+
+  public boolean isLabelLayoutSkip() {
+    return getLabelLayout() == LabelLayout.skip;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILabel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILabel.java
new file mode 100644
index 0000000..6907e88
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILabel.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+
+public abstract class AbstractUILabel
+    extends javax.faces.component.UIOutput implements Visual {
+
+  public String getLabel() {
+    final Converter converter = getConverter();
+    final Object value = getValue();
+    if (converter != null) {
+      return converter.getAsString(FacesContext.getCurrentInstance(), this, value);
+    } else if (value != null) {
+      return String.valueOf(value);
+    } else {
+      return null;
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILayoutBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILayoutBase.java
new file mode 100644
index 0000000..2122951
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILayoutBase.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.UIComponentBase;
+
+/**
+ *
+ */
+public abstract class AbstractUILayoutBase extends UIComponentBase {
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILink.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILink.java
new file mode 100644
index 0000000..cdef960
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILink.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.SupportsAccessKey;
+
+public abstract class AbstractUILink extends AbstractUICommand implements SupportsAccessKey {
+
+  public abstract java.lang.String getImage();
+
+  public abstract Integer getTabIndex();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILinks.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILinks.java
new file mode 100644
index 0000000..5333f8f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUILinks.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUILinks extends AbstractUIPanelBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIMessages.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIMessages.java
new file mode 100644
index 0000000..c6e9fe5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIMessages.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.commons.collections.iterators.SingletonIterator;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.layout.OrderBy;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+public abstract class AbstractUIMessages extends javax.faces.component.UIMessages
+    implements Visual {
+
+  public List<Item> createMessageList(final FacesContext facesContext) {
+
+    final Iterator clientIds;
+    if (isGlobalOnly()) {
+      clientIds = new SingletonIterator(null);
+    } else if (getFor() != null) {
+      clientIds = new SingletonIterator(getFor());
+    } else {
+      clientIds = facesContext.getClientIdsWithMessages();
+    }
+
+    final List<Item> messages = collectMessageList(facesContext, clientIds);
+
+    // todo
+    if (OrderBy.severity == getOrderBy()) {
+      // sort
+      Collections.sort(messages, new ItemComparator());
+    }
+    return messages;
+  }
+
+  private List<Item> collectMessageList(final FacesContext facesContext, final Iterator clientIds) {
+    final List<Item> messages = new ArrayList<Item>();
+    while (clientIds.hasNext()) {
+      final String clientId = (String) clientIds.next();
+      final Iterator<FacesMessage> i = facesContext.getMessages(clientId);
+      while (i.hasNext()) {
+        final FacesMessage facesMessage = i.next();
+        if (getMaxNumber() != null && messages.size() >= getMaxNumber()) {
+          return messages;
+        }
+        if (facesMessage.getSeverity().getOrdinal() < getMinSeverity().getOrdinal()) {
+          continue;
+        }
+        if (facesMessage.getSeverity().getOrdinal() > getMaxSeverity().getOrdinal()) {
+          continue;
+        }
+        messages.add(new Item(clientId, facesMessage));
+      }
+    }
+    return messages;
+  }
+
+  public static class Item {
+
+    private String clientId;
+    private FacesMessage facesMessage;
+
+    public Item(final String clientId, final FacesMessage facesMessage) {
+      this.clientId = clientId;
+      this.facesMessage = facesMessage;
+    }
+
+    public String getClientId() {
+      return clientId;
+    }
+
+    public void setClientId(final String clientId) {
+      this.clientId = clientId;
+    }
+
+    public FacesMessage getFacesMessage() {
+      return facesMessage;
+    }
+
+    public void setFacesMessage(final FacesMessage facesMessage) {
+      this.facesMessage = facesMessage;
+    }
+  }
+
+  public static class ItemComparator implements Comparator<Item> {
+    @Override
+    public int compare(final Item item1, final Item item2) {
+      return item2.getFacesMessage().getSeverity().getOrdinal() - item1.getFacesMessage().getSeverity().getOrdinal();
+    }
+  }
+
+  public abstract FacesMessage.Severity getMinSeverity();
+
+  public abstract FacesMessage.Severity getMaxSeverity();
+
+  public abstract Integer getMaxNumber();
+
+  public abstract OrderBy getOrderBy();
+
+/* TBD: if we support JSF 1.2 whe have to do something here.
+  public abstract String getFor();
+*/
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIObject.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIObject.java
new file mode 100644
index 0000000..e1308b2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIObject.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.component.UIOutput;
+
+public abstract class AbstractUIObject extends UIOutput implements Visual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIOperation.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIOperation.java
new file mode 100644
index 0000000..cdf2fa6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIOperation.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.UIComponentBase;
+
+public abstract class AbstractUIOperation extends UIComponentBase {
+
+  public abstract String getName();
+
+  public abstract String getFor();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIOut.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIOut.java
new file mode 100644
index 0000000..ac0a910
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIOut.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.component.UIOutput;
+
+public abstract class AbstractUIOut extends UIOutput implements SupportsLabelLayout, Visual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPage.java
new file mode 100644
index 0000000..df00e69
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPage.java
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.util.DebugUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.Iterator;
+
+public abstract class AbstractUIPage extends AbstractUIFormBase implements Visual, ClientBehaviorHolder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUIPage.class);
+
+  public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.Page";
+
+  public static final String FORM_ACCEPT_CHARSET = "utf-8";
+
+  private String formId;
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  public String getFormId(final FacesContext facesContext) {
+    if (formId == null) {
+      formId = getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "form";
+    }
+    return formId;
+  }
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext) throws IOException {
+    super.encodeBegin(facesContext);
+    final UIComponent layoutManager = LayoutUtils.getLayoutManager(this);
+    if (layoutManager != null) {
+      layoutManager.encodeBegin(facesContext);
+    }
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext) throws IOException {
+    final UIComponent layoutManager = LayoutUtils.getLayoutManager(this);
+    if (layoutManager != null) {
+      layoutManager.encodeChildren(facesContext);
+    } else {
+      super.encodeChildren(facesContext);
+    }
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext) throws IOException {
+    final UIComponent layoutManager = LayoutUtils.getLayoutManager(this);
+    if (layoutManager != null) {
+      layoutManager.encodeEnd(facesContext);
+    }
+    super.encodeEnd(facesContext);
+    if (LOG.isTraceEnabled()) {
+      LOG.trace(DebugUtils.toString(this.getParent(), 0));
+    }
+  }
+
+  @Override
+  public void processDecodes(final FacesContext context) {
+
+    decode(context);
+
+    markSubmittedForm(context);
+
+    // invoke processDecodes() on children
+    for (final Iterator kids = getFacetsAndChildren(); kids.hasNext();) {
+      final UIComponent kid = (UIComponent) kids.next();
+      kid.processDecodes(context);
+    }
+  }
+
+  public void markSubmittedForm(final FacesContext facesContext) {
+    // find the form of the action command and set submitted to it and all
+    // children
+
+    final UIViewRoot viewRoot = facesContext.getViewRoot();
+
+    // reset old submitted state
+    setSubmitted(false);
+
+    String sourceId = facesContext.getExternalContext().getRequestParameterMap().get("javax.faces.source");
+    UIComponent command = null;
+    if (sourceId != null) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("sourceId = '" + sourceId + "'");
+      }
+      command = viewRoot.findComponent(sourceId);
+    } else {
+      LOG.warn("No sourceId found!");
+    }
+
+    // TODO: remove this if block if proven this never happens anymore
+    if (command == null
+        && sourceId != null && sourceId.matches(".*:\\d+:.*")) {
+      // If currentActionId component was inside a sheet the id contains the
+      // rowIndex and is therefore not found here.
+      // We do not need the row here because we want just to find the
+      // related form, so removing the rowIndex will help here.
+      sourceId = sourceId.replaceAll(":\\d+:", ":");
+      try {
+        command = viewRoot.findComponent(sourceId);
+        //LOG.info("command = \"" + command + "\"", new Exception());
+      } catch (final Exception e) {
+        // ignore
+      }
+    }
+
+    if (LOG.isTraceEnabled()) {
+      LOG.trace(sourceId);
+      LOG.trace("command:{}", command);
+      LOG.trace(DebugUtils.toString(viewRoot, 0));
+    }
+
+    if (command != null) {
+      final AbstractUIFormBase form = ComponentUtils.findForm(command);
+      form.setSubmitted(true);
+
+      if (LOG.isTraceEnabled()) {
+        LOG.trace("form:{}", form);
+        LOG.trace(form.getClientId(facesContext));
+      }
+    } else {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Illegal actionId! Render response...");
+      }
+      facesContext.renderResponse();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPanel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPanel.java
new file mode 100644
index 0000000..1c104f9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPanel.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.behavior.ClientBehaviorHolder;
+
+public abstract class AbstractUIPanel extends AbstractUICollapsiblePanel implements ClientBehaviorHolder {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPanelBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPanelBase.java
new file mode 100644
index 0000000..296d0d4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPanelBase.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public abstract class AbstractUIPanelBase extends javax.faces.component.UIPanel implements Visual {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext) throws IOException {
+
+    super.encodeBegin(facesContext);
+
+    final UIComponent layoutManager = LayoutUtils.getLayoutManager(this);
+    if (layoutManager != null) {
+      layoutManager.encodeBegin(facesContext);
+    }
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext) throws IOException {
+
+    final UIComponent layoutManager = LayoutUtils.getLayoutManager(this);
+    if (layoutManager != null) {
+      layoutManager.encodeChildren(facesContext);
+    } else {
+      super.encodeChildren(facesContext);
+    }
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext) throws IOException {
+
+    final UIComponent layoutManager = LayoutUtils.getLayoutManager(this);
+    if (layoutManager != null) {
+      layoutManager.encodeEnd(facesContext);
+    }
+
+    super.encodeEnd(facesContext);
+  }
+
+  public abstract java.lang.String getTip();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPopup.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPopup.java
new file mode 100644
index 0000000..a5a6339
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIPopup.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.NamingContainer;
+
+public abstract class AbstractUIPopup extends AbstractUICollapsiblePanel
+    implements NamingContainer {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIProgress.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIProgress.java
new file mode 100644
index 0000000..d4a82be
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIProgress.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIOutput;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PreRenderComponentEvent;
+import javax.swing.BoundedRangeModel;
+
+@ListenerFor(systemEventClass = PreRenderComponentEvent.class)
+public abstract class AbstractUIProgress extends UIOutput
+    implements Visual, ComponentSystemEventListener, ClientBehaviorHolder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUIProgress.class);
+
+  private double rangeValue;
+  private double rangeMax;
+
+  public double getRangeValue() {
+    return rangeValue;
+  }
+
+  public double getRangeMax() {
+    return rangeMax;
+  }
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
+
+    super.processEvent(event);
+
+    if (event instanceof PreRenderComponentEvent) {
+      Object model = getValue();
+      if (model instanceof BoundedRangeModel) {
+        BoundedRangeModel m = (BoundedRangeModel) model;
+        rangeValue = (double) m.getValue();
+        rangeMax = (double) m.getMaximum();
+        final int min = m.getMinimum();
+        if (min != 0) {
+          rangeValue -= min;
+          rangeMax -= min;
+        }
+      } else {
+        if (model instanceof Number) {
+          rangeValue = ((Number) model).doubleValue();
+        } else if (model != null) {
+          rangeValue = Double.parseDouble("" + model);
+        }
+        if (getMax() != null) {
+          rangeMax = getMax();
+        } else {
+          rangeMax = 1.0;
+        }
+        if (rangeValue > rangeMax) {
+          rangeValue = rangeMax;
+        }
+      }
+    }
+  }
+
+  public abstract Double getMax();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIRow.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIRow.java
new file mode 100644
index 0000000..9fdb27a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIRow.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.behavior.ClientBehaviorHolder;
+
+public abstract class AbstractUIRow extends AbstractUIColumnBase implements ClientBehaviorHolder {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIScript.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIScript.java
new file mode 100644
index 0000000..8d6586e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUIScript.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.UIComponentBase;
+
+/**
+ * @since 3.0.0
+ */
+public abstract class AbstractUIScript extends UIComponentBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISection.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISection.java
new file mode 100644
index 0000000..6495a13
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISection.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIOutput;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public abstract class AbstractUISection extends AbstractUICollapsiblePanel {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUISection.class);
+
+  private int level;
+
+  public String getLabelToRender() {
+
+    final UIComponent facet = ComponentUtils.getFacet(this, Facets.label);
+    if (facet instanceof UIOutput) {
+      return String.valueOf(((UIOutput) facet).getValue());
+    } else if (facet != null) {
+      LOG.warn("Wrong type: " + facet.getClass().getName());
+    }
+
+    return getLabel();
+  }
+
+  public abstract String getLabel();
+
+  public abstract String getImage();
+
+  @Override
+  public void encodeBegin(FacesContext context) throws IOException {
+
+    if (getLevel() == 0) {
+      final AbstractUISection section = ComponentUtils.findAncestor(getParent(), AbstractUISection.class);
+      if (section != null) {
+        setLevel(section.getLevel() + 1);
+      } else {
+        setLevel(1);
+      }
+    }
+
+    super.encodeBegin(context);
+  }
+
+  public int getLevel() {
+    return level;
+  }
+
+  public void setLevel(int level) {
+    this.level = level;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISegmentLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISegmentLayout.java
new file mode 100644
index 0000000..6ac9c8d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISegmentLayout.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.layout.ColumnPartition;
+
+/**
+ * TODO
+ * @since 3.0.0
+ */
+public abstract class AbstractUISegmentLayout extends AbstractUILayoutBase implements Visual {
+
+  public static final String COMPONENT_FAMILY = "org.apache.myfaces.tobago.SegmentLayout";
+
+  @Override
+  public String toString() {
+    StringBuilder builder  =new StringBuilder(getClass().getSimpleName());
+    if (getExtraSmall() != null) {
+      builder.append("\n        extraSmall=");
+      builder.append(getExtraSmall());
+    }
+    if (getSmall() != null) {
+      builder.append("\n        small=");
+      builder.append(getSmall());
+    }
+    if (getMedium() != null) {
+      builder.append("\n        medium=");
+      builder.append(getMedium());
+    }
+    if (getLarge() != null) {
+      builder.append("\n        large=");
+      builder.append(getLarge());
+    }
+    return builder.toString();
+  }
+
+  public abstract ColumnPartition getExtraSmall();
+
+  public abstract ColumnPartition getSmall();
+
+  public abstract ColumnPartition getMedium();
+
+  public abstract ColumnPartition getLarge();
+
+  }
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectBooleanCheckbox.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectBooleanCheckbox.java
new file mode 100644
index 0000000..979dbcd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectBooleanCheckbox.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.component.SupportsAccessKey;
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.util.MessageUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UISelectBoolean;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUISelectBooleanCheckbox extends UISelectBoolean
+    implements Visual, ClientBehaviorHolder, SupportFieldId, SupportsAccessKey, SupportsLabelLayout {
+
+  @Override
+  public boolean isSelected() {
+    Object value = getSubmittedValue();
+    if (value == null) {
+      value = getValue();
+    }
+    if (value instanceof Boolean) {
+      return ((Boolean) value);
+    } else {
+      return value != null && Boolean.valueOf(value.toString());
+    }
+  }
+
+  @Override
+  protected void validateValue(final FacesContext facesContext, final Object convertedValue) {
+    if (isRequired()) {
+      if (convertedValue instanceof Boolean && !((Boolean) convertedValue)
+          // String: e. g. if there is no ValueExpression
+          || convertedValue instanceof String && !Boolean.parseBoolean((String) convertedValue)) {
+        MessageUtils.addMessage(
+            facesContext, this, FacesMessage.SEVERITY_ERROR, REQUIRED_MESSAGE_ID, new Object[]{getId()});
+        setValid(false);
+        return;
+      }
+    }
+    super.validateValue(facesContext, convertedValue);
+  }
+
+  public abstract boolean isDisabled();
+
+  public abstract boolean isReadonly();
+
+  public abstract boolean isFocus();
+
+  public abstract Integer getTabIndex();
+
+  public abstract String getLabel();
+
+  public abstract String getItemLabel();
+
+  public abstract void setItemLabel(String itemLabel);
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "field";
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectItem.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectItem.java
new file mode 100644
index 0000000..5210e65
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectItem.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UISelectItem;
+import javax.faces.component.UISelectMany;
+import javax.faces.context.FacesContext;
+
+public class AbstractUISelectItem extends UISelectItem {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUISelectItem.class);
+
+  private boolean itemValueLiteral;
+
+  @Override
+  public void setItemValue(final Object itemValue) {
+    if (itemValue instanceof String) {
+      itemValueLiteral = true;
+    } else if (itemValue == null) {
+      // ignore
+    } else {
+      LOG.warn("Unexpected type of literal for attribute 'itemValue': "
+          + "type=" + itemValue.getClass().getName() + " value='" + itemValue + "'.");
+    }
+    super.setItemValue(itemValue);
+  }
+
+  @Override
+  public Object getItemValue() {
+    if (itemValueLiteral && !(getParent() instanceof UISelectMany)) {
+      final Object converted = ComponentUtils.getConvertedValue(
+          FacesContext.getCurrentInstance(), getParent(), (String) super.getItemValue());
+      return converted;
+    } else {
+      return super.getItemValue();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyBase.java
new file mode 100644
index 0000000..09c5ef3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyBase.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.component.UISelectMany;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import java.util.Collection;
+
+public abstract class AbstractUISelectManyBase extends UISelectMany
+    implements Visual, SupportsLabelLayout, ClientBehaviorHolder {
+
+  @Override
+  public Object[] getSelectedValues() {
+    final Object value = getValue();
+    if (value instanceof Collection) {
+      return ((Collection) value).toArray();
+    } else {
+      return (Object[]) value;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyCheckbox.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyCheckbox.java
new file mode 100644
index 0000000..d4b52da
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyCheckbox.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUISelectManyCheckbox extends AbstractUISelectManyBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyListbox.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyListbox.java
new file mode 100644
index 0000000..c7e91ca
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyListbox.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUISelectManyListbox extends AbstractUISelectManyBase implements SupportFieldId {
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    if (getLabelLayout() == LabelLayout.skip) {
+      return getClientId(facesContext);
+    } else {
+      return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "field";
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyShuttle.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyShuttle.java
new file mode 100644
index 0000000..34aef1a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectManyShuttle.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUISelectManyShuttle extends AbstractUISelectManyBase implements SupportFieldId {
+
+  public abstract String getSelectedLabel();
+
+  public abstract String getUnselectedLabel();
+
+  public boolean hasLabel() {
+    return getSelectedLabel() != null || getUnselectedLabel() != null;
+  }
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    if (getLabelLayout() == LabelLayout.skip) {
+      return getClientId(facesContext);
+    } else {
+      return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "unselected";
+    }
+  }
+
+  public boolean isLabelLayoutSkip() {
+    return getLabelLayout() == LabelLayout.skip;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneBase.java
new file mode 100644
index 0000000..dba6153
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneBase.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.util.MessageUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIInput;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUISelectOneBase extends javax.faces.component.UISelectOne
+    implements Visual, SupportsLabelLayout, ClientBehaviorHolder {
+
+  public static final String MESSAGE_VALUE_REQUIRED = "tobago.SelectOne.MESSAGE_VALUE_REQUIRED";
+
+  @Override
+  public void validate(final FacesContext facesContext) {
+    if (isRequired()  && !isReadonly()) {
+      final Object submittedValue = getSubmittedValue();
+      if (submittedValue == null || "".equals(submittedValue)) {
+        if (getRequiredMessage() != null) {
+          final String requiredMessage = getRequiredMessage();
+          facesContext.addMessage(getClientId(facesContext), new FacesMessage(FacesMessage.SEVERITY_ERROR,
+              requiredMessage, requiredMessage));
+        } else {
+          MessageUtils.addMessage(facesContext, this, FacesMessage.SEVERITY_ERROR,
+              UIInput.REQUIRED_MESSAGE_ID, new Object[]{MessageUtils.getLabel(facesContext, this)});
+        }
+        setValid(false);
+      }
+    }
+    super.validate(facesContext);
+  }
+
+  public abstract boolean isReadonly();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneChoice.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneChoice.java
new file mode 100644
index 0000000..11a00f6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneChoice.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUISelectOneChoice extends AbstractUISelectOneBase implements SupportFieldId {
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    if (getLabelLayout() == LabelLayout.skip) {
+      return getClientId(facesContext);
+    } else {
+      return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "field";
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneListbox.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneListbox.java
new file mode 100644
index 0000000..b95886a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneListbox.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUISelectOneListbox extends AbstractUISelectOneBase implements SupportFieldId {
+
+  @Override
+  public String getFieldId(final FacesContext facesContext) {
+    if (getLabelLayout() == LabelLayout.skip) {
+      return getClientId(facesContext);
+    } else {
+      return getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "field";
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneRadio.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneRadio.java
new file mode 100644
index 0000000..6365146
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISelectOneRadio.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUISelectOneRadio extends AbstractUISelectOneBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISeparator.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISeparator.java
new file mode 100644
index 0000000..6a88657
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISeparator.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.component.UIComponentBase;
+
+public abstract class AbstractUISeparator extends UIComponentBase implements Visual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java
new file mode 100644
index 0000000..1e4967c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISheet.java
@@ -0,0 +1,570 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Sorter;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.event.PageActionEvent;
+import org.apache.myfaces.tobago.event.SheetStateChangeEvent;
+import org.apache.myfaces.tobago.event.SheetStateChangeListener;
+import org.apache.myfaces.tobago.event.SheetStateChangeSource2;
+import org.apache.myfaces.tobago.event.SortActionEvent;
+import org.apache.myfaces.tobago.event.SortActionSource2;
+import org.apache.myfaces.tobago.internal.layout.Grid;
+import org.apache.myfaces.tobago.internal.layout.OriginCell;
+import org.apache.myfaces.tobago.layout.AutoLayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.SelectedState;
+import org.apache.myfaces.tobago.model.SheetState;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ELContext;
+import javax.el.MethodExpression;
+import javax.el.ValueExpression;
+import javax.faces.component.UIColumn;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PreRenderComponentEvent;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+@ListenerFor(systemEventClass = PreRenderComponentEvent.class)
+public abstract class AbstractUISheet extends AbstractUIData
+    implements SheetStateChangeSource2, SortActionSource2, ClientBehaviorHolder, Visual,
+               ComponentSystemEventListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUISheet.class);
+
+  public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.Data";
+
+  public static final String SORTER_ID = "sorter";
+
+  private SheetState state;
+  private transient LayoutTokens columnLayout;
+  private transient boolean autoLayout;
+
+  private transient Grid headerGrid;
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext) throws IOException {
+    final SheetState state = getSheetState(facesContext);
+    final int first = state.getFirst();
+    if (first > -1 && (!hasRowCount() || first < getRowCount())) {
+      final ValueExpression expression = getValueExpression(Attributes.first.getName());
+      if (expression != null) {
+        expression.setValue(facesContext.getELContext(), first);
+      } else {
+        setFirst(first);
+      }
+    }
+
+    super.encodeBegin(facesContext);
+  }
+
+  public void setState(final SheetState state) {
+    this.state = state;
+  }
+
+  public SheetState getState() {
+    return getSheetState(FacesContext.getCurrentInstance());
+  }
+
+  public SheetState getSheetState(final FacesContext facesContext) {
+    if (state != null) {
+      return state;
+    }
+
+    final ValueExpression expression = getValueExpression(Attributes.state.getName());
+    if (expression != null) {
+      final ELContext elContext = facesContext.getELContext();
+      SheetState sheetState = (SheetState) expression.getValue(elContext);
+      if (sheetState == null) {
+        sheetState = new SheetState();
+        expression.setValue(elContext, sheetState);
+      }
+      return sheetState;
+    }
+
+    state = new SheetState();
+    return state;
+  }
+
+  public abstract String getColumns();
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
+
+    super.processEvent(event);
+
+    if (event instanceof PreRenderComponentEvent) {
+      final String columns = getColumns();
+      if (columns != null) {
+        columnLayout = LayoutTokens.parse(columns);
+      }
+
+      autoLayout = true;
+      if (columnLayout != null) {
+        for (LayoutToken layoutToken : columnLayout.getTokens()) {
+          if (!(layoutToken instanceof AutoLayoutToken)) {
+            autoLayout = false;
+            break;
+          }
+        }
+      }
+
+      LOG.debug("autoLayout={}", autoLayout);
+    }
+  }
+
+  public LayoutTokens getColumnLayout() {
+    return columnLayout;
+  }
+
+  public boolean isAutoLayout() {
+    return autoLayout;
+  }
+
+  /**
+   * @deprecated The name of this method is ambiguous.
+   * You may use {@link #getLastRowIndexOfCurrentPage()}. Deprecated since 1.5.5.
+   */
+  public int getLast() {
+    final int last = getFirst() + getRows();
+    return last < getRowCount() ? last : getRowCount();
+  }
+
+  /**
+   * The rowIndex of the last row on the current page plus one (because of zero based iterating).
+   * @throws IllegalArgumentException If the number of rows in the model returned
+   * by {@link #getRowCount()} is -1 (undefined).
+   */
+  public int getLastRowIndexOfCurrentPage() {
+    if (!hasRowCount()) {
+      throw new IllegalArgumentException(
+          "Can't determine the last row, because the row count of the model is unknown.");
+    }
+    if (isRowsUnlimited()) {
+      return getRowCount();
+    }
+    final int last = getFirst() + getRows();
+    return last < getRowCount() ? last : getRowCount();
+  }
+
+  /**
+   * @return returns the current page (based by 0).
+   */
+  public int getCurrentPage() {
+    final int rows = getRows();
+    if (rows == 0) {
+      // if the rows are unlimited, there is only one page
+      return 0;
+    }
+    final int first = getFirst();
+    if (hasRowCount() && first >= getRowCount()) {
+      return getPages() - 1; // last page
+    } else {
+      return (first / rows);
+    }
+  }
+  
+  /**
+   * @return returns the current page (based by 1).
+   * @deprecated Please use {@link #getCurrentPage()} which returns the value zero-based. Deprecated since 1.5.5.
+   */
+  @Deprecated
+  public int getPage() {
+    return getCurrentPage() + 1;
+  }
+
+  /**
+   * The number of pages to render.
+   * @throws IllegalArgumentException If the number of rows in the model returned
+   * by {@link #getRowCount()} is -1 (undefined).
+   */
+  public int getPages() {
+    if (isRowsUnlimited()) {
+      return 1;
+    }
+    if (!hasRowCount()) {
+      throw new IllegalArgumentException(
+          "Can't determine the number of pages, because the row count of the model is unknown.");
+    }
+    return (getRowCount() - 1) / getRows() + 1;
+  }
+
+  public List<UIComponent> getRenderedChildrenOf(final UIColumn column) {
+    final List<UIComponent> children = new ArrayList<UIComponent>();
+    for (final UIComponent kid : column.getChildren()) {
+      if (kid.isRendered()) {
+        children.add(kid);
+      }
+    }
+    return children;
+  }
+
+  /**
+   * @return Is the interval to display starting with the first row?
+   */
+  public boolean isAtBeginning() {
+    return getFirst() == 0;
+  }
+
+  /**
+   * @return Does the data model knows the number of rows?
+   */
+  public boolean hasRowCount() {
+    return getRowCount() != -1;
+  }
+
+  /**
+   * @return Should the paging controls be rendered? Either because of the need of paging or because
+   * the show is enforced by {@link #isShowPagingAlways()}
+   */
+  public boolean isPagingVisible() {
+    return isShowPagingAlways() || needMoreThanOnePage();
+  }
+
+  /**
+   * @return Is panging needed to display all rows? If the number of rows is unknown this method returns true.
+   */
+  public boolean needMoreThanOnePage() {
+    if (isRowsUnlimited()) {
+      return false;
+    } else if (!hasRowCount()) {
+      return true;
+    } else {
+      return getRowCount() > getRows();
+    }
+  }
+
+  public abstract boolean isShowPagingAlways();
+
+  public boolean isAtEnd() {
+    if (!hasRowCount()) {
+      final int old = getRowIndex();
+      setRowIndex(getFirst() + getRows() + 1);
+      final boolean atEnd = !isRowAvailable();
+      setRowIndex(old);
+      return atEnd;
+    } else {
+      return getFirst() >= getFirstRowIndexOfLastPage();
+    }
+  }
+
+  /**
+   * Determines the beginning of the last page in the model.
+   * If the number of rows to display on one page is unlimited, the value is 0 (there is only one page).
+   * @return The index of the first row of the last paging page.
+   * @throws IllegalArgumentException If the number of rows in the model returned
+   * by {@link #getRowCount()} is -1 (undefined).
+   */
+  public int getFirstRowIndexOfLastPage() {
+    if (isRowsUnlimited()) {
+      return 0;
+    } else if (!hasRowCount()) {
+      throw new IllegalArgumentException(
+          "Can't determine the last page, because the row count of the model is unknown.");
+    } else {
+      final int rows = getRows();
+      final int rowCount = getRowCount();
+      final int tail = rowCount % rows;
+      return rowCount - (tail != 0 ? tail : rows);
+    }
+  }
+
+  @Override
+  public void processUpdates(final FacesContext context) {
+    super.processUpdates(context);
+
+    final SheetState state = getSheetState(context);
+    if (state != null) {
+      final List<Integer> list = (List<Integer>) ComponentUtils.getAttribute(this, Attributes.selectedListString);
+      state.setSelectedRows(list != null ? list : Collections.<Integer>emptyList());
+      ComponentUtils.removeAttribute(this, Attributes.selectedListString);
+      ComponentUtils.removeAttribute(this, Attributes.scrollPosition);
+    }
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] saveState = new Object[2];
+    saveState[0] = super.saveState(context);
+    saveState[1] = state;
+    return saveState;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object savedState) {
+    final Object[] values = (Object[]) savedState;
+    super.restoreState(context, values[0]);
+    state = (SheetState) values[1];
+  }
+
+  public List<AbstractUIColumnBase> getAllColumns() {
+    ArrayList<AbstractUIColumnBase> result = new ArrayList<AbstractUIColumnBase>();
+    findColumns(this, result, true);
+    return result;
+  }
+
+  private void findColumns(final UIComponent component, final List<AbstractUIColumnBase> result, final boolean all) {
+    for (final UIComponent child : component.getChildren()) {
+      if (all || child.isRendered()) {
+        if (child instanceof AbstractUIColumnBase) {
+          result.add((AbstractUIColumnBase) child);
+        } else if (child instanceof AbstractUIData) {
+          // ignore columns of nested sheets
+        } else {
+          findColumns(child, result, all);
+        }
+      }
+    }
+  }
+
+  @Override
+  public void queueEvent(final FacesEvent facesEvent) {
+    final UIComponent parent = getParent();
+    if (parent == null) {
+      throw new IllegalStateException("Component is not a descendant of a UIViewRoot");
+    }
+
+    if (facesEvent.getComponent() == this
+        && (facesEvent instanceof SheetStateChangeEvent
+        || facesEvent instanceof PageActionEvent)) {
+      facesEvent.setPhaseId(PhaseId.INVOKE_APPLICATION);
+      parent.queueEvent(facesEvent);
+    } else {
+      super.queueEvent(facesEvent);
+    }
+  }
+
+  @Override
+  public void broadcast(final FacesEvent facesEvent) throws AbortProcessingException {
+    super.broadcast(facesEvent);
+    if (facesEvent instanceof SheetStateChangeEvent) {
+      final MethodExpression listener = getStateChangeListenerExpression();
+      listener.invoke(getFacesContext().getELContext(), new Object[]{facesEvent});
+    } else if (facesEvent instanceof PageActionEvent) {
+      if (facesEvent.getComponent() == this) {
+        final MethodExpression listener = getStateChangeListenerExpression();
+        if (listener != null) {
+          listener.invoke(getFacesContext().getELContext(), new Object[]{facesEvent});
+        }
+        performPaging((PageActionEvent) facesEvent);
+      }
+    } else if (facesEvent instanceof SortActionEvent) {
+      getSheetState(getFacesContext()).updateSortState((SortActionEvent) facesEvent);
+      sort(getFacesContext(), (SortActionEvent) facesEvent);
+    }
+  }
+
+  public void init(FacesContext facesContext) {
+    sort(facesContext, null);
+    layoutHeader();
+  }
+
+  private void layoutHeader() {
+    final UIComponent header = getHeader();
+    if (header == null) {
+      LOG.warn("This should not happen. Please file a bug in the issue tracker to reproduce this case.");
+      return;
+    }
+    final LayoutTokens tokens = new LayoutTokens();
+    final List<AbstractUIColumnBase> columns = getAllColumns();
+    for (final UIColumn column : columns) {
+      if (!(column instanceof AbstractUIRow)) {
+        tokens.addToken(RelativeLayoutToken.DEFAULT_INSTANCE);
+      }
+    }
+    final LayoutTokens rows = new LayoutTokens();
+    rows.addToken(AutoLayoutToken.INSTANCE);
+    final Grid grid = new Grid(tokens, rows);
+
+    for (final UIComponent child : header.getChildren()) {
+      if (child.isRendered()) {
+        int columnSpan = ComponentUtils.getIntAttribute(child, Attributes.column, 1);
+        int rowSpan = ComponentUtils.getIntAttribute(child, Attributes.row, 1);
+        grid.add(new OriginCell(child), columnSpan, rowSpan);
+      }
+    }
+    setHeaderGrid(grid);
+  }
+
+  protected void sort(FacesContext facesContext, SortActionEvent event) {
+    final SheetState sheetState = getSheetState(getFacesContext());
+    if (sheetState.isToBeSorted()) {
+      final MethodExpression expression = getSortActionListenerExpression();
+      if (expression != null) {
+        try {
+          if (event == null) {
+            // initial sorting
+            event =
+                new SortActionEvent(this, (UIColumn) findComponent(getSheetState(facesContext).getSortedColumnId()));
+          }
+          expression.invoke(facesContext.getELContext(), new Object[]{event});
+        } catch (Exception e) {
+          LOG.warn("Sorting not possible!", e);
+        }
+      } else {
+        new Sorter().perform(this);
+      }
+      sheetState.setToBeSorted(false);
+    }
+  }
+
+  @Override
+  public void addStateChangeListener(final SheetStateChangeListener listener) {
+    addFacesListener(listener);
+  }
+
+  @Override
+  public SheetStateChangeListener[] getStateChangeListeners() {
+    return (SheetStateChangeListener[]) getFacesListeners(SheetStateChangeListener.class);
+  }
+
+  @Override
+  public void removeStateChangeListener(final SheetStateChangeListener listener) {
+    removeFacesListener(listener);
+  }
+
+  @Override
+  public UIComponent findComponent(final String searchId) {
+    return super.findComponent(stripRowIndex(searchId));
+  }
+
+  public String stripRowIndex(String searchId) {
+    if (searchId.length() > 0 && Character.isDigit(searchId.charAt(0))) {
+      for (int i = 1; i < searchId.length(); ++i) {
+        final char c = searchId.charAt(i);
+        if (c == UINamingContainer.getSeparatorChar(getFacesContext())) {
+          searchId = searchId.substring(i + 1);
+          break;
+        }
+        if (!Character.isDigit(c)) {
+          break;
+        }
+      }
+    }
+    return searchId;
+  }
+
+  public void performPaging(final PageActionEvent pageEvent) {
+
+    int first;
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("action = '" + pageEvent.getAction().name() + "'");
+    }
+
+    switch (pageEvent.getAction()) {
+      case first:
+        first = 0;
+        break;
+      case prev:
+        first = getFirst() - getRows();
+        first = first < 0 ? 0 : first;
+        break;
+      case next:
+        if (hasRowCount()) {
+          first = getFirst() + getRows();
+          first = first > getRowCount() ? getFirstRowIndexOfLastPage() : first;
+        } else {
+          if (isAtEnd()) {
+            first = getFirst();
+          } else {
+            first = getFirst() + getRows();
+          }
+        }
+        break;
+      case last:
+        first = getFirstRowIndexOfLastPage();
+        break;
+      case toRow:
+        first = pageEvent.getValue() - 1;
+        if (hasRowCount() && first > getFirstRowIndexOfLastPage()) {
+          first = getFirstRowIndexOfLastPage();
+        } else if (first < 0) {
+          first = 0;
+        }
+        break;
+      case toPage:
+        final int pageIndex = pageEvent.getValue() - 1;
+        first = pageIndex * getRows();
+        if (hasRowCount() && first > getFirstRowIndexOfLastPage()) {
+          first = getFirstRowIndexOfLastPage();
+        } else if (first < 0) {
+          first = 0;
+        }
+        break;
+      default:
+        // may not happen
+        first = -1;
+    }
+
+    final ValueExpression expression = getValueExpression(Attributes.first.getName());
+    if (expression != null) {
+      expression.setValue(getFacesContext().getELContext(), first);
+    } else {
+      setFirst(first);
+    }
+
+    getState().setFirst(first);
+  }
+
+  @Override
+  public boolean isRendersRowContainer() {
+    return true;
+  }
+
+  public abstract boolean isShowHeader();
+
+  @Override
+  public ExpandedState getExpandedState() {
+    return getState().getExpandedState();
+  }
+
+  @Override
+  public SelectedState getSelectedState() {
+    return getState().getSelectedState();
+  }
+
+  public Grid getHeaderGrid() {
+    return headerGrid;
+  }
+
+  public void setHeaderGrid(final Grid headerGrid) {
+    this.headerGrid = headerGrid;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISuggest.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISuggest.java
new file mode 100644
index 0000000..4894af7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISuggest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.InputSuggest2;
+import org.apache.myfaces.tobago.model.SuggestFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponentBase;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUISuggest
+    extends UIComponentBase implements InputSuggest2, ClientBehaviorHolder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUISuggest.class);
+
+  public static final String COMPONENT_TYPE = "org.apache.myfaces.tobago.Suggest";
+  public static final String COMPONENT_FAMILY = "org.apache.myfaces.tobago.Suggest";
+
+  private transient String query;
+
+  @Override
+  public String getFamily() {
+    return COMPONENT_FAMILY;
+  }
+
+  public abstract Integer getDelay();
+
+  public abstract void setDelay(Integer delay);
+
+  public abstract Integer getMinimumCharacters();
+
+  public abstract void setMinimumCharacters(Integer minimumCharacters);
+
+  public abstract void setFilter(SuggestFilter filter);
+
+  public String getQuery() {
+    final ValueExpression expression = this.getValueExpression("query");
+    if (expression != null) {
+      try {
+        return (String) expression.getValue(FacesContext.getCurrentInstance().getELContext());
+      } catch (Exception e) {
+        LOG.error("", e);
+        return null;
+      }
+    } else {
+      return query;
+    }
+  }
+
+  public void setQuery(String query) {
+    final ValueExpression expression = this.getValueExpression("query");
+    if (expression != null) {
+      try {
+        expression.setValue(FacesContext.getCurrentInstance().getELContext(), query);
+      } catch (Exception e) {
+        LOG.error("query='" + query + "'", e);
+      }
+    } else {
+      this.query = query;
+    }
+  }
+
+  public abstract boolean isUpdate();
+
+  public abstract Integer getTotalCount();
+
+  public abstract Integer getMaximumItems();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITab.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITab.java
new file mode 100644
index 0000000..1b8d86a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITab.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import javax.faces.component.behavior.ClientBehaviorHolder;
+
+public abstract class AbstractUITab extends AbstractUIPanelBase implements ClientBehaviorHolder {
+
+  public abstract String getLabel();
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITabGroup.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITabGroup.java
new file mode 100644
index 0000000..191983b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITabGroup.java
@@ -0,0 +1,277 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.UITab;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.event.TabChangeEvent;
+import org.apache.myfaces.tobago.event.TabChangeListener;
+import org.apache.myfaces.tobago.event.TabChangeSource2;
+import org.apache.myfaces.tobago.model.SwitchType;
+import org.apache.myfaces.tobago.util.FacesELUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.MethodExpression;
+import javax.el.ValueExpression;
+import javax.faces.component.ActionSource2;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ActionListener;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.PhaseId;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class AbstractUITabGroup extends AbstractUIPanelBase
+    implements TabChangeSource2, ActionSource2, ClientBehaviorHolder, Visual {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractUITabGroup.class);
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext) throws IOException {
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext) throws IOException {
+    super.encodeEnd(facesContext);
+    setRenderedIndex(getSelectedIndex());
+  }
+
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void queueEvent(final FacesEvent event) {
+    if (this == event.getSource()) {
+      if (isImmediate() || getSwitchType() == SwitchType.client) {
+        // if switch type client event is always immediate
+        event.setPhaseId(PhaseId.APPLY_REQUEST_VALUES);
+      } else {
+        event.setPhaseId(PhaseId.INVOKE_APPLICATION);
+      }
+    }
+    super.queueEvent(event);
+  }
+
+  public AbstractUITab[] getTabs() {
+    final List<AbstractUITab> tabs = new ArrayList<AbstractUITab>();
+    for (final UIComponent kid : getChildren()) {
+      if (kid instanceof AbstractUITab) {
+        //if (kid.isRendered()) {
+        tabs.add((AbstractUITab) kid);
+        //}
+      } else {
+        LOG.error("Invalid component in UITabGroup: " + kid);
+      }
+    }
+    return tabs.toArray(new AbstractUITab[tabs.size()]);
+  }
+
+  public AbstractUITab getActiveTab() {
+    return getTab(getSelectedIndex());
+  }
+
+
+  @Override
+  public void processDecodes(final FacesContext context) {
+    if (!(getSwitchType() == SwitchType.client)) {
+
+      if (context == null) {
+        throw new NullPointerException("context");
+      }
+      if (!isRendered()) {
+        return;
+      }
+      int index = 0;
+      for (final UIComponent child : getChildren()) {
+        if (child instanceof UITab) {
+          final UITab tab = (UITab) child;
+          if (tab.isRendered()) {
+            if (getRenderedIndex() == index) {
+              tab.processDecodes(context);
+            }
+          }
+          index++;
+        }
+      }
+//      final AbstractUIPanelBase renderedTab = getRenderedTab();
+//      renderedTab.processDecodes(context);
+      for (final UIComponent facet : getFacets().values()) {
+        facet.processDecodes(context);
+      }
+      try {
+        decode(context);
+      } catch (final RuntimeException e) {
+        context.renderResponse();
+        throw e;
+      }
+    } else {
+      super.processDecodes(context);
+    }
+  }
+
+  @Override
+  public void processValidators(final FacesContext context) {
+    if (!(getSwitchType() == SwitchType.client)) {
+      if (!isRendered()) {
+        return;
+      }
+      final AbstractUITab renderedTab = getRenderedTab();
+      renderedTab.processValidators(context);
+      for (final UIComponent facet : getFacets().values()) {
+        facet.processValidators(context);
+      }
+    } else {
+      super.processValidators(context);
+    }
+  }
+
+  @Override
+  public void processUpdates(final FacesContext context) {
+    if (!(getSwitchType() == SwitchType.client)) {
+      if (!isRendered()) {
+        return;
+      }
+      final AbstractUITab renderedTab = getRenderedTab();
+      renderedTab.processUpdates(context);
+      for (final UIComponent facet : getFacets().values()) {
+        facet.processUpdates(context);
+      }
+
+    } else {
+      super.processUpdates(context);
+    }
+  }
+
+  @Override
+  public void broadcast(final FacesEvent facesEvent) throws AbortProcessingException {
+    super.broadcast(facesEvent);
+    if (facesEvent instanceof TabChangeEvent && facesEvent.getComponent() == this) {
+      final TabChangeEvent event = (TabChangeEvent) facesEvent;
+
+      final MethodExpression methodExpression = getTabChangeListenerExpression();
+      if (methodExpression != null) {
+        FacesELUtils.invokeMethodExpression(FacesContext.getCurrentInstance(), methodExpression, facesEvent);
+      }
+
+// switched off, because this is already called in super.broadcast()
+//      final ActionListener[] actionListeners = getActionListeners();
+//      for (ActionListener listener : actionListeners) {
+//        listener.processAction(event);
+//      }
+
+      // XXX is this needed?
+      if (!(getSwitchType() == SwitchType.client)) {
+        final ActionListener defaultActionListener = getFacesContext().getApplication().getActionListener();
+        if (defaultActionListener != null) {
+          defaultActionListener.processAction(event);
+        }
+      }
+      final Integer index = event.getNewTabIndex();
+      final ValueExpression expression = getValueExpression(Attributes.selectedIndex.getName());
+      if (expression != null) {
+        expression.setValue(getFacesContext().getELContext(), index);
+      } else {
+        setSelectedIndex(index);
+      }
+    }
+  }
+
+  @Override
+  public void addTabChangeListener(final TabChangeListener listener) {
+    if (LOG.isWarnEnabled() && getSwitchType() == SwitchType.client) {
+      LOG.warn("Adding TabChangeListener to client side TabGroup!");
+    }
+    addFacesListener(listener);
+  }
+
+  @Override
+  public void removeTabChangeListener(final TabChangeListener listener) {
+    removeFacesListener(listener);
+  }
+
+  @Override
+  public TabChangeListener[] getTabChangeListeners() {
+    return (TabChangeListener[]) getFacesListeners(TabChangeListener.class);
+  }
+
+  public abstract Integer getRenderedIndex();
+
+  public abstract void setRenderedIndex(Integer index);
+
+  public abstract Integer getSelectedIndex();
+
+  public abstract void setSelectedIndex(Integer index);
+
+  public abstract SwitchType getSwitchType();
+
+  private AbstractUITab getTab(final int index) {
+    int i = 0;
+    for (final UIComponent component : getChildren()) {
+      if (component instanceof AbstractUITab) {
+        if (i == index) {
+          return (AbstractUITab) component;
+        }
+        i++;
+      } else {
+        LOG.error("Invalid component in UITabGroup: " + component);
+      }
+    }
+    LOG.error("Found no component with index: " + index + " childCount: " + getChildCount());
+    return null;
+  }
+
+  private AbstractUITab getRenderedTab() {
+    return getTab(getRenderedIndex());
+  }
+
+
+  /**
+   * @since 1.5.0
+   */
+  @Override
+  public void addActionListener(final ActionListener listener) {
+    addFacesListener(listener);
+  }
+
+  /**
+   * @since 1.5.0
+   */
+  @Override
+  public ActionListener[] getActionListeners() {
+    return (ActionListener[]) getFacesListeners(ActionListener.class);
+  }
+
+  /**
+   * @since 1.5.0
+   */
+  @Override
+  public void removeActionListener(final ActionListener listener) {
+    removeFacesListener(listener);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITextarea.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITextarea.java
new file mode 100644
index 0000000..52f0f81
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITextarea.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUITextarea extends AbstractUIInput {
+
+  @Override
+  public String getPlaceholder() {
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITree.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITree.java
new file mode 100644
index 0000000..4f92d0d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITree.java
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.ScrollPosition;
+import org.apache.myfaces.tobago.model.SelectedState;
+import org.apache.myfaces.tobago.model.TreeState;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUITree extends AbstractUIData implements NamingContainer, Visual {
+
+  public static final String MESSAGE_NOT_LEAF = "tobago.tree.MESSAGE_NOT_LEAF";
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  public static final String SEP = "-";
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  public static final String SELECT_STATE = SEP + "selectState";
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  public static final String MARKED = "marked";
+
+  private TreeState state;
+
+  @Override
+  public void processValidators(final FacesContext facesContext) {
+    final int last = hasRows() ? getFirst() + getRows() : Integer.MAX_VALUE;
+    for (int rowIndex = getFirst(); rowIndex < last; rowIndex++) {
+      setRowIndex(rowIndex);
+      if (!isRowAvailable()) {
+        break;
+      }
+      for (final UIComponent child : getChildren()) {
+        child.processValidators(facesContext);
+      }
+    }
+    setRowIndex(-1);
+  }
+
+  @Override
+  public void processUpdates(final FacesContext facesContext) {
+    final int last = hasRows() ? getFirst() + getRows() : Integer.MAX_VALUE;
+    for (int rowIndex = getFirst(); rowIndex < last; rowIndex++) {
+      setRowIndex(rowIndex);
+      if (!isRowAvailable()) {
+        break;
+      }
+      for (final UIComponent child : getChildren()) {
+        child.processUpdates(facesContext);
+      }
+    }
+    setRowIndex(-1);
+  }
+
+  /**
+   * @deprecated since 2.0.0
+   */
+  @Deprecated
+  public UIComponent getRoot() {
+    // find the UITreeNode in the children.
+    for (final UIComponent child : getChildren()) {
+      if (child instanceof AbstractUITreeNodeBase) {
+        return child;
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void processDecodes(final FacesContext facesContext) {
+
+    if (!isRendered()) {
+      return;
+    }
+
+    final int last = hasRows() ? getFirst() + getRows() : Integer.MAX_VALUE;
+    for (int rowIndex = getFirst(); rowIndex < last; rowIndex++) {
+      setRowIndex(rowIndex);
+      if (!isRowAvailable()) {
+        break;
+      }
+      for (final UIComponent child : getChildren()) {
+        child.processDecodes(facesContext);
+      }
+    }
+    setRowIndex(-1);
+
+    decode(facesContext);
+  }
+
+/* XXX
+  @Override
+  public void validate(FacesContext context) {
+*/
+
+  // todo: validate must be written new, without TreeState
+/*
+    if (isRequired() && getState().getSelection().size() == 0) {
+      setValid(false);
+      FacesMessage facesMessage = MessageUtils.createFacesMessage(context,
+          UISelectOne.MESSAGE_VALUE_REQUIRED, FacesMessage.SEVERITY_ERROR);
+      context.addMessage(getClientId(context), facesMessage);
+    }
+
+    String selectable = ComponentUtils.getStringAttribute(this, selectable);
+    if (selectable != null && selectable.endsWith("LeafOnly")) {
+
+      Set<DefaultMutableTreeNode> selection = getState().getSelection();
+
+      for (DefaultMutableTreeNode node : selection) {
+        if (!node.isLeaf()) {
+          FacesMessage facesMessage = MessageUtils.createFacesMessage(
+              context, MESSAGE_NOT_LEAF, FacesMessage.SEVERITY_ERROR);
+          context.addMessage(getClientId(context), facesMessage);
+          break; // don't continue iteration, no dublicate messages needed
+        }
+      }
+    }
+*/
+//  call all validators
+/*
+    if (getValidators() != null) {
+      for (Validator validator : getValidators()) {
+        try {
+          validator.validate(context, this, null);
+        } catch (ValidatorException ve) {
+          // If the validator throws an exception, we're
+          // invalid, and we need to add a message
+          setValid(false);
+          FacesMessage message = ve.getFacesMessage();
+          if (message != null) {
+            message.setSeverity(FacesMessage.SEVERITY_ERROR);
+            context.addMessage(getClientId(context), message);
+          }
+        }
+      }
+    }
+  }
+
+  @Override
+  public void updateModel(FacesContext facesContext) {
+    // nothing to update for tree's
+    // TODO: updating the model here and *NOT* in the decode phase
+  }
+*/
+  public void setState(final TreeState state) {
+    this.state = state;
+  }
+
+  public TreeState getState() {
+    if (state != null) {
+      return state;
+    }
+
+    final ELContext elContext = FacesContext.getCurrentInstance().getELContext();
+    final ValueExpression expression = getValueExpression(Attributes.state.getName());
+
+    if (expression != null) {
+      TreeState state = (TreeState) expression.getValue(elContext);
+      if (state == null) {
+        state = new TreeState(new ExpandedState(2), new SelectedState(), new ScrollPosition());
+        expression.setValue(elContext, state);
+      }
+      return state;
+    }
+
+    state = new TreeState(new ExpandedState(2), new SelectedState(), new ScrollPosition());
+    return state;
+  }
+
+  @Override
+  public SelectedState getSelectedState() {
+    return getState().getSelectedState();
+  }
+
+  @Override
+  public ExpandedState getExpandedState() {
+    return getState().getExpandedState();
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object componentState) {
+    final Object[] values = (Object[]) componentState;
+    super.restoreState(context, values[0]);
+    state = (TreeState) values[1];
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] values = new Object[2];
+    values[0] = super.saveState(context);
+    values[1] = state;
+    return values;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeCommand.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeCommand.java
new file mode 100644
index 0000000..2664d61
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeCommand.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUITreeCommand extends AbstractUICommand {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeIndent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeIndent.java
new file mode 100644
index 0000000..4644d45
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeIndent.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.component.UIGraphic;
+
+public abstract class AbstractUITreeIndent extends UIGraphic implements Visual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeListbox.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeListbox.java
new file mode 100644
index 0000000..2e82ee6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeListbox.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUITreeListbox extends AbstractUITree {
+
+  @Override
+  public boolean isShowRoot() {
+    return false;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeMenu.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeMenu.java
new file mode 100644
index 0000000..9b2b5b8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeMenu.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.model.Selectable;
+
+public abstract class AbstractUITreeMenu extends AbstractUITree {
+
+  @Override
+  public Selectable getSelectable() {
+    return Selectable.none;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java
new file mode 100644
index 0000000..45db22a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNode.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+public abstract class AbstractUITreeNode extends AbstractUITreeNodeBase {
+
+  @Override
+  public String getLabel() {
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNodeBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNodeBase.java
new file mode 100644
index 0000000..2b72deb
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeNodeBase.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.model.TreeDataModel;
+import org.apache.myfaces.tobago.model.TreePath;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.component.UIData;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.List;
+
+public abstract class AbstractUITreeNodeBase
+    extends AbstractUIColumn implements Visual {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext) throws IOException {
+    final TreeDataModel model = ComponentUtils.findAncestor(this, AbstractUIData.class).getTreeDataModel();
+    model.setRowClientId(getClientId(facesContext));
+
+    super.encodeBegin(facesContext);
+  }
+
+  /**
+   * Returns the level of the tree node inside of the virtual tree. The root node has level 0.
+   * The children of the root note have level 1, and so on.
+   */
+  public int getLevel() {
+    final TreeDataModel model = ComponentUtils.findAncestor(this, AbstractUIData.class).getTreeDataModel();
+    return model.getLevel();
+  }
+
+  public List<Boolean> getJunctions() {
+    final TreeDataModel model = ComponentUtils.findAncestor(this, AbstractUIData.class).getTreeDataModel();
+    return model.getJunctions();
+  }
+
+  public boolean isFolder() {
+    final TreeDataModel model = ComponentUtils.findAncestor(this, AbstractUIData.class).getTreeDataModel();
+    return model.isFolder();
+  }
+
+  public TreePath getPath() {
+    final TreeDataModel model = ComponentUtils.findAncestor(this, AbstractUIData.class).getTreeDataModel();
+    return model.getPath();
+  }
+
+  public String nodeStateId(final FacesContext facesContext) {
+    final String clientId = getClientId(facesContext);
+    final UIData data = ComponentUtils.findAncestor(this, UIData.class);
+    final String dataId = data.getClientId(facesContext);
+    return clientId.substring(dataId.length() + 1);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeSelect.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeSelect.java
new file mode 100644
index 0000000..85d93d2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUITreeSelect.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UISelectBoolean;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+
+public abstract class AbstractUITreeSelect extends UISelectBoolean implements Visual, ClientBehaviorHolder {
+
+  @Override
+  public void updateModel(final FacesContext context) {
+    super.updateModel(context);
+  }
+
+  /**
+   * The value is stored in the state of the parent UITree, if the value attribute has not a value expression.
+   * The value is stored normally, if there is a value expression.
+   * @return Is the value stored in the state of the UITree parent object?
+   */
+  public boolean isValueStoredInState() {
+    final ValueExpression valueExpression = getValueExpression(Attributes.value.getName());
+    return valueExpression == null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/ContentSecurityPolicy.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/ContentSecurityPolicy.java
new file mode 100644
index 0000000..515f04c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/ContentSecurityPolicy.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class ContentSecurityPolicy {
+
+  private Mode mode;
+  private List<String> directiveList;
+
+  private boolean unmodifiable = false;
+
+  private void checkLocked() throws IllegalStateException {
+    if (unmodifiable) {
+      throw new RuntimeException("The configuration must not be changed after initialization!");
+    }
+  }
+
+  /**
+   * Lock the configuration, so it cannot be modified any more.
+   */
+  public void lock() {
+    unmodifiable = true;
+    directiveList = Collections.unmodifiableList(directiveList);
+  }
+
+  public ContentSecurityPolicy(final String mode) {
+    this.mode = Mode.parse(mode);
+    this.directiveList = new ArrayList<String>();
+  }
+
+  public void merge(final ContentSecurityPolicy other) {
+    checkLocked();
+    directiveList.addAll(other.directiveList);
+    mode = other.mode;
+  }
+
+  public List<String> getDirectiveList() {
+    return directiveList;
+  }
+
+  public Mode getMode() {
+    return mode;
+  }
+
+  @Override
+  public String toString() {
+    return "ContentSecurityPolicy{"
+        + "mode=" + mode
+        + ", directiveList=" + directiveList
+        + '}';
+  }
+
+  public static enum Mode {
+    ON("on"),
+    OFF("off"),
+    REPORT_ONLY("report-only");
+
+    private final String value;
+
+    private Mode(final String value) {
+      this.value = value;
+    }
+
+    public String getValue() {
+      return value;
+    }
+
+    public static Mode parse(final String string) {
+      if (ON.value.equals(string)) {
+        return ON;
+      } else if (OFF.value.equals(string)) {
+        return OFF;
+      } else if (REPORT_ONLY.value.equals(string)) {
+        return REPORT_ONLY;
+      } else {
+        throw new IllegalArgumentException("Found: " + string);
+      }
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RendererConfig.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RendererConfig.java
new file mode 100644
index 0000000..2212c2e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RendererConfig.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+
+import java.io.Serializable;
+
+public class RendererConfig implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private String name;
+  private Markup supportedMarkups = Markup.NULL;
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = StringUtils.uncapitalize(name);
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final RendererConfig that = (RendererConfig) o;
+
+    return name.equals(that.name);
+  }
+
+  public boolean contains(final String markup) {
+    return supportedMarkups.contains(markup);
+  }
+
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  public void addSupportedMarkup(final String markup) {
+    supportedMarkups = supportedMarkups.add(Markup.valueOf(markup));
+  }
+
+  public void merge(final RendererConfig rendererConfig) {
+     supportedMarkups = supportedMarkups.add(rendererConfig.supportedMarkups);
+  }
+
+  public String toString() {
+    return "RendererConfig: " + getName() + " " + supportedMarkups;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RenderersConfig.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RenderersConfig.java
new file mode 100644
index 0000000..8fc8e8f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RenderersConfig.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import java.util.List;
+
+public interface RenderersConfig {
+
+  boolean isMarkupSupported(String rendererName, String markup);
+
+  List<RendererConfig> getRendererConfigs();
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RenderersConfigImpl.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RenderersConfigImpl.java
new file mode 100644
index 0000000..c1cab0f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/RenderersConfigImpl.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class RenderersConfigImpl implements RenderersConfig, Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(RenderersConfigImpl.class);
+
+  private Map<String, RendererConfig> rendererMap = new HashMap<String, RendererConfig>();
+  private boolean merged = false;
+
+  private boolean unmodifiable = false;
+
+  private void checkLocked() throws IllegalStateException {
+    if (unmodifiable) {
+      throw new RuntimeException("The configuration must not be changed after initialization!");
+    }
+  }
+
+  /**
+   * Lock the configuration, so it cannot be modified any more.
+   */
+  public void lock() {
+    unmodifiable = true;
+    rendererMap = Collections.unmodifiableMap(rendererMap);
+  }
+
+  public boolean isMerged() {
+    return merged;
+  }
+
+  public void setMerged(final boolean merged) {
+    checkLocked();
+    this.merged = merged;
+  }
+
+  @Override
+  public List<RendererConfig> getRendererConfigs() {
+    final ArrayList<RendererConfig> result = new ArrayList<RendererConfig>();
+    result.addAll(rendererMap.values());
+    return result;
+  }
+
+  public void addRenderer(final RendererConfig rendererConfig) {
+    checkLocked();
+    final String name = rendererConfig.getName();
+    if (rendererMap.containsKey(name)) {
+      rendererMap.get(name).merge(rendererConfig);
+    } else {
+      rendererMap.put(name, rendererConfig);
+    }
+  }
+
+  @Override
+  public boolean isMarkupSupported(final String rendererName, final String markup) {
+    final RendererConfig rendererConfig = rendererMap.get(rendererName);
+    return rendererConfig != null && rendererConfig.contains(markup);
+  }
+
+  public void merge(final RenderersConfig renderersConfig, final boolean override) {
+    checkLocked();
+    final Collection<RendererConfig> renderers = renderersConfig.getRendererConfigs();
+    for (final RendererConfig rendererConfig : renderers) {
+      addRenderer(rendererConfig);
+    }
+  }
+
+  public String toString() {
+    return rendererMap.toString();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java
new file mode 100644
index 0000000..22ae841
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigBuilder.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+public final class TobagoConfigBuilder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoConfigBuilder.class);
+
+  private static final String WEB_INF_TOBAGO_CONFIG_XML = "WEB-INF/tobago-config.xml";
+  private static final String META_INF_TOBAGO_CONFIG_XML = "META-INF/tobago-config.xml";
+
+  private List<TobagoConfigFragment> list;
+
+  private TobagoConfigBuilder(final ServletContext servletContext)
+      throws ServletException, IOException, SAXException, ParserConfigurationException, URISyntaxException {
+    list = new ArrayList<TobagoConfigFragment>();
+    configFromClasspath();
+    configFromWebInf(servletContext);
+    final TobagoConfigSorter sorter = new TobagoConfigSorter(list);
+    sorter.sort();
+    final TobagoConfigImpl tobagoConfig = sorter.merge();
+
+    tobagoConfig.initProjectState(servletContext);
+    // prepare themes
+    tobagoConfig.resolveThemes();
+
+    tobagoConfig.initDefaultValidatorInfo();
+
+    tobagoConfig.lock();
+
+    servletContext.setAttribute(TobagoConfig.TOBAGO_CONFIG, tobagoConfig);
+  }
+
+  public static void init(final ServletContext servletContext) {
+    try {
+      final TobagoConfigBuilder builder = new TobagoConfigBuilder(servletContext);
+    } catch (final Throwable e) {
+      if (LOG.isErrorEnabled()) {
+        final String error = "Error while deploy process. Tobago can't be initialized! Application will not run!";
+        LOG.error(error, e);
+        throw new RuntimeException(error, e);
+      }
+    }
+  }
+
+  private void configFromWebInf(final ServletContext servletContext)
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final URL url = servletContext.getResource("/" + WEB_INF_TOBAGO_CONFIG_XML);
+    if (url != null) {
+      list.add(new TobagoConfigParser().parse(url));
+    }
+  }
+
+  private void configFromClasspath() throws ServletException {
+
+    try {
+      if (LOG.isInfoEnabled()) {
+        LOG.info("Searching for '" + META_INF_TOBAGO_CONFIG_XML + "'");
+      }
+      final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+      final List<URL> urls = new ArrayList<URL>();
+      CollectionUtils.addAll(urls, classLoader.getResources(META_INF_TOBAGO_CONFIG_XML));
+
+      for (final URL themeUrl : urls) {
+        try {
+          final TobagoConfigFragment fragment = new TobagoConfigParser().parse(themeUrl);
+          fragment.setUrl(themeUrl);
+          list.add(fragment);
+
+          // tomcat uses jar
+          // weblogic uses zip
+          // IBM WebSphere uses wsjar
+          final String protocol = themeUrl.getProtocol();
+          if (!"jar".equals(protocol) && !"zip".equals(protocol) && !"wsjar".equals(protocol)) {
+            LOG.warn("Unknown protocol '" + themeUrl + "'");
+          }
+        } catch (final Exception e) {
+          throw new Exception(e.getClass().getName() + " on themeUrl: " + themeUrl, e);
+        }
+      }
+    } catch (final Exception e) {
+      final String msg = "while loading ";
+      LOG.error(msg, e);
+      throw new ServletException(msg, e);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigEntityResolver.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigEntityResolver.java
new file mode 100644
index 0000000..851edb9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigEntityResolver.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+public class TobagoConfigEntityResolver extends DefaultHandler {
+
+  private static final String TOBAGO_CONFIG_DTD_1_0 = "/org/apache/myfaces/tobago/config/tobago-config_1_0.dtd";
+  private static final String TOBAGO_CONFIG_DTD_1_0_29 = "/org/apache/myfaces/tobago/config/tobago-config-1.0.29.dtd";
+  private static final String TOBAGO_CONFIG_DTD_1_0_30 = "/org/apache/myfaces/tobago/config/tobago-config-1.0.30.dtd";
+  private static final String TOBAGO_CONFIG_DTD_1_0_34 = "/org/apache/myfaces/tobago/config/tobago-config-1.0.34.dtd";
+  protected static final String TOBAGO_CONFIG_XSD_1_5 = "/org/apache/myfaces/tobago/config/tobago-config-1.5.xsd";
+  @Deprecated
+  protected static final String TOBAGO_CONFIG_XSD_1_6 = "/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd";
+  protected static final String TOBAGO_CONFIG_XSD_2_0 = "/org/apache/myfaces/tobago/config/tobago-config-2.0.xsd";
+  protected static final String TOBAGO_CONFIG_XSD_2_0_6 = "/org/apache/myfaces/tobago/config/tobago-config-2.0.6.xsd";
+  protected static final String TOBAGO_CONFIG_XSD_3_0 = "/org/apache/myfaces/tobago/config/tobago-config-3.0.xsd";
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoConfigEntityResolver.class);
+
+  @Override
+  public InputSource resolveEntity(final String publicId, final String systemId) throws IOException, SAXException {
+    if (LOG.isInfoEnabled()) {
+      LOG.info("Resolving publicId='" + publicId + "' and systemId='" + systemId + "'.");
+    }
+    final InputStream localStream;
+    if (systemId.equals("http://myfaces.apache.org/tobago/tobago-config_1_0.dtd")) {
+      localStream = getClass().getResourceAsStream(TOBAGO_CONFIG_DTD_1_0);
+    } else if (systemId.equals("http://myfaces.apache.org/tobago/tobago-config-1.0.29.dtd")) {
+      localStream = getClass().getResourceAsStream(TOBAGO_CONFIG_DTD_1_0_29);
+    } else if (systemId.equals("http://myfaces.apache.org/tobago/tobago-config-1.0.30.dtd")) {
+      localStream = getClass().getResourceAsStream(TOBAGO_CONFIG_DTD_1_0_30);
+    } else if (systemId.equals("http://myfaces.apache.org/tobago/tobago-config-1.0.34.dtd")) {
+      localStream = getClass().getResourceAsStream(TOBAGO_CONFIG_DTD_1_0_34);
+    } else {
+      localStream = null;
+    }
+    if (localStream != null) {
+      return new InputSource(localStream);
+    } else {
+      LOG.warn("Didn't find local resource for publicId='" + publicId + "' and systemId='" + systemId + "'. "
+          + "Trying to load with parent resolver (might be loaded over the internet).");
+      return super.resolveEntity(publicId, systemId);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java
new file mode 100644
index 0000000..5d98a55
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigFragment.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class TobagoConfigFragment {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoConfigFragment.class);
+
+  private String name;
+  private List<String> before;
+  private List<String> after;
+
+  private List<String> supportedThemeNames;
+  private String defaultThemeName;
+  private RenderersConfig renderersConfig;
+  private Boolean createSessionSecret;
+  private Boolean checkSessionSecret;
+  private Boolean preventFrameAttacks;
+  private ContentSecurityPolicy contentSecurityPolicy;
+  private Boolean setNosniffHeader;
+  private List<ThemeImpl> themeDefinitions;
+  private URL url;
+  private String sanitizerClass;
+  private Properties sanitizerProperties;
+  private Map<String, String> mimeTypes;
+
+  public TobagoConfigFragment() {
+    before = new ArrayList<String>();
+    after = new ArrayList<String>();
+    supportedThemeNames = new ArrayList<String>();
+    themeDefinitions = new ArrayList<ThemeImpl>();
+    mimeTypes = new HashMap<String, String>();
+  }
+
+  public void addSupportedThemeName(final String name) {
+    supportedThemeNames.add(name);
+  }
+
+  public List<String> getSupportedThemeNames() {
+    return supportedThemeNames;
+  }
+
+  public String getDefaultThemeName() {
+    return defaultThemeName;
+  }
+
+  public void setDefaultThemeName(final String defaultThemeName) {
+    this.defaultThemeName = defaultThemeName;
+  }
+
+  public RenderersConfig getRenderersConfig() {
+    return renderersConfig;
+  }
+
+  public void setRenderersConfig(final RenderersConfig renderersConfig) {
+    this.renderersConfig = renderersConfig;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public List<String> getBefore() {
+    return before;
+  }
+
+  public void addBefore(final String name) {
+    before.add(name);
+  }
+
+  public List<String> getAfter() {
+    return after;
+  }
+
+  public void addAfter(final String name) {
+    after.add(name);
+  }
+
+  public void addThemeDefinition(final ThemeImpl theme) {
+    themeDefinitions.add(theme);
+  }
+
+  public List<ThemeImpl> getThemeDefinitions() {
+    return themeDefinitions;
+  }
+
+  public Boolean getCreateSessionSecret() {
+    return createSessionSecret;
+  }
+
+  public void setCreateSessionSecret(final String createSessionSecret) {
+    this.createSessionSecret = Boolean.valueOf(createSessionSecret);
+  }
+
+  public Boolean getCheckSessionSecret() {
+    return checkSessionSecret;
+  }
+
+  public void setCheckSessionSecret(final String checkSessionSecret) {
+    this.checkSessionSecret = Boolean.valueOf(checkSessionSecret);
+  }
+
+  public Boolean getPreventFrameAttacks() {
+    return preventFrameAttacks;
+  }
+
+  public void setPreventFrameAttacks(final Boolean preventFrameAttacks) {
+    this.preventFrameAttacks = preventFrameAttacks;
+  }
+
+  public ContentSecurityPolicy getContentSecurityPolicy() {
+    return contentSecurityPolicy;
+  }
+
+  public void setContentSecurityPolicy(final ContentSecurityPolicy contentSecurityPolicy) {
+    this.contentSecurityPolicy = contentSecurityPolicy;
+  }
+
+  public Boolean getSetNosniffHeader() {
+    return setNosniffHeader;
+  }
+
+  public void setSetNosniffHeader(final Boolean setNosniffHeader) {
+    this.setNosniffHeader = setNosniffHeader;
+  }
+
+  public URL getUrl() {
+    return url;
+  }
+
+  public void setUrl(final URL url) {
+    this.url = url;
+  }
+
+  public String getSanitizerClass() {
+    return sanitizerClass;
+  }
+
+  public void setSanitizerClass(String sanitizerClass) {
+    this.sanitizerClass = sanitizerClass;
+  }
+
+  public Properties getSanitizerProperties() {
+    return sanitizerProperties;
+  }
+
+  public void setSanitizerProperties(Properties sanitizerProperties) {
+    this.sanitizerProperties = sanitizerProperties;
+  }
+
+  public void addMimeType(String extension, String type) {
+    this.mimeTypes.put(extension, type);
+  }
+
+  public Map<String, String> getMimeTypes() {
+    return mimeTypes;
+  }
+
+  @Override
+  public String toString() {
+    return name != null ? name : "(id=" + System.identityHashCode(this) + ")";
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java
new file mode 100644
index 0000000..5b94c92
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigImpl.java
@@ -0,0 +1,408 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.myfaces.tobago.application.ProjectStage;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.apache.myfaces.tobago.internal.util.JndiUtils;
+import org.apache.myfaces.tobago.sanitizer.Sanitizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.Application;
+import javax.faces.context.FacesContext;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.servlet.ServletContext;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * <p>
+ * Implementation of the Tobago configuration.
+ * </p>
+ * <p>
+ * All setters must are protected, so EL can't modify this config.
+ * </p>
+ */
+public class TobagoConfigImpl extends TobagoConfig {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoConfigImpl.class);
+
+  private List<Theme> supportedThemes;
+  private List<String> supportedThemeNames;
+  private Theme defaultTheme;
+  private String defaultThemeName;
+  private Map<String, ThemeImpl> availableThemes;
+  private RenderersConfig renderersConfig;
+  private ProjectStage projectStage;
+  private boolean createSessionSecret;
+  private boolean checkSessionSecret;
+  private boolean preventFrameAttacks;
+  private ContentSecurityPolicy contentSecurityPolicy;
+  private boolean setNosniffHeader;
+  private Map<String, String> defaultValidatorInfo;
+  private Sanitizer sanitizer;
+  private Map<String, String> mimeTypes;
+
+  private boolean unmodifiable = false;
+
+  protected TobagoConfigImpl() {
+    supportedThemeNames = new ArrayList<String>();
+    supportedThemes = new ArrayList<Theme>();
+    availableThemes = new HashMap<String, ThemeImpl>();
+    createSessionSecret = true;
+    checkSessionSecret = true;
+    preventFrameAttacks = true;
+    setNosniffHeader = true;
+    contentSecurityPolicy = new ContentSecurityPolicy(ContentSecurityPolicy.Mode.OFF.getValue());
+    mimeTypes = new HashMap<String, String>();
+  }
+
+  /**
+   * Lock the configuration, so it cannot be modified any more.
+   */
+  protected void lock() {
+    unmodifiable = true;
+    supportedThemes = Collections.unmodifiableList(supportedThemes);
+    for (Theme theme : supportedThemes) {
+      ((ThemeImpl) theme).lock();
+    }
+    supportedThemeNames = Collections.unmodifiableList(supportedThemeNames);
+    availableThemes = Collections.unmodifiableMap(availableThemes);
+
+    if (renderersConfig instanceof RenderersConfigImpl) {
+      ((RenderersConfigImpl) renderersConfig).lock();
+    }
+    contentSecurityPolicy.lock();
+
+    mimeTypes = Collections.unmodifiableMap(mimeTypes);
+  }
+
+  private void checkLocked() throws IllegalStateException {
+    if (unmodifiable) {
+      throw new RuntimeException("The configuration must not be changed after initialization!");
+    }
+  }
+
+  protected void addSupportedThemeName(final String name) {
+    checkLocked();
+    supportedThemeNames.add(name);
+  }
+
+  // TODO one init method
+  protected void resolveThemes() {
+    checkLocked();
+
+    if (defaultThemeName != null) {
+      defaultTheme = availableThemes.get(defaultThemeName);
+      checkThemeIsAvailable(defaultThemeName, defaultTheme);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("name = '{}'", defaultThemeName);
+        LOG.debug("defaultTheme = '{}'", defaultTheme);
+      }
+    } else {
+      int deep = 0;
+      for (final Map.Entry<String, ThemeImpl> entry : availableThemes.entrySet()) {
+        final Theme theme = entry.getValue();
+        if (theme.getFallbackList().size() > deep) {
+          defaultTheme = theme;
+          deep = theme.getFallbackList().size();
+        }
+      }
+      if (defaultTheme == null) {
+        final String error = "Did not found any theme! "
+            + "Please ensure you have a tobago-config.xml with a theme-definition in your "
+            + "theme JAR. Please add a theme JAR to your WEB-INF/lib";
+        LOG.error(error);
+        throw new RuntimeException(error);
+      } else {
+        if (LOG.isInfoEnabled()) {
+          LOG.info("Using default Theme {}", defaultTheme.getName());
+        }
+      }
+    }
+    if (!supportedThemeNames.isEmpty()) {
+      for (final String name : supportedThemeNames) {
+        final Theme theme = availableThemes.get(name);
+        checkThemeIsAvailable(name, theme);
+        supportedThemes.add(theme);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("name = '{}'", name);
+          LOG.debug("supportedThemes.last() = '{}'", supportedThemes.get(supportedThemes.size() - 1));
+        }
+      }
+    }
+  }
+
+  private void checkThemeIsAvailable(final String name, final Theme theme) {
+    if (theme == null) {
+      final String error = "Theme not found! name: '" + name + "'. "
+          + "Please ensure you have a tobago-config.xml with a theme-definition in your "
+          + "theme JAR. Found the following themes: " + availableThemes.keySet();
+      LOG.error(error);
+      throw new RuntimeException(error);
+    }
+  }
+
+  @Override
+  public Theme getTheme(final String name) {
+    if (name == null) {
+      LOG.debug("searching theme: null");
+      return defaultTheme;
+    }
+    if (defaultTheme.getName().equals(name)) {
+      return defaultTheme;
+    }
+    for (final Theme theme : supportedThemes) {
+      if (theme.getName().equals(name)) {
+        return theme;
+      }
+    }
+    LOG.debug("searching theme '{}' not found. Using default: {}", name, defaultTheme);
+    return defaultTheme;
+  }
+
+  protected void setDefaultThemeName(final String defaultThemeName) {
+    checkLocked();
+    this.defaultThemeName = defaultThemeName;
+  }
+
+  @Override
+  public List<Theme> getSupportedThemes() {
+    return supportedThemes;
+  }
+
+  @Override
+  public Theme getDefaultTheme() {
+    return defaultTheme;
+  }
+
+  protected void addAvailableTheme(ThemeImpl availableTheme) {
+    checkLocked();
+    availableThemes.put(availableTheme.getName(), availableTheme);
+  }
+
+  public Map<String, ThemeImpl> getAvailableThemes() {
+    return availableThemes;
+  }
+
+  protected RenderersConfig getRenderersConfig() {
+    return renderersConfig;
+  }
+
+  protected void setRenderersConfig(final RenderersConfig renderersConfig) {
+    checkLocked();
+    this.renderersConfig = renderersConfig;
+  }
+
+  @Override
+  public ProjectStage getProjectStage() {
+    return projectStage;
+  }
+
+  // TODO one init method
+  protected void initProjectState(final ServletContext servletContext) {
+    checkLocked();
+    String stageName = null;
+    try {
+      final Context ctx = new InitialContext();
+      final Object obj = JndiUtils.getJndiProperty(ctx, "jsf", "ProjectStage");
+      if (obj != null) {
+        if (obj instanceof String) {
+          stageName = (String) obj;
+        } else {
+          LOG.warn("JNDI lookup for key {} should return a java.lang.String value",
+              ProjectStage.PROJECT_STAGE_JNDI_NAME);
+        }
+      }
+    } catch (final NamingException e) {
+      // ignore
+    }
+
+    if (stageName == null) {
+      stageName = servletContext.getInitParameter(ProjectStage.PROJECT_STAGE_PARAM_NAME);
+    }
+
+    if (stageName == null) {
+      stageName = System.getProperty("org.apache.myfaces.PROJECT_STAGE");
+    }
+
+    if (stageName != null) {
+      try {
+        projectStage = ProjectStage.valueOf(stageName);
+      } catch (final IllegalArgumentException e) {
+        LOG.error("Couldn't discover the current project stage", e);
+      }
+    }
+    if (projectStage == null) {
+      if (LOG.isInfoEnabled()) {
+        LOG.info("Couldn't discover the current project stage, using {}", ProjectStage.Production);
+      }
+      projectStage = ProjectStage.Production;
+    }
+  }
+
+  protected synchronized void initDefaultValidatorInfo() {
+    if (defaultValidatorInfo != null) {
+      checkLocked();
+    }
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    if (facesContext != null) {
+      try {
+        final Application application = facesContext.getApplication();
+        final Map<String, String> map = application.getDefaultValidatorInfo();
+        if (map.size() > 0) {
+          defaultValidatorInfo = Collections.unmodifiableMap(map);
+        } else {
+          defaultValidatorInfo = Collections.emptyMap();
+        }
+      } catch (final Exception e) {
+        LOG.error("Can't initialize default validators (this happens with JBoss GateIn 3.6.0).", e);
+        defaultValidatorInfo = Collections.emptyMap();
+      }
+    }
+  }
+
+  @Override
+  public boolean isCreateSessionSecret() {
+    return createSessionSecret;
+  }
+
+  protected void setCreateSessionSecret(final boolean createSessionSecret) {
+    checkLocked();
+    this.createSessionSecret = createSessionSecret;
+  }
+
+  @Override
+  public boolean isCheckSessionSecret() {
+    return checkSessionSecret;
+  }
+
+  protected void setCheckSessionSecret(final boolean checkSessionSecret) {
+    checkLocked();
+    this.checkSessionSecret = checkSessionSecret;
+  }
+
+
+  @Override
+  public boolean isPreventFrameAttacks() {
+    return preventFrameAttacks;
+  }
+
+  protected void setPreventFrameAttacks(final boolean preventFrameAttacks) {
+    checkLocked();
+    this.preventFrameAttacks = preventFrameAttacks;
+  }
+
+  @Override
+  public ContentSecurityPolicy getContentSecurityPolicy() {
+    return contentSecurityPolicy;
+  }
+
+  @Override
+  public boolean isSetNosniffHeader() {
+    return setNosniffHeader;
+  }
+
+  protected void setSetNosniffHeader(final boolean setNosniffHeader) {
+    checkLocked();
+    this.setNosniffHeader = setNosniffHeader;
+  }
+
+  public Map<String, String> getDefaultValidatorInfo() {
+    // TODO: if the startup hasn't found a FacesContext and Application, this may depend on the order of the listeners.
+    if (defaultValidatorInfo == null) {
+      initDefaultValidatorInfo();
+    }
+    return defaultValidatorInfo;
+  }
+
+  @Override
+  public Sanitizer getSanitizer() {
+    return sanitizer;
+  }
+
+  protected void setSanitizer(Sanitizer sanitizer) {
+    checkLocked();
+    this.sanitizer = sanitizer;
+  }
+
+  @Override
+  public Map<String, String> getMimeTypes() {
+    return mimeTypes;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  @Override
+  @Deprecated
+  public boolean isClassicDateTimePicker() {
+    return false;
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("TobagoConfigImpl{");
+    builder.append("\nsupportedThemes=[");
+    for (final Theme supportedTheme : supportedThemes) {
+      builder.append(supportedTheme.getName());
+      builder.append(", ");
+    }
+    builder.append("], \ndefaultTheme=");
+    builder.append(defaultTheme != null ? defaultTheme.getName() : null);
+    builder.append(", \navailableThemes=");
+    builder.append(availableThemes.keySet());
+    builder.append(", \nprojectStage=");
+    builder.append(projectStage);
+    builder.append(", \ncreateSessionSecret=");
+    builder.append(createSessionSecret);
+    builder.append(", \ncheckSessionSecret=");
+    builder.append(checkSessionSecret);
+    builder.append(", \npreventFrameAttacks=");
+    builder.append(preventFrameAttacks);
+    builder.append(", \ncontentSecurityPolicy=");
+    builder.append(contentSecurityPolicy);
+    builder.append(", \nsetNosniffHeader=");
+    builder.append(setNosniffHeader);
+    builder.append(", \ndefaultValidatorInfo=");
+    builder.append(defaultValidatorInfo);
+    builder.append(", \nsanitizer=");
+    builder.append(sanitizer);
+    // to see only different (ignore alternative names for the same theme)
+    builder.append(", \nthemes=");
+    final Set<Theme> all = new HashSet<Theme>(availableThemes.values());
+    builder.append(all);
+    builder.append(", \nmimeTypes=");
+    builder.append(mimeTypes);
+    builder.append('}');
+    return builder.toString();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java
new file mode 100644
index 0000000..c9c8e92
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParser.java
@@ -0,0 +1,452 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.apache.myfaces.tobago.context.ThemeScript;
+import org.apache.myfaces.tobago.context.ThemeStyle;
+import org.apache.myfaces.tobago.internal.util.IoUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.transform.Source;
+import javax.xml.transform.stream.StreamSource;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import javax.xml.validation.Validator;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Properties;
+import java.util.Stack;
+
+public class TobagoConfigParser extends TobagoConfigEntityResolver {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoConfigParser.class);
+
+  private static final int TOBAGO_CONFIG = -1498874611;
+  private static final int NAME = 3373707;
+  private static final int ORDERING = 1234314708;
+  private static final int BEFORE = -1392885889;
+  private static final int AFTER = 92734940;
+  private static final int THEME_CONFIG = 1930630086;
+  private static final int DEFAULT_THEME = -114431171;
+  private static final int SUPPORTED_THEME = -822303766;
+  private static final int CREATE_SESSION_SECRET = 413906616;
+  private static final int CHECK_SESSION_SECRET = 275994924;
+  private static final int PREVENT_FRAME_ATTACKS = 270456726;
+  private static final int SET_NOSNIFF_HEADER = -1238451304;
+  private static final int CONTENT_SECURITY_POLICY = 1207440139;
+  private static final int DIRECTIVE = -962590641;
+  private static final int RENDERERS = 1839650832;
+  private static final int RENDERER = -494845757;
+  private static final int SUPPORTED_MARKUP = 71904295;
+  private static final int MARKUP = -1081305560;
+  private static final int THEME_DEFINITIONS = -255617156;
+  private static final int THEME_DEFINITION = 1515774935;
+  private static final int DISPLAY_NAME = 1568910518;
+  private static final int FALLBACK = 761243362;
+  private static final int VERSIONED = -1407102089;
+  private static final int RESOURCES = -1983070683;
+  private static final int EXCLUDES = 1994055129;
+  private static final int SANITIZER = 1807639849;
+  private static final int SANITIZER_CLASS = -974266412;
+  private static final int SCRIPT = -907685685;
+  private static final int STYLE = 109780401;
+  private static final int PROPERTIES = -926053069;
+  private static final int ENTRY = 96667762;
+  private static final int MIME_TYPES = 1081186720;
+  private static final int MIME_TYPE = -242217677;
+  private static final int EXTENSION = -612557761;
+  private static final int TYPE = 3575610;
+
+  private TobagoConfigFragment tobagoConfig;
+  private RendererConfig currentRenderer;
+  private ThemeImpl currentTheme;
+  private Boolean production;
+  private boolean exclude;
+  private StringBuilder buffer;
+  private Properties properties;
+  private String entryKey;
+  private String extension;
+  private String type;
+
+  private Stack<String> stack;
+
+  public TobagoConfigParser() {
+  }
+
+  public TobagoConfigFragment parse(final URL url)
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    if (LOG.isInfoEnabled()) {
+      LOG.info("Parsing configuration file: '{}'", url);
+    }
+
+    final TobagoConfigVersion version = new TobagoConfigVersion(url);
+
+    // todo: Is there a solution that validate with both, DTD and XSD?
+
+    if (version.isSchema()) {
+      validate(url, version);
+    }
+
+    InputStream inputStream = null;
+    try {
+      inputStream = url.openStream();
+      final SAXParserFactory factory = SAXParserFactory.newInstance();
+      if (!version.isSchema()) {
+        factory.setValidating(true);
+      }
+      final SAXParser saxParser = factory.newSAXParser();
+      saxParser.parse(inputStream, this);
+    } finally {
+      IoUtils.closeQuietly(inputStream);
+    }
+    return tobagoConfig;
+  }
+
+  @Override
+  public void ignorableWhitespace(final char[] ch, final int start, final int length) throws SAXException {
+    super.ignorableWhitespace(ch, start, length);
+  }
+
+  @Override
+  public void startDocument() throws SAXException {
+
+    buffer = new StringBuilder();
+    stack = new Stack<String>();
+  }
+
+  @Override
+  public void endDocument() throws SAXException {
+    assert stack.empty();
+    stack = null;
+  }
+
+  @Override
+  public void startElement(final String uri, final String localName, final String qName, final Attributes attributes)
+      throws SAXException {
+
+    // No unused content should be collected, specially text mixed with tags.
+    assert buffer.toString().trim().length() == 0;
+
+    buffer.setLength(0);
+    stack.add(qName);
+
+    switch (qName.hashCode()) {
+
+      case TOBAGO_CONFIG:
+        tobagoConfig = new TobagoConfigFragment();
+        break;
+
+      case CONTENT_SECURITY_POLICY:
+        final String mode = attributes.getValue("mode");
+        tobagoConfig.setContentSecurityPolicy(new ContentSecurityPolicy(mode));
+        break;
+
+      case RENDERERS:
+        if (currentTheme != null) {
+          currentTheme.setRenderersConfig(new RenderersConfigImpl());
+        } else {
+          tobagoConfig.setRenderersConfig(new RenderersConfigImpl());
+        }
+        break;
+
+      case RENDERER:
+        currentRenderer = new RendererConfig();
+        break;
+
+      case THEME_DEFINITION:
+        currentTheme = new ThemeImpl();
+        tobagoConfig.addThemeDefinition(currentTheme);
+        break;
+
+      case RESOURCES:
+        production = Boolean.parseBoolean(attributes.getValue("production"));
+        break;
+
+      case EXCLUDES:
+        exclude = true;
+        break;
+
+      case SCRIPT:
+        final ThemeScript script = new ThemeScript();
+        script.setName(attributes.getValue("name"));
+        if (production) {
+          currentTheme.getProductionResources().addScript(script, exclude);
+        } else {
+          currentTheme.getResources().addScript(script, exclude);
+        }
+        break;
+
+      case STYLE:
+        final ThemeStyle style = new ThemeStyle();
+        style.setName(attributes.getValue("name"));
+        if (production) {
+          currentTheme.getProductionResources().addStyle(style, exclude);
+        } else {
+          currentTheme.getResources().addStyle(style, exclude);
+        }
+        break;
+
+      case PROPERTIES:
+        properties = new Properties();
+        break;
+
+      case ENTRY:
+        entryKey = attributes.getValue("key");
+        break;
+
+      case NAME:
+      case ORDERING:
+      case BEFORE:
+      case AFTER:
+      case THEME_CONFIG:
+      case DEFAULT_THEME:
+      case SUPPORTED_THEME:
+      case SUPPORTED_MARKUP:
+      case MARKUP:
+      case CREATE_SESSION_SECRET:
+      case CHECK_SESSION_SECRET:
+      case PREVENT_FRAME_ATTACKS:
+      case SET_NOSNIFF_HEADER:
+      case DIRECTIVE:
+      case THEME_DEFINITIONS:
+      case DISPLAY_NAME:
+      case VERSIONED:
+      case FALLBACK:
+      case SANITIZER:
+      case SANITIZER_CLASS:
+      case MIME_TYPES:
+      case MIME_TYPE:
+      case EXTENSION:
+      case TYPE:
+        break;
+
+      default:
+        LOG.warn("Ignoring unknown start tag <" + qName + "> with hashCode=" + qName.hashCode());
+    }
+  }
+
+  @Override
+  public void characters(final char[] ch, final int start, final int length) throws SAXException {
+    buffer.append(ch, start, length);
+  }
+
+  @Override
+  public void endElement(final String uri, final String localName, final String qName) throws SAXException {
+    assert qName.equals(stack.peek());
+
+    final String text = buffer.toString().trim();
+    buffer.setLength(0);
+
+    switch (qName.hashCode()) {
+
+      case NAME:
+        final String parent = stack.get(stack.size() - 2);
+        switch (parent.hashCode()) {
+
+          case TOBAGO_CONFIG:
+            tobagoConfig.setName(text);
+            break;
+
+          case BEFORE:
+            tobagoConfig.addBefore(text);
+            break;
+
+          case AFTER:
+            tobagoConfig.addAfter(text);
+            break;
+
+          case RENDERER:
+            currentRenderer.setName(text);
+            if (currentTheme != null) {
+              ((RenderersConfigImpl) currentTheme.getRenderersConfig()).addRenderer(currentRenderer);
+            } else {
+              ((RenderersConfigImpl) tobagoConfig.getRenderersConfig()).addRenderer(currentRenderer);
+            }
+            break;
+
+          case THEME_DEFINITION:
+            currentTheme.setName(text);
+            break;
+
+          default:
+            LOG.warn("Ignoring unknown parent <" + qName + "> of tag <name>");
+        }
+        break;
+
+      case DEFAULT_THEME:
+        tobagoConfig.setDefaultThemeName(text);
+        break;
+
+      case SUPPORTED_THEME:
+        tobagoConfig.addSupportedThemeName(text);
+        break;
+
+      case CREATE_SESSION_SECRET:
+        tobagoConfig.setCreateSessionSecret(text);
+        break;
+
+      case CHECK_SESSION_SECRET:
+        tobagoConfig.setCheckSessionSecret(text);
+        break;
+
+      case PREVENT_FRAME_ATTACKS:
+        tobagoConfig.setPreventFrameAttacks(Boolean.parseBoolean(text));
+        break;
+
+      case SET_NOSNIFF_HEADER:
+        tobagoConfig.setSetNosniffHeader(Boolean.parseBoolean(text));
+        break;
+
+      case DIRECTIVE:
+        tobagoConfig.getContentSecurityPolicy().getDirectiveList().add(text);
+        break;
+
+      case MARKUP:
+        currentRenderer.addSupportedMarkup(text);
+        break;
+
+      case DISPLAY_NAME:
+        currentTheme.setDisplayName(text);
+        break;
+
+      case FALLBACK:
+        currentTheme.setFallbackName(text);
+        break;
+
+      case THEME_DEFINITION:
+        currentTheme = null;
+        break;
+
+      case VERSIONED:
+        currentTheme.setVersioned(Boolean.parseBoolean(text));
+        break;
+
+      case RESOURCES:
+        production = null;
+        break;
+
+      case EXCLUDES:
+        exclude = false;
+        break;
+
+      case SANITIZER_CLASS:
+        tobagoConfig.setSanitizerClass(text);
+        break;
+
+      case SANITIZER:
+        if (properties != null) {
+          tobagoConfig.setSanitizerProperties(properties);
+        }
+        properties = null;
+        break;
+
+      case ENTRY:
+        properties.setProperty(entryKey, text);
+        entryKey = null;
+        break;
+
+      case EXTENSION:
+        extension = text;
+        break;
+
+      case TYPE:
+        type = text;
+        break;
+
+      case MIME_TYPE:
+        tobagoConfig.addMimeType(extension, type);
+        break;
+
+      case TOBAGO_CONFIG:
+      case THEME_CONFIG:
+      case ORDERING:
+      case BEFORE:
+      case AFTER:
+      case SUPPORTED_MARKUP:
+      case CONTENT_SECURITY_POLICY:
+      case THEME_DEFINITIONS:
+      case RENDERERS:
+      case RENDERER:
+      case SCRIPT:
+      case STYLE:
+      case PROPERTIES:
+      case MIME_TYPES:
+        break;
+
+      default:
+        LOG.warn("Ignoring unknown end tag <" + qName + ">");
+    }
+
+    stack.pop();
+  }
+
+  @Override
+  public void warning(final SAXParseException e) throws SAXException {
+    throw e;
+  }
+
+  @Override
+  public void error(final SAXParseException e) throws SAXException {
+    throw e;
+  }
+
+  @Override
+  public void fatalError(final SAXParseException e) throws SAXException {
+    throw e;
+  }
+
+  private void validate(final URL url, final TobagoConfigVersion version)
+      throws URISyntaxException, SAXException, IOException {
+
+    final SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+    final Schema schema;
+    if ("3.0".equals(version.getVersion())) {
+      schema = schemaFactory.newSchema(getClass().getResource(TOBAGO_CONFIG_XSD_3_0));
+    } else if ("2.0.6".equals(version.getVersion())) {
+      schema = schemaFactory.newSchema(getClass().getResource(TOBAGO_CONFIG_XSD_2_0_6));
+    } else if ("2.0".equals(version.getVersion())) {
+      schema = schemaFactory.newSchema(getClass().getResource(TOBAGO_CONFIG_XSD_2_0));
+    } else if ("1.6".equals(version.getVersion())) {
+      LOG.warn("Using deprecated schema with version attribute 1.6 in file: '" + url + "'");
+      schema = schemaFactory.newSchema(getClass().getResource(TOBAGO_CONFIG_XSD_1_6));
+    } else if ("1.5".equals(version.getVersion())) {
+      schema = schemaFactory.newSchema(getClass().getResource(TOBAGO_CONFIG_XSD_1_5));
+    } else {
+      throw new SAXException("Using unknown version attribute '" + version.getVersion() + "' in file: '" + url + "'");
+    }
+    final Validator validator = schema.newValidator();
+    final Source source = new StreamSource(url.openStream());
+
+    validator.validate(source);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigSorter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigSorter.java
new file mode 100644
index 0000000..3ab2418
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigSorter.java
@@ -0,0 +1,332 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.apache.myfaces.tobago.sanitizer.IgnoringSanitizer;
+import org.apache.myfaces.tobago.sanitizer.JsoupSanitizer;
+import org.apache.myfaces.tobago.sanitizer.Sanitizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class TobagoConfigSorter implements Comparator<TobagoConfigFragment> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoConfigSorter.class);
+
+  private List<TobagoConfigFragment> list;
+  private List<Pair> pairs;
+
+  public TobagoConfigSorter(final List<TobagoConfigFragment> list) {
+    this.list = list;
+  }
+
+  public void sort() {
+
+    createRelevantPairs();
+
+    makeTransitive();
+
+    ensureIrreflexive();
+
+    ensureAntiSymmetric();
+
+    sort0();
+
+    if (LOG.isInfoEnabled()) {
+      LOG.info("Order of the Tobago config files:");
+      for (final TobagoConfigFragment fragment : list) {
+        String name = fragment.getName();
+        if (name == null) {
+          name = "<unnamed>";
+        } else {
+          name = "'" + name + "'";
+        }
+        LOG.info("name=" + name + " url='" + fragment.getUrl() + "'");
+      }
+    }
+  }
+
+  public TobagoConfigImpl merge() {
+
+    final TobagoConfigImpl result = new TobagoConfigImpl();
+
+    // default sanitizer
+    String sanitizerClass = JsoupSanitizer.class.getName();
+    Properties sanitizerProperties = new Properties();
+    sanitizerProperties.setProperty("whitelist", "relaxed");
+
+    for (final TobagoConfigFragment fragment : list) {
+      // default theme
+      final String defaultTheme = fragment.getDefaultThemeName();
+      if (defaultTheme != null) {
+        result.setDefaultThemeName(defaultTheme);
+      }
+
+      // supported themes
+      for (final String supported : fragment.getSupportedThemeNames()) {
+        result.addSupportedThemeName(supported);
+      }
+
+      // renderers config
+      if (fragment.getRenderersConfig() != null) {
+        if (result.getRenderersConfig() instanceof RenderersConfigImpl) {
+          ((RenderersConfigImpl) result.getRenderersConfig()).merge(fragment.getRenderersConfig(), false);
+        } else if (result.getRenderersConfig() == null) {
+          result.setRenderersConfig(fragment.getRenderersConfig());
+        }
+      }
+
+      // session secret
+      if (fragment.getCreateSessionSecret() != null) {
+        result.setCreateSessionSecret(fragment.getCreateSessionSecret());
+      }
+      if (fragment.getCheckSessionSecret() != null) {
+        result.setCheckSessionSecret(fragment.getCheckSessionSecret());
+      }
+
+      if (fragment.getPreventFrameAttacks() != null) {
+        result.setPreventFrameAttacks(fragment.getPreventFrameAttacks());
+      }
+
+      if (fragment.getContentSecurityPolicy() != null) {
+        result.getContentSecurityPolicy().merge(fragment.getContentSecurityPolicy());
+      }
+
+      if (fragment.getSetNosniffHeader() != null) {
+        result.setSetNosniffHeader(fragment.getSetNosniffHeader());
+      }
+
+      if (fragment.getSanitizerClass() != null) {
+        sanitizerClass = fragment.getSanitizerClass();
+        sanitizerProperties = fragment.getSanitizerProperties();
+      }
+
+      // theme definition
+      result.toString();
+      for (ThemeImpl theme : fragment.getThemeDefinitions()) {
+        result.addAvailableTheme(theme);
+      }
+
+      // url
+      // todo???
+
+      final Map<String, String> mimeTypes = result.getMimeTypes();
+      for (final Map.Entry<String, String> entry : fragment.getMimeTypes().entrySet()) {
+        mimeTypes.put(entry.getKey(), entry.getValue());
+      }
+
+    }
+
+    resolveThemes(result, result.getAvailableThemes());
+
+    if (sanitizerClass != null) {
+      try {
+        final Class<? extends Sanitizer> aClass = Class.forName(sanitizerClass).asSubclass(Sanitizer.class);
+        final Sanitizer sanitizer = aClass.newInstance();
+        sanitizer.setProperties(sanitizerProperties);
+        result.setSanitizer(sanitizer);
+      } catch (Throwable e) {
+        LOG.error("Can't create sanitizer: '" + sanitizerClass + "'", e);
+        result.setSanitizer(new IgnoringSanitizer());
+      }
+    }
+
+    return result;
+  }
+
+  protected void makeTransitive() {
+    // make the half order transitive: a < b && b < c => a < c
+    boolean growing = true;
+    while (growing) {
+      growing = false;
+      for (int i = 0; i < pairs.size(); i++) {
+        for (int j = 0; j < pairs.size(); j++) {
+          if (pairs.get(i).getHigher() == pairs.get(j).getLower()
+              && !isInRelation(pairs.get(i).getLower(), pairs.get(j).getHigher())) {
+            pairs.add(new Pair(pairs.get(i).getLower(), pairs.get(j).getHigher()));
+            growing = true;
+          }
+        }
+      }
+    }
+  }
+
+  protected void ensureIrreflexive() {
+    for (final Pair a : pairs) {
+        if (a.getLower() == a.getHigher()) {
+          final StringBuilder buffer = new StringBuilder();
+          buffer.append("Ordering problem. There are conflicting order rules. Not irreflexive. '");
+          buffer.append(a.getLower());
+          buffer.append("' < '");
+          buffer.append(a.getHigher());
+          buffer.append("'!\nThe reason may be a cycle.\n");
+          buffer.append("Complete list of rules: \n");
+          for (final Pair pair : pairs) {
+            buffer.append("'");
+            buffer.append(pair.getLower());
+            buffer.append("' < '");
+            buffer.append(pair.getHigher());
+            buffer.append("'\n");
+
+          }
+          throw new RuntimeException(buffer.toString());
+        }
+      }
+  }
+
+  protected void ensureAntiSymmetric() {
+    for (final Pair a : pairs) {
+      for (final Pair b : pairs) {
+        if (a.getLower() == b.getHigher() && a.getHigher() == b.getLower()) {
+          final StringBuilder buffer = new StringBuilder();
+          buffer.append("Ordering problem. There are conflicting order rules. Not antisymmetric. '");
+          buffer.append(a.getLower());
+          buffer.append("' < '");
+          buffer.append(a.getHigher());
+          buffer.append("'" + "'");
+          buffer.append(a.getLower());
+          buffer.append("' > '");
+          buffer.append(a.getHigher());
+          buffer.append("'!\nThe reason may be a cycle.\n");
+          buffer.append("Complete list of rules: \n");
+          for (final Pair pair : pairs) {
+            buffer.append("'");
+            buffer.append(pair.getLower());
+            buffer.append("' < '");
+            buffer.append(pair.getHigher());
+            buffer.append("'\n");
+
+          }
+          throw new RuntimeException(buffer.toString());
+        }
+      }
+    }
+  }
+
+  @Override
+  public int compare(final TobagoConfigFragment a, final TobagoConfigFragment b) {
+    if (isInRelation(a, b)) {
+      return -1;
+    }
+    if (isInRelation(b, a)) {
+      return 1;
+    }
+    return 0;
+  }
+
+  protected void createRelevantPairs() {
+
+    pairs = new ArrayList<Pair>();
+
+    // collecting all relations, which are relevant for us. We don't need "before" and "after" of unknown names.
+    for (final TobagoConfigFragment tobagoConfig : list) {
+      for (final String befores : tobagoConfig.getBefore()) {
+        final TobagoConfigFragment before = findByName(befores);
+        if (before != null) {
+          pairs.add(new Pair(tobagoConfig, before));
+        }
+      }
+      for (final String afters : tobagoConfig.getAfter()) {
+        final TobagoConfigFragment after = findByName(afters);
+        if (after != null) {
+          pairs.add(new Pair(after, tobagoConfig));
+        }
+      }
+    }
+  }
+
+  protected void sort0() {
+    Collections.sort(list, this);
+  }
+
+  private boolean isInRelation(final TobagoConfigFragment lower, final TobagoConfigFragment higher) {
+    for (final Pair p : pairs) {
+      if (p.getLower() == lower && p.getHigher() == higher) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  private TobagoConfigFragment findByName(final String name) {
+    for (final TobagoConfigFragment tobagoConfig : list) {
+      if (name.equals(tobagoConfig.getName())) {
+        return tobagoConfig;
+      }
+    }
+    return null;
+  }
+
+  private void resolveThemes(TobagoConfigImpl tobagoConfig, Map<String, ThemeImpl> map) {
+    for (final ThemeImpl theme : map.values()) {
+      final String fallbackName = theme.getFallbackName();
+      final ThemeImpl fallback = map.get(fallbackName);
+      theme.setFallback(fallback);
+    }
+    for (final ThemeImpl theme : map.values()) {
+      theme.resolveFallbacks();
+    }
+    for (final ThemeImpl theme : map.values()) {
+      theme.resolveRendererConfig(tobagoConfig.getRenderersConfig());
+    }
+    for (final ThemeImpl theme : map.values()) {
+      theme.resolveResources();
+    }
+    for (final ThemeImpl theme : map.values()) {
+      theme.init();
+    }
+  }
+
+  protected List<Pair> getPairs() {
+    return pairs;
+  }
+
+  private static class Pair {
+
+    private final TobagoConfigFragment lower;
+    private final TobagoConfigFragment higher;
+
+    private Pair(final TobagoConfigFragment lower, final TobagoConfigFragment higher) {
+      this.lower = lower;
+      this.higher = higher;
+    }
+
+    public TobagoConfigFragment getLower() {
+      return lower;
+    }
+
+    public TobagoConfigFragment getHigher() {
+      return higher;
+    }
+
+    @Override
+    public String toString() {
+      return lower + "<" + higher;
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigVersion.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigVersion.java
new file mode 100644
index 0000000..89e77fa
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/config/TobagoConfigVersion.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.myfaces.tobago.internal.util.IoUtils;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+public class TobagoConfigVersion extends TobagoConfigEntityResolver {
+
+  /** Schema or DTD? */
+  private boolean schema;
+
+  private String version;
+
+  public TobagoConfigVersion(final URL url) throws ParserConfigurationException, SAXException, IOException {
+
+    // simple reading with no validation, at this time
+    InputStream inputStream = null;
+    try {
+      inputStream = url.openStream();
+      final SAXParserFactory factory = SAXParserFactory.newInstance();
+      final SAXParser saxParser = factory.newSAXParser();
+      saxParser.parse(inputStream, this);
+    } finally {
+      IoUtils.closeQuietly(inputStream);
+    }
+  }
+
+  @Override
+  public void startElement(final String uri, final String localName, final String qName, final Attributes attributes) {
+    if ("tobago-config".equals(qName)) {
+      version = attributes.getValue("version");
+      schema = version != null;
+    }
+  }
+
+  public boolean isSchema() {
+    return schema;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/context/DateTimeI18n.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/context/DateTimeI18n.java
new file mode 100644
index 0000000..a84876f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/context/DateTimeI18n.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.context;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+public class DateTimeI18n {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DateTimeI18n.class);
+
+  private static final Map<Locale, DateTimeI18n> CACHE = new HashMap<Locale, DateTimeI18n>();
+
+  private final String[] monthNames = new String[12];
+  private final String[] monthNamesShort = new String[12];
+  private final String[] dayNames = new String[7];
+  private final String[] dayNamesShort = new String[7];
+  private final String[] dayNamesMin = new String[7];
+  private final int firstDay;
+
+  private DateTimeI18n(Locale locale) {
+
+    LOG.debug("Creating DateTimeI18n for locale: " + locale);
+
+    final Calendar calendar = Calendar.getInstance(locale);
+
+    calendar.set(2000, Calendar.JANUARY, 1);
+    final SimpleDateFormat dateFormatMMMMM = new SimpleDateFormat("MMMMM", locale);
+    final SimpleDateFormat dateFormatMMM = new SimpleDateFormat("MMM", locale);
+    for (int i = 0; i < monthNames.length; i++) {
+      monthNames[i] = dateFormatMMMMM.format(calendar.getTime());
+      monthNamesShort[i] = dateFormatMMM.format(calendar.getTime());
+      calendar.add(java.util.Calendar.MONTH, 1);
+    }
+
+    final SimpleDateFormat dateFormatEEEEE = new SimpleDateFormat("EEEEE", locale);
+    final SimpleDateFormat dateFormatEEE = new SimpleDateFormat("EEE", locale);
+    final SimpleDateFormat dateFormatE = new SimpleDateFormat("E", locale);
+    calendar.set(2000, Calendar.JANUARY, 2);
+    for (int i = 0; i < dayNames.length; i++) {
+      dayNames[i] = dateFormatEEEEE.format(calendar.getTime());
+      dayNamesShort[i] = dateFormatEEE.format(calendar.getTime());
+      dayNamesMin[i] = dateFormatE.format(calendar.getTime());
+      calendar.add(Calendar.DAY_OF_YEAR, 1);
+    }
+
+    firstDay = calendar.getFirstDayOfWeek() - 1; // because Java: 1 = Sunday and jQuery UI DatePicker: 0 = Sunday
+  }
+
+  public static synchronized DateTimeI18n valueOf(Locale locale) {
+    DateTimeI18n dateTimeI18n;
+    dateTimeI18n = CACHE.get(locale);
+    if (dateTimeI18n == null) {
+      dateTimeI18n = new DateTimeI18n(locale);
+      CACHE.put(locale, dateTimeI18n);
+    }
+    return dateTimeI18n;
+  }
+
+  public String[] getMonthNames() {
+    return monthNames;
+  }
+
+  public String[] getMonthNamesShort() {
+    return monthNamesShort;
+  }
+
+  public String[] getDayNames() {
+    return dayNames;
+  }
+
+  public String[] getDayNamesShort() {
+    return dayNamesShort;
+  }
+
+  public String[] getDayNamesMin() {
+    return dayNamesMin;
+  }
+
+  public int getFirstDay() {
+    return firstDay;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/BankHead.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/BankHead.java
new file mode 100644
index 0000000..1cf37d6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/BankHead.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import org.apache.myfaces.tobago.layout.LayoutToken;
+
+/**
+ * BankHead represents the head information of a bank like the token for this bank, the computed
+ * "current" and "minimum" measure and if it will be rendered. A bank is a generalization for columns and rows.
+ */
+public class BankHead {
+
+  private LayoutToken token;
+
+  private boolean rendered;
+
+  public BankHead(final LayoutToken token) {
+    this.token = token;
+    this.rendered = true;
+  }
+
+  public LayoutToken getToken() {
+    return token;
+  }
+
+  public void setToken(final LayoutToken token) {
+    this.token = token;
+  }
+
+  public boolean isRendered() {
+    return rendered;
+  }
+
+  public void setRendered(final boolean rendered) {
+    this.rendered = rendered;
+  }
+
+  @Override
+  public String toString() {
+    return "BankHead{" + token + "," + rendered + '}';
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Cell.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Cell.java
new file mode 100644
index 0000000..a5fe792
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Cell.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import javax.faces.component.UIComponent;
+
+/**
+ * To support horizontal and vertical spans, at each position will be a cell as a representative.
+ * Either a "origin cell" for the first position or a "span cell" for spanned other positions.
+ */
+public interface Cell {
+
+  UIComponent getComponent();
+
+  OriginCell getOrigin();
+
+  /**
+   * Is the origin cell or span cell at the first position of the cell compound.
+   *
+   * @return If its at the first position.
+   */
+  boolean isHorizontalFirst();
+
+  /**
+   * Is the origin cell or span cell at the first position of the cell compound.
+   *
+   * @return If its at the first position.
+   */
+  boolean isVerticalFirst();
+
+  int getColumnSpan();
+
+  int getRowSpan();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Grid.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Grid.java
new file mode 100644
index 0000000..44ca472
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/Grid.java
@@ -0,0 +1,447 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class Grid {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Grid.class);
+
+  // TODO: check if it is faster with arrays.
+  /**
+   * The rectangular data as a 1-dim list
+   */
+  private List<Cell> cells;
+
+  private LayoutTokens columns;
+  private LayoutTokens rows;
+
+  private int columnCount;
+  private int rowCount;
+
+  private int columnCursor;
+  private int rowCursor;
+
+  private List<Integer> errorIndexes;
+
+  public Grid(final LayoutTokens columns, final LayoutTokens rows) {
+    assert columns.getSize() > 0;
+    assert rows.getSize() > 0;
+
+    this.columnCount = columns.getSize();
+    this.rowCount = rows.getSize();
+
+    this.columns = columns;
+    this.rows = rows;
+
+    final int size = columnCount * rowCount;
+    this.cells = new ArrayList<Cell>(size);
+    for (int i = 0; i < size; i++) {
+      this.cells.add(null);
+    }
+  }
+
+  public void add(final OriginCell cell, int columnSpan, final int rowSpan) {
+
+    assert columnSpan > 0;
+    assert rowSpan > 0;
+
+    boolean error = false;
+
+    if (columnSpan + columnCursor > columnCount) {
+      LOG.warn("The columnSpan is to large for the actual position in the grid. Will be fixed. "
+          + "columnSpan='" + columnSpan + "' columnCursor='" + columnCursor + "' columnCount='" + columnCount + "'");
+      columnSpan = columnCount - columnCursor;
+      error = true;
+    }
+
+    cell.setColumnSpan(columnSpan);
+    cell.setRowSpan(rowSpan);
+
+    for (int i = 1; i < columnSpan; i++) {
+      if (getCell(i + columnCursor, rowCursor) != null) {
+        LOG.warn("The columnSpan is to large for the actual position in the grid. Will be fixed. "
+            + "columnSpan='" + columnSpan + "' columnCursor='" + columnCursor + "' columnCount='" + columnCount + "'");
+        columnSpan = i - 1;
+        error = true;
+      }
+    }
+
+    for (int j = 0; j < rowSpan; j++) {
+      for (int i = 0; i < columnSpan; i++) {
+        final Cell actualCell;
+        if (i == 0 && j == 0) {
+          actualCell = cell;
+        } else {
+          actualCell = new SpanCell(cell, i == 0, j == 0);
+        }
+        assert getCell(i + columnCursor, j + rowCursor) == null : "Position in the cell must be free.";
+        setCell(i + columnCursor, j + rowCursor, actualCell);
+        if (error) {
+          addError(i + columnCursor, j + rowCursor);
+        }
+      }
+    }
+
+    findNextFreeCell();
+  }
+
+  public Cell getCell(final int column, final int row) {
+    assert column >= 0 && column < columnCount : "column=" + column + " columnCount=" + columnCount;
+    assert row >= 0 : "row=" + row;
+
+    if (row >= rowCount) {
+      return null;
+    } else {
+      return cells.get(column + row * columnCount);
+    }
+  }
+
+  public void setCell(final int column, final int row, final Cell cell) {
+    if (row >= rowCount) {
+      enlarge(row - rowCount + 1);
+    }
+    cells.set(column + row * columnCount, cell);
+  }
+
+  private void findNextFreeCell() {
+    for (; rowCursor < rowCount; rowCursor++) {
+      for (; columnCursor < columnCount; columnCursor++) {
+        if (getCell(columnCursor, rowCursor) == null) {
+          return;
+        }
+      }
+      columnCursor = 0;
+    }
+  }
+
+  public LayoutTokens getColumns() {
+    return columns;
+  }
+
+  public LayoutTokens getRows() {
+    return rows;
+  }
+
+  private void enlarge(final int newRows) {
+    
+    // process cells
+    for (int i = 0; i < newRows; i++) {
+      for (int j = 0; j < columnCount; j++) {
+        cells.add(null);
+      }
+    }
+
+    // process heads
+    for (int i = rowCount; i < rowCount + newRows; i++) {
+      rows.addToken(RelativeLayoutToken.DEFAULT_INSTANCE);
+    }
+
+    rowCount += newRows;
+  }
+
+  public void addError(final int i, final int j) {
+    if (errorIndexes == null) {
+      errorIndexes = new ArrayList<Integer>();
+    }
+    errorIndexes.add(j * columnCount + i);
+  }
+
+  public boolean hasError(final int i, final int j) {
+    if (errorIndexes == null) {
+      return false;
+    }
+    return errorIndexes.contains(j * columnCount + i);
+  }
+
+  public int getColumnCount() {
+    return columnCount;
+  }
+
+  public int getRowCount() {
+    return rowCount;
+  }
+
+  /**
+   * Prints the state of the grid as an Unicode shape like this:
+   * ┏━┳━┳━┳━┯━┓
+   * ┃█┃█┃█┃█│➞┃
+   * ┠─╂─╊━╇━┿━┫
+   * ┃⬇┃⬇┃█│➞│➞┃
+   * ┣━╉─╊━╈━╈━┫
+   * ┃█┃⬇┃█┃█┃█┃
+   * ┣━╇━╇━╉─╊━┩
+   * ┃█│➞│➞┃⬇┃◌│
+   * ┡━┿━┿━╉─╂─┤
+   * │◌│◌│◌┃⬇┃◌│
+   * └─┴─┴─┺━┹─┘
+   */
+  public String gridAsString() {
+
+    final StringBuilder builder = new StringBuilder();
+
+    // top of grid
+    for (int i = 0; i < columnCount; i++) {
+      if (i == 0) {
+        if (getCell(i, 0) != null) {
+          builder.append("┏");
+        } else {
+          builder.append("┌");
+        }
+      } else {
+        final Cell c = getCell(i - 1, 0);
+        final Cell d = getCell(i, 0);
+        if (c == null && d == null) {
+          builder.append("┬");
+        } else {
+          if (connected(c, d)) {
+            builder.append("┯");
+          } else {
+            if (c == null) {
+              builder.append("┲");
+            } else if (d == null) {
+              builder.append("┱");
+            } else {
+              builder.append("┳");
+            }
+          }
+        }
+      }
+      if (getCell(i, 0) != null) {
+        builder.append("━");
+      } else {
+        builder.append("─");
+      }
+
+    }
+    if (getCell(columnCount - 1, 0) != null) {
+      builder.append("┓");
+    } else {
+      builder.append("┐");
+    }
+    builder.append("\n");
+
+    for (int j = 0; j < rowCount; j++) {
+
+      // between the cells
+      if (j != 0) {
+        for (int i = 0; i < columnCount; i++) {
+          if (i == 0) {
+            final Cell b = getCell(0, j - 1);
+            final Cell d = getCell(0, j);
+            if (b == null && d == null) {
+              builder.append("├");
+            } else {
+              if (connected(b, d)) {
+                builder.append("┠");
+              } else {
+                if (b == null) {
+                  builder.append("┢");
+                } else if (d == null) {
+                  builder.append("┡");
+                } else {
+                  builder.append("┣");
+                }
+              }
+            }
+          } else {
+            final Cell a = getCell(i - 1, j - 1);
+            final Cell b = getCell(i, j - 1);
+            final Cell c = getCell(i - 1, j);
+            final Cell d = getCell(i, j);
+//            a│b
+//            ─┼─
+//            c│d
+            if (connected(a, b)) {
+              if (connected(c, d)) {
+                if (connected(a, c)) {
+                  builder.append("┼");
+                } else {
+                  builder.append("┿");
+                }
+              } else {
+                builder.append("╈");
+              }
+            } else {
+              if (connected(c, d)) {
+                if (connected(a, c)) {
+                  builder.append("╄");
+                } else if (connected(b, d)) {
+                  builder.append("╃");
+                } else {
+                  builder.append("╇");
+                }
+              } else {
+                if (connected(a, c)) {
+                  if (connected(b, d)) {
+                    builder.append("╂");
+                  } else {
+                    builder.append("╊");
+                  }
+                } else {
+                  if (connected(b, d)) {
+                    builder.append("╉");
+                  } else {
+                    builder.append("╋");
+                  }
+                }
+              }
+            }
+          }
+          final Cell a = getCell(i, j - 1);
+          final Cell c = getCell(i, j);
+          if (connected(a, c)) {
+            builder.append("─");
+          } else {
+            builder.append("━");
+          }
+        }
+        final Cell a = getCell(columnCount - 1, j - 1);
+        final Cell c = getCell(columnCount - 1, j);
+        if (a == null && c == null) {
+          builder.append("┤");
+        } else {
+          if (connected(a, c)) {
+            builder.append("┨");
+          } else {
+            if (a == null) {
+              builder.append("┪");
+            } else if (c == null) {
+              builder.append("┩");
+            } else {
+              builder.append("┫");
+            }
+          }
+        }
+        builder.append("\n");
+      }
+
+      // cell
+      for (int i = 0; i < columnCount; i++) {
+        if (i == 0) {
+          if (getCell(i, j) != null) {
+            builder.append("┃");
+          } else {
+            builder.append("│");
+          }
+        } else {
+          final Cell c = getCell(i - 1, j);
+          final Cell d = getCell(i, j);
+          if (connected(c, d)) {
+            builder.append("│");
+          } else {
+            builder.append("┃");
+          }
+        }
+        if (hasError(i, j)) {
+          builder.append("✖"); //↯
+        } else {
+          if (getCell(i, j) instanceof OriginCell) {
+            builder.append("█");
+          } else if (getCell(i, j) instanceof SpanCell) {
+            if (j == 0) {
+              builder.append("➞");
+            } else {
+              final Cell a = getCell(i, j - 1);
+              final Cell c = getCell(i, j);
+              if (connected(a, c)) {
+                builder.append("⬇");
+              } else {
+                builder.append("➞");
+              }
+            }
+          } else {
+            builder.append("◌");
+          }
+        }
+      }
+      if (getCell(columnCount - 1, j) != null) {
+        builder.append("┃");
+      } else {
+        builder.append("│");
+      }
+      builder.append("\n");
+    }
+
+    //last bottom
+    for (int i = 0; i < columnCount; i++) {
+      if (i == 0) {
+        if (getCell(0, rowCount - 1) != null) {
+          builder.append("┗");
+        } else {
+          builder.append("└");
+        }
+      } else {
+        final Cell a = getCell(i - 1, rowCount - 1);
+        final Cell b = getCell(i, rowCount - 1);
+        if (a == null && b == null) {
+          builder.append("┴");
+        } else {
+          if (connected(a, b)) {
+            builder.append("┷");
+          } else {
+            if (a == null) {
+              builder.append("┺");
+            } else if (b == null) {
+              builder.append("┹");
+            } else {
+              builder.append("┻");
+            }
+          }
+        }
+      }
+      if (getCell(i, rowCount - 1) != null) {
+        builder.append("━");
+      } else {
+        builder.append("─");
+      }
+    }
+    if (getCell(columnCount - 1, rowCount - 1) != null) {
+      builder.append("┛");
+    } else {
+      builder.append("┘");
+    }
+    builder.append("\n");
+
+    return builder.toString();
+  }
+
+  @Override
+  public String toString() {
+    return gridAsString() + "columns=" + columns + '\n' + "rows=" + rows + "\n";
+  }
+
+  private boolean connected(final Cell a, final Cell b) {
+    if (a == null && b == null) {
+      return true;
+    }
+    if (a == null || b == null) {
+      return false;
+    }
+    return a.getOrigin().equals(b.getOrigin());
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/LayoutUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/LayoutUtils.java
new file mode 100644
index 0000000..589e51f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/LayoutUtils.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.component.UIComponent;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+
+public final class LayoutUtils {
+
+  private static final Pattern TOKEN_PATTERN = Pattern.compile("^(\\d*px|\\d*\\*|\\d*%|auto|fixed)$");
+
+  private LayoutUtils() {
+    // to prevent instantiation
+  }
+
+  public static boolean checkTokens(final String columns) {
+    final StringTokenizer st = new StringTokenizer(columns, ";");
+    while (st.hasMoreTokens()) {
+      final String token = st.nextToken();
+      if (!TOKEN_PATTERN.matcher(token).matches()) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public static List<UIComponent> findLayoutChildren(final UIComponent container) {
+    final List<UIComponent> result = new ArrayList<UIComponent>();
+    addLayoutChildren(container, result);
+    return result;
+  }
+
+  private static void addLayoutChildren(final UIComponent component, final List<UIComponent> result) {
+    for (final UIComponent child : component.getChildren()) {
+      if (child instanceof Visual) {
+        result.add(child);
+      } else {
+        // Child seems to be transparent for layout, like UIForm. 
+        // So we try to add the inner components.
+        addLayoutChildren(child, result);
+      }
+    }
+
+    final UIComponent child = component.getFacet(UIComponent.COMPOSITE_FACET_NAME);
+    if (child instanceof Visual) {
+      result.add(child);
+    } else if (child != null) {
+      // Child seems to be transparent for layout, like UIForm.
+      // So we try to add the inner components.
+      addLayoutChildren(child, result);
+    }
+  }
+
+  /**
+   * This is needed, when the layout manager is set by a facet.
+   * This should be only used by the classic &lt;tc:gridLayout&gt;
+   * @since 3.0.0
+   * @deprecated since 3.0.0
+   */
+  @Deprecated
+  public static UIComponent getLayoutManager(UIComponent component) {
+    final UIComponent base;
+
+    final UIComponent compositeFacet = component.getFacet(UIComponent.COMPOSITE_FACET_NAME);
+    if (compositeFacet != null) {
+      base = compositeFacet.getChildren().get(0);
+    } else {
+      base = component;
+    }
+
+    final UIComponent layoutFacet = ComponentUtils.getFacet(base, Facets.layout);
+    if (layoutFacet != null) {
+      return layoutFacet;
+    } else {
+      return null;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/MathUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/MathUtils.java
new file mode 100644
index 0000000..d3bd89e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/MathUtils.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+public final class MathUtils {
+
+  /**
+   * Values smaller than this EPSILON should be treated as zero.
+   */
+  public static final double EPSILON = 0.0000001;
+
+  private MathUtils() {
+  }
+
+  /**
+   * Adjusts the list of double values to rounded values with the same sum.
+   * E. g. 2.3, 2.4, 2.5, 2.8 -&gt; 2.0, 2.0, 3.0, 3.0
+   */
+  public static void adjustRemainders(final double[] list, double bias) {
+    for (final double ignored : list) {
+      final double lastBias;
+      if (bias < 0.0) {
+        lastBias = findAndAdjustMaxRemainder(list);
+      } else {
+        lastBias = findAndAdjustMinRemainder(list);
+      }
+      if (isZero(lastBias)) {
+        break;
+      }
+      bias += lastBias;
+    }
+
+    assert isZero(bias);
+  }
+
+  public static double findAndAdjustMaxRemainder(final double[] list) {
+    double max = 0.0;
+    Integer indexOfMax = null;
+    for (int i = 0; i < list.length; i++) {
+      final double remainder = remainder(list[i]);
+      if (remainder > max + EPSILON) {
+        max = remainder;
+        indexOfMax = i;
+      }
+    }
+    if (indexOfMax != null) {
+      list[indexOfMax] += 1.0 - max;
+      return 1.0 - max;
+    }
+    return 0.0;
+  }
+
+  public static double findAndAdjustMinRemainder(final double[] list) {
+    double min = 1.0;
+    Integer indexOfMin = null;
+    for (int i = 0; i < list.length; i++) {
+      final double remainder = remainder(list[i]);
+      if (remainder == 0) { // is zero
+        continue;
+      }
+      if (remainder < min - EPSILON) {
+        min = remainder;
+        indexOfMin = i;
+      }
+    }
+    if (indexOfMin != null) {
+      list[indexOfMin] -= min;
+      return -min;
+    }
+    return 0.0;
+  }
+
+  public static double remainder(final double v) {
+    return v - Math.floor(v);
+  }
+
+  public static boolean isZero(final double factor) {
+    return Math.abs(factor) < EPSILON;
+  }
+
+  public static boolean isNotZero(final double factor) {
+    return Math.abs(factor) >= EPSILON;
+  }
+
+  public static boolean isInteger(final double value) {
+    return isZero(value - Math.round(value));
+  }
+
+  public static boolean isNotInteger(final double value) {
+    return isNotZero(value - Math.round(value));
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/OriginCell.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/OriginCell.java
new file mode 100644
index 0000000..84ad0ae
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/OriginCell.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import javax.faces.component.UIComponent;
+
+public class OriginCell implements Cell {
+
+  private UIComponent component;
+  private int columnSpan;
+  private int rowSpan;
+
+  public OriginCell(final UIComponent component) {
+    this.component = component;
+  }
+
+  @Override
+  public UIComponent getComponent() {
+    return component;
+  }
+
+  @Override
+  public OriginCell getOrigin() {
+    return this;
+  }
+
+  @Override
+  public boolean isVerticalFirst() {
+    return true;
+  }
+
+  @Override
+  public boolean isHorizontalFirst() {
+    return true;
+  }
+
+  @Override
+  public int getColumnSpan() {
+    return columnSpan;
+  }
+
+  public void setColumnSpan(final int columnSpan) {
+    this.columnSpan = columnSpan;
+  }
+
+  @Override
+  public int getRowSpan() {
+    return rowSpan;
+  }
+
+  public void setRowSpan(final int rowSpan) {
+    this.rowSpan = rowSpan;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/SpanCell.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/SpanCell.java
new file mode 100644
index 0000000..50986fd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/layout/SpanCell.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import javax.faces.component.UIComponent;
+
+public class SpanCell implements Cell {
+
+  private OriginCell origin;
+  private boolean horizontalFirst;
+  private boolean verticalFirst;
+
+  public SpanCell(final OriginCell origin, final boolean horizontalFirst, final boolean verticalFirst) {
+    this.origin = origin;
+    this.horizontalFirst = horizontalFirst;
+    this.verticalFirst = verticalFirst;
+  }
+
+  @Override
+  public UIComponent getComponent() {
+    return origin.getComponent();
+  }
+
+  @Override
+  public OriginCell getOrigin() {
+    return origin;
+  }
+
+  @Override
+  public boolean isHorizontalFirst() {
+    return horizontalFirst;
+  }
+
+  @Override
+  public boolean isVerticalFirst() {
+    return verticalFirst;
+  }
+
+  @Override
+  public int getColumnSpan() {
+    return origin.getColumnSpan();
+  }
+
+  @Override
+  public int getRowSpan() {
+    return origin.getRowSpan();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/package-info.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/package-info.java
new file mode 100644
index 0000000..e8539e4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/package-info.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal;
+
+/**
+ * Package of internal classes.
+ * <br/>
+ * Classes of this package will normally not used by applications directly.
+ * <br/>
+ * Classes of this package may be changed without any deprecation warnings.
+ */
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/Collapse.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/Collapse.java
new file mode 100644
index 0000000..a024216
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/Collapse.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit;
+
+public class Collapse {
+
+  private Action action;
+  private String forId;
+
+  public Collapse(Action action, String forId) {
+    this.action = action;
+    this.forId = forId;
+  }
+
+  public Action getAction() {
+    return action;
+  }
+
+  public String getFor() {
+    return forId;
+  }
+
+  public enum Action {
+    show, hide
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/Command.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/Command.java
new file mode 100644
index 0000000..64e9dda
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/Command.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.UIForm;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.renderkit.renderer.TobagoClientBehaviorRenderer;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.ValueHolder;
+import javax.faces.context.FacesContext;
+
+/**
+ * @since 2.0.0
+ */
+public class Command {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Command.class);
+
+  /**
+   * The action is only needed if the action is not the HTML element itself.
+   */
+  private String action;
+  private Boolean transition;
+  private String target;
+  private String execute;
+  private String render;
+  private String focus;
+  private String confirmation;
+  private Integer delay;
+  private Collapse collapse;
+  private Boolean omit;
+
+  public Command() {
+  }
+
+  public Command(
+      final String action, final Boolean transition, final String target, final String execute,
+      final String render, final String focus, final String confirmation, final Integer delay,
+      final Collapse collapse, final Boolean omit) {
+    this.action = action;
+    this.transition = transition;
+    this.target = target;
+    setExecute(execute);
+    setRender(render);
+    this.focus = focus;
+    this.confirmation = confirmation;
+    this.delay = delay;
+    this.collapse = collapse;
+    this.omit = omit;
+  }
+
+  public Command(final FacesContext facesContext, final AbstractUICommand command) {
+    this(
+        null,
+        command.isTransition(),
+        command.getTarget(),
+        null,
+        null,
+        null,
+        getConfirmation(command),
+        null,
+        TobagoClientBehaviorRenderer.createCollapsible(facesContext, command),
+        command.isOmit());
+  }
+
+  public Command(final FacesContext facesContext, UIComponent facetComponent, final String focusId) {
+    if (facetComponent instanceof UIForm && facetComponent.getChildCount() == 1) {
+      LOG.warn("Please don't use a form, but a command with immediate=true instead.");
+      facetComponent = facetComponent.getChildren().get(0);
+    }
+    this.action = facetComponent.getClientId(facesContext);
+    // transition == true is the default
+    if (!ComponentUtils.getBooleanAttribute(facetComponent, Attributes.transition)) {
+      this.transition = Boolean.FALSE;
+    }
+    final String target = ComponentUtils.getStringAttribute(facetComponent, Attributes.target);
+    if (target != null) {
+      this.target = target;
+    }
+    if (focusId != null) {
+      this.focus = focusId;
+    }
+
+    final int delay = ComponentUtils.getIntAttribute(facetComponent, Attributes.delay);
+    if (delay > 0) {
+      this.delay = delay;
+    }
+    // omit == false is the default
+    if (ComponentUtils.getBooleanAttribute(facetComponent, Attributes.omit)) {
+      this.omit = Boolean.TRUE;
+    }
+  }
+
+  private static String getConfirmation(final AbstractUICommand command) {
+    final String confirmation = command.getConfirmation();
+    if (confirmation != null) {
+      return confirmation;
+    }
+    final UIComponent facet = ComponentUtils.getFacet(command, Facets.confirmation);
+    if (facet instanceof ValueHolder) {
+      final ValueHolder valueHolder = (ValueHolder) facet;
+      return "" + valueHolder.getValue();
+    } else if (facet != null) {
+      LOG.warn("The content of a confirmation facet must be a ValueHolder. Use e. g. <tc:out>.");
+    }
+    return null;
+  }
+
+  public String getAction() {
+    return action;
+  }
+
+  public void setAction(final String action) {
+    this.action = action;
+  }
+
+  public Boolean getTransition() {
+    return transition;
+  }
+
+  public void setTransition(final Boolean transition) {
+    this.transition = transition;
+  }
+
+  public String getTarget() {
+    return target;
+  }
+
+  public void setTarget(final String target) {
+    this.target = target;
+  }
+
+  public String getExecute() {
+    return execute;
+  }
+
+  public void setExecute(String execute) {
+    if (StringUtils.isNotBlank(execute)) {
+      this.execute = execute;
+    }
+  }
+
+  public String getRender() {
+    return render;
+  }
+
+  public void setRender(String render) {
+    if (StringUtils.isNotBlank(render)) {
+      this.render = render;
+    }
+  }
+
+  public String getFocus() {
+    return focus;
+  }
+
+  public void setFocus(final String focus) {
+    this.focus = focus;
+  }
+
+  public String getConfirmation() {
+    return confirmation;
+  }
+
+  public void setConfirmation(final String confirmation) {
+    this.confirmation = confirmation;
+  }
+
+  public Integer getDelay() {
+    return delay;
+  }
+
+  public void setDelay(final Integer delay) {
+    this.delay = delay;
+  }
+
+  public Collapse getCollapse() {
+    return collapse;
+  }
+
+  public void setCollapse(Collapse collapse) {
+    this.collapse = collapse;
+  }
+
+  public Boolean getOmit() {
+    return omit;
+  }
+
+  public void setOmit(final Boolean omit) {
+    this.omit = omit;
+  }
+
+  public void merge(Command c) {
+
+    //XXX TBD: check if this is okay.
+    // we need at least this for "execute" and "render" in the moment.
+
+    if (action == null) {
+      action = c.action;
+    }
+    if (transition == null) {
+      transition = c.transition;
+    }
+    if (target == null) {
+      target = c.target;
+    }
+    if (execute != null) {
+      if (c.execute != null) {
+        execute += " " + c.execute;
+      }
+    } else {
+      execute = c.execute;
+    }
+    if (render != null) {
+      if (c.render != null) {
+        render += " " + c.render;
+      }
+    } else {
+      render = c.render;
+    }
+    if (focus == null) {
+      focus = c.focus;
+    }
+    if (confirmation == null) {
+      confirmation = c.confirmation;
+    }
+    if (delay == null) {
+      delay = c.delay;
+    }
+    if (collapse == null) {
+      collapse = c.collapse;
+    }
+    if (omit == null) {
+      omit = c.omit;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/CommandMap.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/CommandMap.java
new file mode 100644
index 0000000..673391f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/CommandMap.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit;
+
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+
+import javax.faces.context.FacesContext;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Map of commands to be send to the user agent.
+ * It contains the command which shall be executed by click or other events.
+ *
+ * @since 2.0.0
+ */
+public class CommandMap {
+
+  private static final String KEY = CommandMap.class.getName() + ".KEY";
+
+  private Command click;
+  private Map<ClientBehaviors, Command> other;
+
+  /**
+   * Creates an empty command map, which may hold different command triggered by different keys.
+   */
+  public CommandMap() {
+  }
+
+  /**
+   * Creates a command map, which hold the given command triggered by "click".
+   */
+  public CommandMap(final Command click) {
+    this.click = click;
+  }
+
+  public void setClick(final Command click) {
+    this.click = click;
+  }
+
+  public Command getClick() {
+    return click;
+  }
+
+  public void addCommand(final ClientBehaviors name, final Command command) {
+    if (name == ClientBehaviors.click) {
+      setClick(command);
+    } else {
+      if (other == null) {
+        other = new HashMap<ClientBehaviors, Command>();
+      }
+
+      other.put(name, command);
+    }
+  }
+
+  public Map<ClientBehaviors, Command> getOther() {
+    if (other != null) {
+      return Collections.unmodifiableMap(other);
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * Merges these two maps.
+   * If one is null, the other one will be return. It may also return null.
+   * If both are not null, m1 will be filled with the data of m2.
+   * @param m1 map 1
+   * @param m2 map 2
+   * @return m1 or m2
+   */
+  public static CommandMap merge(final CommandMap m1, final CommandMap m2) {
+    if (m1 == null) {
+      return m2;
+    } else {
+      if (m2 == null) {
+        return m1;
+      } else {
+        final Command c2 = m2.getClick();
+        if (c2 != null) {
+          final Command c1 = m1.getClick();
+          if (c1 == null) {
+            m1.setClick(c2);
+          } else {
+            c1.merge(c2);
+          }
+        } else {
+          for (Map.Entry<ClientBehaviors, Command> entry : m2.getOther().entrySet()) {
+            ClientBehaviors key = entry.getKey();
+            Command value = entry.getValue();
+            if (m1.other.containsKey(key)) {
+              final Command command = m1.other.get(key);
+              command.merge(value);
+            } else {
+              m1.addCommand(key, value);
+            }
+          }
+        }
+        return m1;
+      }
+    }
+  }
+
+  public static CommandMap restoreCommandMap(final FacesContext facesContext) {
+    return (CommandMap) facesContext.getAttributes().get(KEY);
+  }
+
+  public static void storeCommandMap(final FacesContext facesContext, final CommandMap map) {
+    facesContext.getAttributes().put(KEY, map);
+  }
+
+  public boolean isEmpty() {
+    return click == null && other == null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/BarRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/BarRenderer.java
new file mode 100644
index 0000000..34339a7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/BarRenderer.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.UIBar;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFormBase;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Icons;
+import org.apache.myfaces.tobago.renderkit.html.Arias;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JQueryUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class BarRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final UIBar bar = (UIBar) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String clientId = bar.getClientId(facesContext);
+    final String navbarId = clientId + "::navbar";
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(clientId);
+    writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.NAVIGATION.toString(), false);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, bar);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.CONTAINER_FLUID);
+
+    encodeOpener(facesContext, bar, writer, navbarId);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(navbarId);
+    writer.writeClassAttribute(BootstrapClass.COLLAPSE, BootstrapClass.NAVBAR_TOGGLEABLE_XS);
+// XXX writer.writeClassAttribute(BootstrapClass.COLLAPSE, BootstrapClass.NAVBAR_COLLAPSE, BootstrapClass.NAVBAR_TEXT);
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    List<UIComponent> itemsToEncode = new ArrayList<UIComponent>();
+    collectItemsToEncode(component, itemsToEncode);
+    for (UIComponent child : itemsToEncode) {
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(BootstrapClass.FORM_INLINE);
+      child.encodeAll(facesContext);
+      writer.endElement(HtmlElements.DIV);
+    }
+  }
+
+  private void collectItemsToEncode(final UIComponent component, List<UIComponent> result) {
+    for (UIComponent child : component.getChildren()) {
+      if (child.isRendered()) {
+        if (child instanceof AbstractUIFormBase) {
+          collectItemsToEncode(child, result);
+        } else {
+          result.add(child);
+        }
+      }
+    }
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+  private void encodeOpener(
+      FacesContext facesContext, UIBar bar, TobagoResponseWriter writer, String navbarId) throws IOException {
+
+    writer.startElement(HtmlElements.DIV);
+
+    writer.startElement(HtmlElements.BUTTON);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+    writer.writeClassAttribute(BootstrapClass.NAVBAR_TOGGLER, BootstrapClass.HIDDEN_SM_UP);
+    writer.writeAttribute(DataAttributes.TOGGLE, "collapse", false);
+    writer.writeAttribute(DataAttributes.TARGET, JQueryUtils.escapeIdForHtml(navbarId), true);
+    writer.writeAttribute(Arias.EXPANDED, Boolean.FALSE.toString(), false);
+    writer.writeAttribute(Arias.CONTROLS, navbarId, false);
+
+    writer.writeIcon(Icons.BARS);
+
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(BootstrapClass.SR_ONLY);
+    writer.writeText("Toggle navigation"); // todo: i18n
+    writer.endElement(HtmlElements.SPAN);
+
+    writer.endElement(HtmlElements.BUTTON);
+
+    final UIComponent brand = ComponentUtils.getFacet(bar, Facets.brand);
+    if (brand != null) {
+      writer.startElement(HtmlElements.SPAN);
+      writer.writeClassAttribute(BootstrapClass.NAVBAR_BRAND);
+      RenderUtils.encode(facesContext, brand);
+      writer.endElement(HtmlElements.SPAN);
+    }
+
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/BoxRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/BoxRenderer.java
new file mode 100644
index 0000000..200e595
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/BoxRenderer.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.internal.component.AbstractUIBox;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.model.CollapseMode;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class BoxRenderer extends PanelRendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUIBox box = (AbstractUIBox) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final UIComponent label = ComponentUtils.getFacet(box, Facets.label);
+    final String labelString = box.getLabel();
+    final UIComponent bar = ComponentUtils.getFacet(box, Facets.bar);
+
+    writer.startElement(HtmlElements.DIV);
+    final boolean collapsed = box.isCollapsed();
+    writer.writeClassAttribute(
+        Classes.create(box),
+        collapsed ? TobagoClass.COLLAPSED : null,
+        BootstrapClass.CARD,
+        box.getCustomClass());
+    final String clientId = box.getClientId(facesContext);
+    writer.writeIdAttribute(clientId);
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, box);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, box);
+    writer.writeStyleAttribute(box.getStyle());
+
+    if (box.getCollapsedMode() != CollapseMode.none) {
+      encodeHidden(writer, clientId, collapsed);
+    }
+
+    if (label != null || labelString != null || bar != null) {
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(BootstrapClass.CARD_HEADER);
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(TobagoClass.BOX__HEADER);
+
+      writer.startElement(HtmlElements.H3);
+      if (labelString != null) {
+        writer.writeText(labelString);
+      }
+      if (label != null) {
+        RenderUtils.encode(facesContext, label);
+      }
+      writer.endElement(HtmlElements.H3);
+
+      if (bar != null) {
+        RenderUtils.encode(facesContext, bar);
+      }
+
+      writer.endElement(HtmlElements.DIV);
+      writer.endElement(HtmlElements.DIV);
+    }
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.CARD_BLOCK);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonRenderer.java
new file mode 100644
index 0000000..c6c4c13
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonRenderer.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.CssItem;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.context.FacesContext;
+import java.util.List;
+
+public class ButtonRenderer extends CommandRendererBase {
+
+  @Override
+  protected void addCssItems(
+      final FacesContext facesContext, final AbstractUICommand command, final List<CssItem> collected) {
+
+    final boolean defaultCommand = ComponentUtils.getBooleanAttribute(command, Attributes.defaultCommand);
+
+    collected.add(BootstrapClass.BTN);
+    collected.add(defaultCommand ? BootstrapClass.BTN_PRIMARY : BootstrapClass.BTN_SECONDARY);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRenderer.java
new file mode 100644
index 0000000..59067c7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ButtonsRenderer.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIButtons;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class ButtonsRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final AbstractUIButtons buttons = (AbstractUIButtons) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(buttons.getClientId(facesContext));
+      writer.writeClassAttribute(BootstrapClass.BTN_GROUP, BootstrapClass.NAVBAR_NAV);
+      writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.GROUP.toString(), false);
+    writer.writeClassAttribute(Classes.create(buttons), buttons.getCustomClass(), BootstrapClass.BTN_TOOLBAR);
+    writer.writeStyleAttribute(buttons.getStyle());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, buttons);
+    final String tip = buttons.getTip();
+    if (tip != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
+    }
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CalendarRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CalendarRenderer.java
new file mode 100644
index 0000000..7466b9e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CalendarRenderer.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UICalendar;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class CalendarRenderer extends RendererBase {
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UICalendar output = (UICalendar) component;
+    final String id = output.getClientId(facesContext);
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeIdAttribute(id);
+    writer.writeText("[tc:calender is currently not implemented]");
+    writer.endElement(HtmlElements.SPAN);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ColumnRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ColumnRenderer.java
new file mode 100644
index 0000000..d058176
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ColumnRenderer.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIColumn;
+import org.apache.myfaces.tobago.component.UILink;
+import org.apache.myfaces.tobago.component.UIOut;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+
+import javax.faces.component.UIComponent;
+
+public class ColumnRenderer extends RendererBase {
+
+  /**
+   * Differ between simple content and complex content.
+   * Decide if the content of a cell needs usually the whole possible space or
+   * is the character of the content like flowing text.
+   * In the second case, the style usually sets a padding.<br/>
+   * Pure is needed for &lt;tc:panel>,  &lt;tc:in>, etc.<br/>
+   * Pure is not needed for  &lt;tc:out> and &lt;tc:link>
+   */
+  private boolean isPure(final UIColumn column) {
+    for (final UIComponent child : column.getChildren()) {
+      if (!(child instanceof UIOut) && !(child instanceof UILink)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ColumnSelectorRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ColumnSelectorRenderer.java
new file mode 100644
index 0000000..4cf7204
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ColumnSelectorRenderer.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+
+public class ColumnSelectorRenderer extends RendererBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
new file mode 100644
index 0000000..5a2e8fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/CommandRendererBase.java
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.internal.component.AbstractUIButton;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFormBase;
+import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.CssItem;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public abstract class CommandRendererBase extends DecodingCommandRendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CommandRendererBase.class);
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUICommand command = (AbstractUICommand) component;
+    final String clientId = command.getClientId(facesContext);
+    final boolean disabled = command.isDisabled();
+    final LabelWithAccessKey label = new LabelWithAccessKey(command);
+    final boolean link = command.getLink() != null && !disabled;
+    final String target = command.getTarget();
+    final boolean parentOfCommands = command.isParentOfCommands();
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    if (parentOfCommands) { // extra span
+      writer.startElement(HtmlElements.SPAN);
+      writer.writeIdAttribute(clientId);
+      if (component instanceof AbstractUIButton) { // todo: check if we should differ here
+        writer.writeClassAttribute(BootstrapClass.BTN_GROUP);
+      } else {
+        writer.writeClassAttribute(BootstrapClass.DROPDOWN);
+      }
+    }
+
+    if (link) {
+      writer.startElement(HtmlElements.A);
+    } else {
+      writer.startElement(HtmlElements.BUTTON);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+    }
+    writer.writeIdAttribute(command.getFieldId(facesContext));
+    writer.writeNameAttribute(clientId);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+
+    if (!disabled) {
+      if (link) {
+        final String href = RenderUtils.generateUrl(facesContext, command);
+        writer.writeAttribute(HtmlAttributes.HREF, href, false);
+        writer.writeAttribute(HtmlAttributes.TARGET, target, false);
+
+        command.setOmit(true);
+      }
+
+      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, command)));
+
+      if (label.getAccessKey() != null) {
+        writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
+        AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), clientId);
+      }
+
+      final int tabIndex = ComponentUtils.getIntAttribute(command, Attributes.tabIndex);
+      if (tabIndex != 0) {
+        writer.writeAttribute(HtmlAttributes.TABINDEX, tabIndex);
+      }
+    }
+
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, command);
+    writer.writeStyleAttribute(command.getStyle());
+
+    final List<CssItem> cssItems = new ArrayList<CssItem>();
+    if (parentOfCommands) {
+      // XXX BootstrapClass.NAV_LINK should only be shown inside of UICommands or UIButtons
+      cssItems.add(BootstrapClass.DROPDOWN_TOGGLE);
+      writer.writeAttribute(DataAttributes.TOGGLE, "dropdown", false);
+    }
+    addCssItems(facesContext, command, cssItems);
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, command);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+
+    cssItems.add(command.getCustomClass());
+
+    writer.writeClassAttribute(
+        Classes.create(command),
+        null,
+        cssItems.toArray(new CssItem[cssItems.size()]));
+
+    final boolean defaultCommand = ComponentUtils.getBooleanAttribute(command, Attributes.defaultCommand);
+    if (defaultCommand) {
+      final AbstractUIFormBase form = ComponentUtils.findAncestor(command, AbstractUIFormBase.class);
+      writer.writeAttribute(DataAttributes.DEFAULT, form.getClientId(facesContext), false);
+    }
+
+    final String image = ComponentUtils.getStringAttribute(command, Attributes.image);
+    HtmlRendererUtils.encodeIconWithLabel(writer, facesContext, image, label, disabled);
+
+    if (link) {
+      writer.endElement(HtmlElements.A);
+    } else {
+      writer.endElement(HtmlElements.BUTTON);
+    }
+
+    if (parentOfCommands) {
+      writer.startElement(HtmlElements.UL);
+      writer.writeClassAttribute(BootstrapClass.DROPDOWN_MENU);
+      writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.MENU.toString(), false);
+    }
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUICommand command = (AbstractUICommand) component;
+
+    if (command.isParentOfCommands()) {
+      final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+      for (final UIComponent child : component.getChildren()) {
+        if (child.isRendered()) {
+          writer.startElement(HtmlElements.LI);
+          final CssItem submenu;
+          final CssItem disabled;
+          if (child instanceof AbstractUICommand) {
+            final AbstractUICommand c = (AbstractUICommand) child;
+            submenu = c.isParentOfCommands() ? TobagoClass.DROPDOWN__SUBMENU : null;
+            disabled = c.isDisabled() ? BootstrapClass.DISABLED : null;
+          } else {
+            submenu = null;
+            disabled = null;
+          }
+          writer.writeClassAttribute(BootstrapClass.DROPDOWN_ITEM, submenu, disabled);
+          child.encodeAll(facesContext);
+          writer.endElement(HtmlElements.LI);
+        }
+      }
+    } else {
+      super.encodeChildren(facesContext, component);
+    }
+
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUICommand command = (AbstractUICommand) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    if (command.isParentOfCommands()) {
+      writer.endElement(HtmlElements.UL);
+      writer.endElement(HtmlElements.SPAN);
+    }
+  }
+
+  protected void addCssItems(
+      final FacesContext facesContext, final AbstractUICommand command, final List<CssItem> collected) {
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DateRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DateRenderer.java
new file mode 100644
index 0000000..e1940dc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DateRenderer.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIDate;
+import org.apache.myfaces.tobago.internal.component.AbstractUIInput;
+import org.apache.myfaces.tobago.internal.context.DateTimeI18n;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapDateTimePickerClass;
+import org.apache.myfaces.tobago.renderkit.css.Icons;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class DateRenderer extends InRenderer {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DateRenderer.class);
+
+  @Override
+  protected void writeAdditionalAttributes(
+      final FacesContext facesContext, final TobagoResponseWriter writer, final AbstractUIInput input)
+      throws IOException {
+
+    final AbstractUIDate date = (AbstractUIDate) input;
+
+    super.writeAdditionalAttributes(facesContext, writer, date);
+    writer.writeAttribute(DataAttributes.PATTERN, date.getPattern(), true);
+    final DateTimeI18n dateTimeI18n = DateTimeI18n.valueOf(facesContext.getViewRoot().getLocale());
+    writer.writeAttribute(DataAttributes.DATE_TIME_I18N, JsonUtils.encode(dateTimeI18n), true);
+  }
+
+  @Override
+  protected void encodeBeginField(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(TobagoClass.PANEL);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.INPUT_GROUP);
+
+    super.encodeBeginField(facesContext, component);
+  }
+
+  @Override
+  public void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+
+    super.encodeEndField(facesContext, component);
+
+    final AbstractUIDate date = (AbstractUIDate) component;
+    final String pattern = date.getPattern();
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(BootstrapClass.INPUT_GROUP_BTN);
+    writer.startElement(HtmlElements.BUTTON);
+    writer.writeClassAttribute(
+        BootstrapClass.BTN,
+        BootstrapClass.BTN_SECONDARY,
+        BootstrapDateTimePickerClass.DATEPICKERBUTTON);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+    writer.writeAttribute(HtmlAttributes.DISABLED, date.isDisabled() || date.isReadonly());
+
+    final boolean hasDate = StringUtils.containsAny(pattern, "yYMDdE");
+    final boolean hasTime = StringUtils.containsAny(pattern, "Hhms");
+
+    if (hasDate || !hasTime) { //  || !hasTime is, to have at least one icon
+      writer.writeIcon(Icons.CALENDAR);
+    }
+    if (hasTime) {
+      writer.writeIcon(Icons.CLOCK_O);
+    }
+
+    if (StringUtils.containsAny(pattern, "GWFKzX")) {
+      LOG.warn("Pattern chars 'G', 'W', 'F', 'K', 'z' and 'X' are not supported: " + pattern);
+    }
+
+    writer.endElement(HtmlElements.BUTTON);
+    writer.endElement(HtmlElements.SPAN);
+
+    writer.endElement(HtmlElements.DIV);
+
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingCommandRendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingCommandRendererBase.java
new file mode 100644
index 0000000..bed16f5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingCommandRendererBase.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+
+public abstract class DecodingCommandRendererBase extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DecodingCommandRendererBase.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+
+    if (ComponentUtils.isOutputOnly(component)) {
+      return;
+    }
+    final String sourceId = facesContext.getExternalContext().getRequestParameterMap().get("javax.faces.source");
+    final String clientId = component.getClientId(facesContext);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("sourceId = '" + sourceId + "'");
+      LOG.debug("clientId = '" + clientId + "'");
+    }
+    if (clientId.equals(sourceId)) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("queueEvent = '" + clientId + "'");
+      }
+      commandActivated(component);
+    }
+
+    RenderUtils.decodeClientBehaviors(facesContext, component);
+
+  }
+
+  protected void commandActivated(final UIComponent component) {
+    component.queueEvent(new ActionEvent(component));
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingInputRendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingInputRendererBase.java
new file mode 100644
index 0000000..2df2210
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/DecodingInputRendererBase.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.UITextarea;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.sanitizer.SanitizeMode;
+import org.apache.myfaces.tobago.sanitizer.Sanitizer;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.Map;
+
+public abstract class DecodingInputRendererBase extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DecodingInputRendererBase.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    if (!(component instanceof EditableValueHolder)) {
+      return; // no decoding required
+    }
+
+    if (ComponentUtils.isOutputOnly(component)) {
+      return; // no decoding required
+    }
+
+    final String clientId = component.getClientId(facesContext);
+
+    final Map<String, String> requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
+    if (requestParameterMap.containsKey(clientId)) {
+      String newValue = requestParameterMap.get(clientId);
+      if (LOG.isDebugEnabled()) {
+        final boolean password = ComponentUtils.getBooleanAttribute(component, Attributes.password);
+        LOG.debug("clientId='{}'", clientId);
+        LOG.debug("requestParameterMap.get(clientId)='{}'", StringUtils.toConfidentialString(newValue, password));
+      }
+      if (component instanceof UITextarea) {
+        UITextarea textarea = (UITextarea) component;
+        if (ComponentUtils.getDataAttribute(component, "html-editor") != null
+            && SanitizeMode.auto == textarea.getSanitize()) {
+          final Sanitizer sanitizer = TobagoConfig.getInstance(facesContext).getSanitizer();
+          newValue = sanitizer.sanitize(newValue);
+        }
+      }
+
+      ((EditableValueHolder) component).setSubmittedValue(newValue);
+    }
+
+    RenderUtils.decodeClientBehaviors(facesContext, component);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/EventRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/EventRenderer.java
new file mode 100644
index 0000000..4b9c151
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/EventRenderer.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+public class EventRenderer extends DecodingCommandRendererBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FigureRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FigureRenderer.java
new file mode 100644
index 0000000..1759e34
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FigureRenderer.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFigure;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class FigureRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+    final AbstractUIFigure figure = (AbstractUIFigure) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.startElement(HtmlElements.FIGURE);
+    writer.writeClassAttribute(Classes.create(figure), BootstrapClass.FIGURE, figure.getCustomClass());
+    writer.writeStyleAttribute(figure.getStyle());
+    final String tip = figure.getTip();
+    if (tip != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
+    }
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.FIGURE_IMG);
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+    final AbstractUIFigure figure = (AbstractUIFigure) component;
+    final UIComponent label = ComponentUtils.getFacet(figure, Facets.label);
+    final String labelString = figure.getLabel();
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.endElement(HtmlElements.DIV);
+
+    if (labelString != null || label != null) {
+      writer.startElement(HtmlElements.FIGCAPTION);
+      writer.writeClassAttribute(BootstrapClass.FIGURE_CAPTION);
+      if (labelString != null) {
+        writer.writeText(labelString);
+      }
+      if (label != null) {
+        RenderUtils.encode(facesContext, label);
+      }
+      writer.endElement(HtmlElements.FIGCAPTION);
+    }
+    writer.endElement(HtmlElements.FIGURE);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
new file mode 100644
index 0000000..b87240d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FileRenderer.java
@@ -0,0 +1,205 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.context.TobagoResourceBundle;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFile;
+import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.HttpPartWrapper;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.PartUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.Icons;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.validator.FileItemValidator;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PostAddToViewEvent;
+import javax.faces.validator.Validator;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
+public class FileRenderer extends LabelLayoutRendererBase implements ComponentSystemEventListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(FileRenderer.class);
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    FacesContextUtils.setEnctype(facesContext, "multipart/form-data");
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    if (ComponentUtils.isOutputOnly(component)) {
+      return;
+    }
+
+    final AbstractUIFile file = (AbstractUIFile) component;
+    final Object request = facesContext.getExternalContext().getRequest();
+    if (request instanceof HttpServletRequest) {
+      try {
+        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+        if (file.isMultiple()) {
+          List<Part> parts = new ArrayList<Part>();
+          for (Part part : httpServletRequest.getParts()) {
+            if (file.getClientId(facesContext).equals(part.getName())) {
+              LOG.debug("Uploaded file '{}', size={}, type='{}'",
+                  PartUtils.getSubmittedFileName(part), part.getSize(), part.getContentType());
+              parts.add(new HttpPartWrapper(part));
+            }
+            file.setSubmittedValue(parts.toArray(new Part[parts.size()]));
+          }
+        } else {
+          final Part part = httpServletRequest.getPart(file.getClientId(facesContext));
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("Uploaded file '{}', size={}, type='{}'",
+                PartUtils.getSubmittedFileName(part), part.getSize(), part.getContentType());
+          }
+          file.setSubmittedValue(new HttpPartWrapper(part));
+        }
+      } catch (Exception e) {
+        LOG.error("", e);
+        file.setValid(false);
+      }
+    } else { // todo: PortletRequest
+      LOG.warn("Unsupported request type: " + request.getClass().getName());
+    }
+
+    RenderUtils.decodeClientBehaviors(facesContext, component);
+  }
+
+  @Override
+  protected void encodeBeginField(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final AbstractUIFile file = (AbstractUIFile) component;
+    final String clientId = file.getClientId(facesContext);
+    final String fieldId = file.getFieldId(facesContext);
+    final String accept = createAcceptFromValidators(file);
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(Classes.create(file), file.getCustomClass());
+    if (file.isLabelLayoutSkip()) {
+      writer.writeIdAttribute(clientId);
+    }
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, file);
+    writer.writeStyleAttribute(file.getStyle());
+
+    // visible fake input for a pretty look
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.INPUT_GROUP);
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.TEXT);
+    writer.writeAttribute(HtmlAttributes.ACCEPT, accept, true);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
+    writer.writeAttribute(HtmlAttributes.DISABLED, file.isDisabled() || file.isReadonly());
+    writer.writeAttribute(HtmlAttributes.READONLY, file.isReadonly());
+    writer.writeClassAttribute(Classes.create(file, "pretty"), BootstrapClass.FORM_CONTROL);
+    // TODO Focus
+    //HtmlRendererUtils.renderFocus(clientId, file.isFocus(), ComponentUtils.isError(file), facesContext, writer);
+    writer.endElement(HtmlElements.INPUT);
+
+    // invisible file input
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.MULTIPLE, file.isMultiple());
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.FILE);
+    writer.writeAttribute(HtmlAttributes.ACCEPT, accept, true);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
+    writer.writeIdAttribute(fieldId);
+    writer.writeClassAttribute(Classes.create(file, "real"));
+    writer.writeNameAttribute(clientId);
+    String multiFormat = TobagoResourceBundle.getString(facesContext, "tobago.file.multiFormat");
+    writer.writeAttribute(DataAttributes.dynamic("tobago-file-multi-format"), multiFormat, true);
+    // readonly seems not making sense in browsers.
+    writer.writeAttribute(HtmlAttributes.DISABLED, file.isDisabled() || file.isReadonly());
+    writer.writeAttribute(HtmlAttributes.READONLY, file.isReadonly());
+    writer.writeAttribute(HtmlAttributes.REQUIRED, file.isRequired());
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, file);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, file)));
+
+    writer.endElement(HtmlElements.INPUT);
+
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(BootstrapClass.INPUT_GROUP_BTN);
+    writer.startElement(HtmlElements.BUTTON);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, file.getTabIndex());
+    writer.writeClassAttribute(BootstrapClass.BTN, BootstrapClass.BTN_SECONDARY);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+    writer.writeAttribute(HtmlAttributes.DISABLED, file.isDisabled() || file.isReadonly());
+    writer.writeIcon(Icons.FOLDER_OPEN);
+    writer.endElement(HtmlElements.BUTTON);
+    writer.endElement(HtmlElements.SPAN);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+  private String createAcceptFromValidators(final AbstractUIFile file) {
+    final StringBuilder builder = new StringBuilder();
+    for (Validator validator : file.getValidators()) {
+      if (validator instanceof FileItemValidator) {
+        final FileItemValidator fileItemValidator = (FileItemValidator) validator;
+        for (final String contentType : fileItemValidator.getContentType()) {
+          builder.append(",");
+          builder.append(contentType);
+        }
+      }
+    }
+    if (builder.length() > 0) {
+      return builder.substring(1);
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  protected void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FlexLayoutRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FlexLayoutRenderer.java
new file mode 100644
index 0000000..e01067d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FlexLayoutRenderer.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIFlexLayout;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class FlexLayoutRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UIFlexLayout flexLayout = (UIFlexLayout) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(flexLayout.getClientId());
+    final String columns = flexLayout.getColumns();
+    StringBuilder b = new StringBuilder(); // TODO: implement better: own class, parser, validation, etc.
+    if (columns.contains(";")) {
+      b.append("{\"columns\":[");
+      b.append(columns
+          .replace("auto", "\"auto\"")
+          .replace(";", ",")
+          .replace("1*", "1")
+          .replace("2*", "2")
+          .replace("3*", "3")
+          .replace("4*", "4")
+          .replace("5*", "5")
+          .replace("6*", "6")
+          .replace("7*", "7")
+          .replace("8*", "8")
+          .replace("9*", "9")
+          .replace("*", "1").replaceAll("(\\d+[a-zA-Z]{2})", "{\"measure\":\"$1\"}"));
+      b.append("]}");
+    }
+    final String rows = flexLayout.getRows();
+    if (rows.contains(";")) {
+      b.append("{\"rows\":[");
+      b.append(rows
+          .replace("auto", "\"auto\"")
+          .replace(";", ",")
+          .replace("1*", "1")
+          .replace("2*", "2")
+          .replace("3*", "3")
+          .replace("4*", "4")
+          .replace("5*", "5")
+          .replace("6*", "6")
+          .replace("7*", "7")
+          .replace("8*", "8")
+          .replace("9*", "9")
+          .replace("*", "1").replaceAll("(\\d+[a-zA-Z]{2})", "{\"measure\":\"$1\"}"));
+      b.append("]}");
+    }
+    // todo: const, utils, etc.
+    writer.writeAttribute(DataAttributes.LAYOUT, b.toString(), true);
+    boolean vertically = rows.contains(";");
+    writer.writeClassAttribute(
+        Classes.create(flexLayout, vertically ? Markup.VERTICALLY : Markup.NULL),
+        TobagoClass.valueOf(flexLayout.getAlignItems()));
+    writer.writeStyleAttribute(flexLayout.getStyle());
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FlowLayoutRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FlowLayoutRenderer.java
new file mode 100644
index 0000000..0fd7b31
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FlowLayoutRenderer.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIFlowLayout;
+import org.apache.myfaces.tobago.layout.TextAlign;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class FlowLayoutRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final UIFlowLayout layout = (UIFlowLayout) component;
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(layout.getClientId());
+    writer.writeClassAttribute(Classes.create(layout), layout.getCustomClass());
+
+    Style style = layout.getStyle();
+    final TextAlign textAlign = layout.getTextAlign();
+    if (style == null && textAlign != null) {
+      style = new Style();
+      style.setTextAlign(textAlign);
+    }
+    writer.writeStyleAttribute(style);
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UIComponent container = component.getParent();
+    if (!container.isRendered()) {
+      return;
+    }
+    RenderUtils.encodeChildren(facesContext, container);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FooterRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FooterRenderer.java
new file mode 100644
index 0000000..d65efca
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FooterRenderer.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIFooter;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class FooterRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final UIFooter footer = (UIFooter) component;
+    writer.startElement(HtmlElements.FOOTER);
+    writer.writeIdAttribute(component.getClientId(facesContext));
+    writer.writeClassAttribute(
+        Classes.create(footer),
+        footer.isFixed() ? BootstrapClass.NAVBAR_FIXED_BOTTOM : null,
+        footer.getCustomClass());
+    writer.writeAttribute(HtmlAttributes.TITLE, footer.getTip(), true);
+    writer.writeStyleAttribute(footer.getStyle());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, footer);
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.FOOTER);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FormRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FormRenderer.java
new file mode 100644
index 0000000..8539be0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/FormRenderer.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIForm;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class FormRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final AbstractUIForm form = (AbstractUIForm) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final String clientId = form.getClientId(facesContext);
+    final boolean inline = form.isInline();
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(clientId);
+    writer.writeClassAttribute(
+        TobagoClass.FORM,
+        inline ? BootstrapClass.D_INLINE : null);;
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/GridLayoutRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/GridLayoutRenderer.java
new file mode 100644
index 0000000..7a77b23
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/GridLayoutRenderer.java
@@ -0,0 +1,153 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.internal.component.AbstractUIGridLayout;
+import org.apache.myfaces.tobago.internal.layout.Cell;
+import org.apache.myfaces.tobago.internal.layout.Grid;
+import org.apache.myfaces.tobago.internal.layout.OriginCell;
+import org.apache.myfaces.tobago.layout.LayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class GridLayoutRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(GridLayoutRenderer.class);
+
+  // todo: may use: http://www.w3.org/TR/css3-grid-layout/ (currently only IE 10 and higher)
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final AbstractUIGridLayout gridLayout = (AbstractUIGridLayout) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.TABLE);
+    writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.PRESENTATION.toString(), false);
+    writer.writeClassAttribute(Classes.create(gridLayout));
+
+    final StringBuilder builder = new StringBuilder();
+
+    builder.append("{\"columns\":");
+    JsonUtils.encode(gridLayout.getGrid().getColumns(), builder);
+    builder.append(",");
+
+    builder.append("\"rows\":");
+    JsonUtils.encode(gridLayout.getGrid().getRows(), builder);
+    builder.append("}");
+
+    writer.writeAttribute(DataAttributes.LAYOUT, builder.toString(), true);
+
+    writer.startElement(HtmlElements.COLGROUP);
+    final LayoutTokens columns = gridLayout.getGrid().getColumns();
+    for (LayoutToken column : columns.getTokens()) {
+        writer.startElement(HtmlElements.COL);
+        writer.endElement(HtmlElements.COL);
+    }
+    writer.endElement(HtmlElements.COLGROUP);
+    writer.startElement(HtmlElements.TBODY);
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUIGridLayout gridLayout = (AbstractUIGridLayout) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final Grid grid = gridLayout.getGrid();
+    final int columns = grid.getColumnCount();
+    final int rows = grid.getRowCount();
+
+    for (int i = 0; i < rows; i++) {
+      writer.startElement(HtmlElements.TR);
+      for (int j = 0; j < columns; j++) {
+        final Cell cell = grid.getCell(j, i);
+        if (cell instanceof OriginCell) {
+          writer.startElement(HtmlElements.TD);
+          final int columnSpan = cell.getColumnSpan();
+          if (columnSpan > 1) {
+            writer.writeAttribute(HtmlAttributes.COLSPAN, columnSpan);
+          }
+          final int rowSpan = cell.getRowSpan();
+          if (rowSpan > 1) {
+            writer.writeAttribute(HtmlAttributes.ROWSPAN, rowSpan);
+          }
+
+          final UIComponent element = cell.getComponent();
+          StringBuilder builder = new StringBuilder();
+          builder.append("{");
+          final Measure width = Measure.valueOf(ComponentUtils.getAttribute(element, Attributes.width));
+          if (width != null) {
+            builder.append("\"width\":");
+            builder.append(width.serialize());
+            builder.append(",");
+          }
+          final Measure height = Measure.valueOf(ComponentUtils.getAttribute(element, Attributes.height));
+          if (height != null) {
+            builder.append("\"height\":");
+            builder.append(height.serialize());
+            builder.append(",");
+          }
+          if (builder.length() > 1) {
+            builder.deleteCharAt(builder.length() - 1);
+          }
+          // todo: add more attributes
+          builder.append("}");
+
+          if (builder.length() > 2) { // empty is not need to render
+            ComponentUtils.putDataAttribute(element, "tobago-layout", builder.toString());
+          }
+          RenderUtils.encode(facesContext, element);
+
+          writer.endElement(HtmlElements.TD);
+        }
+      }
+      writer.endElement(HtmlElements.TR);
+    }
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.endElement(HtmlElements.TBODY);
+    writer.endElement(HtmlElements.TABLE);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/HeaderRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/HeaderRenderer.java
new file mode 100644
index 0000000..ce14251
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/HeaderRenderer.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIHeader;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class HeaderRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final UIHeader header = (UIHeader) component;
+    writer.startElement(HtmlElements.HEADER);
+    writer.writeIdAttribute(component.getClientId(facesContext));
+    // TBD: NAVBAR_DARK and BG_INVERSE should not be the default
+    // TBD: how to configure it when it is needed, with customClass, or with markup?
+    writer.writeClassAttribute(
+        Classes.create(header),
+        BootstrapClass.NAVBAR, /*BootstrapClass.NAVBAR_DARK, BootstrapClass.BG_INVERSE,*/
+        header.isFixed() ? BootstrapClass.NAVBAR_FIXED_TOP : null,
+        header.getCustomClass());
+// TBD: should NAVBAR class be in the LinksRenderer?
+    writer.writeAttribute(HtmlAttributes.TITLE, header.getTip(), true);
+    writer.writeStyleAttribute(header.getStyle());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, header);
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.HEADER);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/HiddenRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/HiddenRenderer.java
new file mode 100644
index 0000000..edbb480
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/HiddenRenderer.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIHidden;
+import org.apache.myfaces.tobago.layout.Display;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class HiddenRenderer extends DecodingInputRendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final AbstractUIHidden hidden = (AbstractUIHidden) component;
+    final String clientId = hidden.getClientId(facesContext);
+    final String value = RenderUtils.currentValue(hidden);
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.INPUT);
+    if (hidden.isDisabled()) {
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.TEXT);
+      final Style style = new Style();
+      style.setDisplay(Display.none);
+      writer.writeStyleAttribute(style);
+      writer.writeAttribute(HtmlAttributes.DISABLED, true);
+    } else {
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    }
+    writer.writeNameAttribute(clientId);
+    writer.writeIdAttribute(clientId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, hidden);
+    writer.writeAttribute(HtmlAttributes.VALUE, value != null ? value : "", true);
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.INPUT);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ImageRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ImageRenderer.java
new file mode 100644
index 0000000..aa00bc5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ImageRenderer.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUICommandBase;
+import org.apache.myfaces.tobago.internal.component.AbstractUIImage;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.FontAwesomeIconEncoder;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class ImageRenderer extends RendererBase {
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final AbstractUIImage image = (AbstractUIImage) component;
+    final String value = image.getUrl();
+    boolean fontAwesome = StringUtils.startsWith(value, "fa-");
+    if (fontAwesome) {
+      // todo: should not be static
+      writer.writeIcon(null, image.getStyle(), FontAwesomeIconEncoder.generateClass(value));
+    } else {
+      final String alt = image.getAlt();
+      writer.startElement(HtmlElements.IMG);
+      writer.writeIdAttribute(image.getClientId(facesContext));
+      HtmlRendererUtils.writeDataAttributes(facesContext, writer, image);
+      writer.writeAttribute(HtmlAttributes.SRC, value, true);
+      writer.writeAttribute(HtmlAttributes.ALT, alt != null ? alt : "", true);
+      final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, image);
+      if (title != null) {
+        writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+      }
+      writer.writeClassAttribute(
+          Classes.create(image),
+          isDisabled(image) ? BootstrapClass.DISABLED : null,
+          image.getCustomClass());
+      writer.writeStyleAttribute(image.getStyle());
+      writer.endElement(HtmlElements.IMG);
+    }
+  }
+
+  private boolean isDisabled(final AbstractUIImage image) {
+    return image.isDisabled()
+        || (image.getParent() instanceof AbstractUICommandBase
+        && ((AbstractUICommandBase) image.getParent()).isDisabled());
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRenderer.java
new file mode 100644
index 0000000..9de251c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/InRenderer.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.internal.component.AbstractUIButton;
+import org.apache.myfaces.tobago.internal.component.AbstractUIInput;
+import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIPanel;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.LengthValidator;
+import javax.faces.validator.Validator;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+public class InRenderer extends LabelLayoutRendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(InRenderer.class);
+
+  @Override
+  protected void encodeBeginField(FacesContext facesContext, UIComponent component)
+      throws IOException {
+    final AbstractUIInput input = (AbstractUIInput) component;
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, input);
+    final String currentValue = getCurrentValue(facesContext, input);
+    final boolean password = ComponentUtils.getBooleanAttribute(input, Attributes.password);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("currentValue = '{}'", StringUtils.toConfidentialString(currentValue, password));
+    }
+    final HtmlInputTypes type = password ? HtmlInputTypes.PASSWORD : HtmlInputTypes.TEXT;
+    final String clientId = input.getClientId(facesContext);
+    final String fieldId = input.getFieldId(facesContext);
+    final boolean readonly = input.isReadonly();
+    final boolean disabled = input.isDisabled();
+    final boolean required = ComponentUtils.getBooleanAttribute(input, Attributes.required);
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final UIComponent after = ComponentUtils.getFacet(input, Facets.after);
+    final UIComponent before = ComponentUtils.getFacet(input, Facets.before);
+
+    if (after != null || before != null) {
+      writer.startElement(HtmlElements.DIV); // Wrapping the field to fix input groups with flexLeft/flexRight
+      writer.writeClassAttribute(TobagoClass.INPUT__GROUP__OUTER);
+      if (input.isLabelLayoutSkip()) {
+        writer.writeIdAttribute(clientId);
+      }
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(BootstrapClass.INPUT_GROUP);
+    }
+    encodeGroupAddon(facesContext, writer, before);
+
+    writer.startElement(HtmlElements.INPUT);
+
+    if (input.getAccessKey() != null) {
+      writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(input.getAccessKey()), false);
+      AccessKeyLogger.addAccessKey(facesContext, input.getAccessKey(), clientId);
+    }
+
+    writer.writeAttribute(HtmlAttributes.TYPE, type);
+    writer.writeNameAttribute(clientId);
+    writer.writeIdAttribute(fieldId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, input);
+    if (currentValue != null) {
+      writer.writeAttribute(HtmlAttributes.VALUE, currentValue, true);
+    }
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+    int maxLength = 0;
+    final String pattern = null;
+    for (final Validator validator : input.getValidators()) {
+      if (validator instanceof LengthValidator) {
+        final LengthValidator lengthValidator = (LengthValidator) validator;
+        maxLength = lengthValidator.getMaximum();
+      }
+        /*if (validator instanceof RegexValidator) {
+          RegexValidator regexValidator = (RegexValidator) validator;
+          pattern = regexValidator.getPattern();
+        }*/
+    }
+    if (maxLength > 0) {
+      writer.writeAttribute(HtmlAttributes.MAXLENGTH, maxLength);
+    }
+    if (pattern != null) {
+      writer.writeAttribute(HtmlAttributes.PATTERN, pattern, false);
+    }
+    writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, input.getTabIndex());
+    writer.writeStyleAttribute(input.getStyle());
+
+    final String placeholder = input.getPlaceholder();
+    if (!disabled && !readonly && StringUtils.isNotBlank(placeholder)) {
+      writer.writeAttribute(HtmlAttributes.PLACEHOLDER, placeholder, true);
+    }
+
+    writer.writeClassAttribute(Classes.create(input), BootstrapClass.FORM_CONTROL, input.getCustomClass());
+    writer.writeAttribute(HtmlAttributes.REQUIRED, required);
+    HtmlRendererUtils.renderFocus(clientId, input.isFocus(), ComponentUtils.isError(input), facesContext, writer);
+    writeAdditionalAttributes(facesContext, writer, input);
+
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, input)));
+
+    writer.endElement(HtmlElements.INPUT);
+
+    encodeGroupAddon(facesContext, writer, after);
+
+    if (after != null || before != null) {
+      writer.endElement(HtmlElements.DIV);
+      writer.endElement(HtmlElements.DIV);
+    }
+  }
+
+  private void encodeGroupAddon(FacesContext facesContext, TobagoResponseWriter writer, UIComponent addon)
+      throws IOException {
+    if (addon != null) {
+      final List<UIComponent> children;
+      if (addon instanceof UIPanel) {
+        children = addon.getChildren();
+      } else {
+        children = Collections.singletonList(addon);
+      }
+      for (UIComponent child : children) {
+        writer.startElement(HtmlElements.SPAN);
+        final BootstrapClass css
+            = child instanceof AbstractUIButton ? BootstrapClass.INPUT_GROUP_BTN : BootstrapClass.INPUT_GROUP_ADDON;
+        writer.writeClassAttribute(css);
+        RenderUtils.encode(facesContext, child);
+        writer.endElement(HtmlElements.SPAN);
+      }
+    }
+  }
+
+  @Override
+  protected void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+  }
+
+  protected void writeAdditionalAttributes(
+      final FacesContext facesContext, final TobagoResponseWriter writer, final AbstractUIInput input)
+      throws IOException {
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LabelLayoutRendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LabelLayoutRendererBase.java
new file mode 100644
index 0000000..bbf51d1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LabelLayoutRendererBase.java
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportsAccessKey;
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.CssItem;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+/**
+ * Manages the rendering of the <b>label</b> and the <b>field</b> together with different possibilities for
+ * the position of the label (defined by {@link org.apache.myfaces.tobago.component.Attributes#labelLayout}
+ */
+public abstract class LabelLayoutRendererBase extends DecodingInputRendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    encodeBeginSurrounding(facesContext, component);
+
+    switch (getType(component)) {
+      case segmentLeft:
+        if (LabelLayout.getSegment(facesContext) == LabelLayout.segmentRight) {
+          encodeBeginField(facesContext, component);
+        }
+        break;
+      case segmentRight:
+        if (LabelLayout.getSegment(facesContext) == LabelLayout.segmentLeft) {
+          encodeBeginField(facesContext, component);
+        }
+        break;
+      default:
+        encodeBeginField(facesContext, component);
+        break;
+    }
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    switch (getType(component)) {
+      case segmentLeft:
+        if (LabelLayout.getSegment(facesContext) == LabelLayout.segmentRight) {
+          encodeEndField(facesContext, component);
+        }
+        break;
+      case segmentRight:
+        if (LabelLayout.getSegment(facesContext) == LabelLayout.segmentLeft) {
+          encodeEndField(facesContext, component);
+        }
+        break;
+      default:
+        encodeEndField(facesContext, component);
+        break;
+    }
+
+    encodeEndSurrounding(facesContext, component);
+  }
+
+  protected abstract void encodeBeginField(FacesContext facesContext, UIComponent component) throws IOException;
+
+  protected abstract void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException;
+
+  protected void encodeBeginSurrounding(final FacesContext facesContext, final UIComponent component)
+      throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    // possible values:
+    // - none
+    // - flexLeft (default)
+    // - flexRight
+    // - top
+    // - segmentLeft (todo)
+    // - segmentRight (todo)
+    // - flowLeft (todo)
+    // - flowRight (todo)
+    final LabelLayout labelLayout = getType(component);
+    final CssItem divClass;
+    switch (labelLayout) {
+      case skip:
+        // skip rendering the surrounding element
+        return;
+      case flexLeft:
+      case flexRight:
+        divClass = TobagoClass.FLEX_LAYOUT;
+        break;
+      default: // none, top, segmentLeft, segmentRight, flowLeft, flowRight
+        divClass = null;
+    }
+
+//    if (labelLayout != LabelLayout.none) {
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(component.getClientId(facesContext));
+//    }
+//    writer.writeClassAttribute(divClass, BootstrapClass.maximumSeverity(component));
+    // todo: check if BootstrapClass.FORM_GROUP is needed, I've removed it, because of it's margin-bottom: 15px;
+    // todo: so we lost too much space
+    // todo: without it, e. g. an input field in the header will not be layouted correctly
+//    CssItem extra = ComponentUtils.findAncestor(component, AbstractUILinks.class) != null
+// ? BootstrapClass.FORM_GROUP : null;
+    // TODO: optimize findAncestor() -> set a marker in AbstractUILinks?
+
+//    writer.writeClassAttribute(divClass, extra, BootstrapClass.maximumSeverity(component));
+    writer.writeClassAttribute(
+        divClass,
+        BootstrapClass.FORM_GROUP,
+        BootstrapClass.maximumSeverity(component),
+        ComponentUtils.getBooleanAttribute(component, Attributes.required) ? TobagoClass.REQUIRED : null);
+
+    switch (labelLayout) {
+      case flexLeft:
+        writer.writeAttribute(DataAttributes.LAYOUT, "{\"columns\":[\"auto\",1]}", true);
+        break;
+      case flexRight:
+        writer.writeAttribute(DataAttributes.LAYOUT, "{\"columns\":[1,\"auto\"]}", true);
+        break;
+      default:
+        // nothing to do
+    }
+
+    switch (labelLayout) {
+      case none:
+      case flexRight:
+      case flowRight:
+        break;
+      case segmentLeft:
+        if (LabelLayout.getSegment(facesContext) == LabelLayout.segmentLeft) {
+          encodeLabel(component, writer, labelLayout);
+        }
+        break;
+      case segmentRight:
+        if (LabelLayout.getSegment(facesContext) == LabelLayout.segmentRight) {
+          encodeLabel(component, writer, labelLayout);
+        }
+        break;
+      default:
+        encodeLabel(component, writer, labelLayout);
+    }
+  }
+
+  protected void encodeEndSurrounding(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final LabelLayout labelLayout = getType(component);
+
+    switch (labelLayout) {
+      case skip:
+        return;
+      case flexRight:
+      case flowRight:
+        encodeLabel(component, writer, labelLayout);
+        break;
+      default:
+        // nothing to do
+    }
+
+//    if (labelLayout != LabelLayout.none) {
+    writer.endElement(HtmlElements.DIV);
+//    }
+  }
+
+  protected void encodeLabel(UIComponent component, TobagoResponseWriter writer, LabelLayout labelLayout)
+      throws IOException {
+    // TBD: maybe use an interface for getLabel()
+    final String label = ComponentUtils.getStringAttribute(component, Attributes.label);
+    if (StringUtils.isNotBlank(label)) {
+      writer.startElement(HtmlElements.LABEL);
+      writer.writeAttribute(HtmlAttributes.FOR, component.getClientId(), false);
+      writer.writeClassAttribute(TobagoClass.LABEL, BootstrapClass.COL_FORM_LABEL);
+      if (component instanceof SupportsAccessKey) {
+        LabelWithAccessKey labelWithAccessKey = new LabelWithAccessKey((SupportsAccessKey) component);
+        HtmlRendererUtils.writeLabelWithAccessKey(writer, labelWithAccessKey);
+      } else {
+        writer.writeText(label);
+      }
+      writer.endElement(HtmlElements.LABEL);
+    }
+  }
+
+  private LabelLayout getType(UIComponent component) {
+    return component instanceof SupportsLabelLayout
+        ? ((SupportsLabelLayout) component).getLabelLayout()
+        : LabelLayout.skip;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LabelRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LabelRenderer.java
new file mode 100644
index 0000000..6c84336
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LabelRenderer.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.SupportFieldId;
+import org.apache.myfaces.tobago.component.UILabel;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
+import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PostAddToViewEvent;
+import java.io.IOException;
+
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
+public class LabelRenderer extends RendererBase implements ComponentSystemEventListener {
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) {
+    ComponentUtils.evaluateAutoFor(event.getComponent(), UIInput.class);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UILabel label = (UILabel) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final UIComponent corresponding = ComponentUtils.findFor(label);
+    final String forId;
+    if (corresponding instanceof SupportFieldId) {
+      forId = ((SupportFieldId) corresponding).getFieldId(facesContext);
+    } else {
+      forId = corresponding != null ? corresponding.getClientId(facesContext) : null;
+    }
+    final String clientId = label.getClientId(facesContext);
+
+    // TBD: want to do this in JavaScript in Browser (or CSS)?
+    Markup correspondingMarkup = Markup.NULL;
+    // adding the markups from the corresponding input component
+    if (corresponding != null) {
+      correspondingMarkup = ComponentUtils.updateMarkup(corresponding, Markup.NULL);
+    }
+
+    writer.startElement(HtmlElements.LABEL);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, label);
+    writer.writeClassAttribute(
+        Classes.create(label, correspondingMarkup), BootstrapClass.COL_FORM_LABEL, label.getCustomClass());
+    writer.writeStyleAttribute(label.getStyle());
+    writer.writeIdAttribute(clientId);
+    if (forId != null) {
+      writer.writeAttribute(HtmlAttributes.FOR, forId, false);
+    }
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, label);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+
+    encodeTextContent(facesContext, writer, label);
+
+    writer.endElement(HtmlElements.LABEL);
+  }
+
+  /** Encodes the text inside of the label.
+   * Can be overwritten in other themes.
+   */
+  protected void encodeTextContent(
+      final FacesContext facesContext, final TobagoResponseWriter writer, final UILabel component)
+      throws IOException {
+
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+
+    if (label.getAccessKey() != null) {
+      writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
+      AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), component.getClientId());
+    }
+    HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkRenderer.java
new file mode 100644
index 0000000..26c7d88
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinkRenderer.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+public class LinkRenderer extends CommandRendererBase {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinksRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinksRenderer.java
new file mode 100644
index 0000000..ac0827c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/LinksRenderer.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUILinks;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFormBase;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class LinksRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.startElement(HtmlElements.UL);
+    writer.writeClassAttribute(BootstrapClass.NAV, BootstrapClass.NAVBAR_NAV);
+    writer.writeIdAttribute(component.getClientId(facesContext));
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    for (UIComponent child : component.getChildren()) {
+      if (child.isRendered()) {
+        if (child instanceof AbstractUIFormBase) { // XXX hack! TBD: How to walk through the children, or do that in JS?
+          encodeChildren(facesContext, child);
+        } else {
+          // fixme: only a temporary workaround
+          final AbstractUILinks commands = ComponentUtils.findAncestor(component, AbstractUILinks.class);
+          writer.startElement(HtmlElements.LI);
+          writer.writeClassAttribute(BootstrapClass.NAV_ITEM, BootstrapClass.DROPDOWN);
+          child.encodeAll(facesContext);
+          writer.endElement(HtmlElements.LI);
+        }
+      }
+    }
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.UL);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/MessagesRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/MessagesRenderer.java
new file mode 100644
index 0000000..a70dd2b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/MessagesRenderer.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIMessages;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.Arias;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.List;
+
+public class MessagesRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(MessagesRenderer.class);
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UIMessages messages = (UIMessages) component;
+
+    if (messages.isConfirmation()) {
+      LOG.warn("'confirmation' is currently not supported for tc:messages!");
+    }
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("facesContext is " + facesContext.getClass().getName());
+    }
+    final List<UIMessages.Item> messageList = messages.createMessageList(facesContext);
+
+    if (messageList.size() > 0) { // in ie empty span gets a height
+      writer.writeStyleAttribute(messages.getStyle());
+
+      // with id
+      /*String focusId = null;
+      Iterator clientIds;
+      if (ComponentUtils.getBooleanAttribute(messages, Attributes.globalOnly)) {
+        ArrayList<String> list = new ArrayList<String>(1);
+        list.add(null);
+        clientIds = list.iterator();
+      } else {
+        clientIds = facesContext.getClientIdsWithMessages();
+      }*/
+
+      writer.startElement(HtmlElements.DIV);
+      writer.writeIdAttribute(messages.getClientId(facesContext));
+      writer.writeClassAttribute(Classes.create(messages), messages.getCustomClass());
+
+      FacesMessage.Severity lastSeverity = null;
+      boolean first = true;
+
+      for (final UIMessages.Item item : messageList) {
+        final FacesMessage message = item.getFacesMessage();
+        final FacesMessage.Severity severity = message.getSeverity();
+
+        if (!first && lastSeverity != severity) {
+          writer.endElement(HtmlElements.DIV);
+        }
+
+        if (first || lastSeverity != severity) {
+          writer.startElement(HtmlElements.DIV);
+          writer.writeClassAttribute(
+              BootstrapClass.ALERT, BootstrapClass.ALERT_DISMISSIBLE, BootstrapClass.alert(severity));
+          HtmlRendererUtils.writeDataAttributes(facesContext, writer, messages);
+          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.ALERT.toString(), false);
+
+          writer.startElement(HtmlElements.BUTTON);
+          writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+          writer.writeClassAttribute(BootstrapClass.CLOSE);
+          writer.writeAttribute(DataAttributes.DISMISS, "alert", false);
+          writer.writeAttribute(Arias.ACTIVEDESCENDANT, "Close", false); // todo: i18n
+          writer.startElement(HtmlElements.SPAN);
+          writer.writeAttribute(Arias.HIDDEN, Boolean.TRUE.toString(), false);
+          writer.writeText("×"); // times
+          writer.endElement(HtmlElements.SPAN);
+          writer.endElement(HtmlElements.BUTTON);
+
+        }
+
+        encodeMessage(writer, messages, message, item.getClientId());
+
+        lastSeverity = severity;
+        first = false;
+      }
+      writer.endElement(HtmlElements.DIV); // close open tag from for-loop
+
+      writer.endElement(HtmlElements.DIV);
+/*
+      while(clientIds.hasNext()) {
+        String clientId = (String) clientIds.next();
+        encodeMessagesForId(facesContext, writer, clientId, showSummary, showDetail);
+        if (focusId == null) {
+          focusId = clientId;
+        }
+      }
+  todo: don't forget: focus
+      if (focusId != null) {
+        ComponentUtils.findPage(facesContext, messages).setFocusId(focusId);
+      }
+*/
+      if (messages.getFor() == null) {
+        final String id = messages.getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "messagesExists";
+        writer.startElement(HtmlElements.INPUT);
+        writer.writeAttribute(HtmlAttributes.VALUE, Boolean.TRUE.toString(), false);
+        writer.writeAttribute(HtmlAttributes.ID, id, false);
+        writer.writeAttribute(HtmlAttributes.NAME, id, false);
+        writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+        writer.endElement(HtmlElements.INPUT);
+      }
+    }
+  }
+
+  private void encodeMessage(
+      final TobagoResponseWriter writer, final UIMessages messages, final FacesMessage message, final String clientId)
+      throws IOException {
+
+    final String summary = message.getSummary();
+    final String detail = message.getDetail();
+    writer.startElement(HtmlElements.LABEL);
+    if (clientId != null) {
+      writer.writeAttribute(HtmlAttributes.FOR, clientId, false);
+    }
+    writer.writeAttribute(HtmlAttributes.TITLE, detail, true);
+    boolean writeEmptyText = true;
+    if (summary != null && messages.isShowSummary()) {
+      writer.writeText(summary);
+      writeEmptyText = false;
+      if (detail != null && messages.isShowDetail()) {
+        writer.writeText(" ");
+      }
+    }
+    if (detail != null && messages.isShowDetail()) {
+      writeEmptyText = false;
+      writer.writeText(detail);
+    }
+    if (writeEmptyText) {
+      writer.writeText("");
+    }
+    writer.endElement(HtmlElements.LABEL);
+
+    message.rendered();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ObjectRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ObjectRenderer.java
new file mode 100644
index 0000000..6dc0674
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ObjectRenderer.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIObject;
+import org.apache.myfaces.tobago.context.TobagoResourceBundle;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class ObjectRenderer extends RendererBase {
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UIObject object = (UIObject) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.IFRAME);
+    writer.writeAttribute(HtmlAttributes.FRAMEBORDER, "0", false);
+    final String clientId = object.getClientId(facesContext);
+    writer.writeIdAttribute(clientId);
+    String name = object.getName();
+    if (name == null) {
+      name = clientId;
+    }
+    writer.writeNameAttribute(name);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, object);
+    writer.writeAttribute(HtmlAttributes.SRC, object.getSrc(), true);
+    writer.writeClassAttribute(Classes.create(object), object.getCustomClass());
+    writer.writeStyleAttribute(object.getStyle());
+
+    String noframes = TobagoResourceBundle.getString(facesContext, "browser.noframe.message.prefix");
+    writer.writeText(noframes);
+    writer.writeText(" ");
+    if (object.getSrc() != null) {
+      writer.writeText(object.getSrc());
+    }
+    noframes = TobagoResourceBundle.getString(facesContext, "browser.noframe.message.postfix");
+    writer.writeText(" " + noframes);
+
+    writer.endElement(HtmlElements.IFRAME);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/OperationRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/OperationRenderer.java
new file mode 100644
index 0000000..fc57bba
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/OperationRenderer.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+
+public class OperationRenderer extends RendererBase {
+
+  // no needed
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/OutRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/OutRenderer.java
new file mode 100644
index 0000000..6347bf6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/OutRenderer.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIOut;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.sanitizer.SanitizeMode;
+import org.apache.myfaces.tobago.sanitizer.Sanitizer;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.StringTokenizer;
+
+public class OutRenderer extends LabelLayoutRendererBase {
+
+  @Override
+  public void encodeBeginField(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UIOut out = (UIOut) component;
+
+    String text = RenderUtils.currentValue(out);
+    if (text == null) {
+      text = "";
+    }
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final boolean escape = out.isEscape();
+    final boolean createSpan = out.isCreateSpan();
+
+    if (createSpan) {
+      writer.startElement(HtmlElements.SPAN);
+      HtmlRendererUtils.writeDataAttributes(facesContext, writer, out);
+      writer.writeStyleAttribute(out.getStyle());
+      writer.writeClassAttribute(Classes.create(out), BootstrapClass.FORM_CONTROL_STATIC, out.getCustomClass());
+      final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, out);
+      if (title != null) {
+        writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+      }
+    }
+    if (escape) {
+      final StringTokenizer tokenizer = new StringTokenizer(text, "\r\n");
+      while (tokenizer.hasMoreTokens()) {
+        final String token = tokenizer.nextToken();
+        writer.writeText(token);
+        if (tokenizer.hasMoreTokens()) {
+          writer.startElement(HtmlElements.BR);
+          writer.endElement(HtmlElements.BR);
+        }
+      }
+    } else { // escape="false"
+      writer.writeText("", null); // to ensure the closing > of the <span> start tag.
+      if (SanitizeMode.auto == out.getSanitize()) {
+        final Sanitizer sanitizer = TobagoConfig.getInstance(facesContext).getSanitizer();
+        text = sanitizer.sanitize(text);
+      }
+      writer.write(text);
+    }
+  }
+
+  @Override
+  public void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UIOut out = (UIOut) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final boolean createSpan = out.isCreateSpan();
+
+    if (createSpan) {
+      writer.endElement(HtmlElements.SPAN);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
new file mode 100644
index 0000000..a416958
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PageRenderer.java
@@ -0,0 +1,408 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.application.ProjectStage;
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.UIPage;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.TobagoContext;
+import org.apache.myfaces.tobago.context.TobagoResourceBundle;
+import org.apache.myfaces.tobago.internal.component.AbstractUIPage;
+import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
+import org.apache.myfaces.tobago.internal.util.CookieUtils;
+import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.MimeTypeUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.ResponseUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.portlet.PortletUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.Secret;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.Application;
+import javax.faces.application.ViewHandler;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.portlet.MimeResponse;
+import javax.portlet.ResourceURL;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+// currently using tobago-jsf.js instead
+//@ResourceDependency(name="jsf.js", library="javax.faces", target="head")
+public class PageRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(PageRenderer.class);
+
+  private static final String LAST_FOCUS_ID = "lastFocusId";
+  private static final String HEAD_TARGET = "head";
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+
+    final AbstractUIPage page = (AbstractUIPage) component;
+    final String clientId = page.getClientId(facesContext);
+    final ExternalContext externalContext = facesContext.getExternalContext();
+
+    // last focus
+    final String lastFocusId =
+        externalContext.getRequestParameterMap().get(clientId + ComponentUtils.SUB_SEPARATOR + LAST_FOCUS_ID);
+    if (lastFocusId != null) {
+      FacesContextUtils.setFocusId(facesContext, lastFocusId);
+    }
+  }
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UIPage page = (UIPage) component;
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(facesContext);
+
+    if (FacesContextUtils.getFocusId(facesContext) == null && !StringUtils.isBlank(page.getFocusId())) {
+      FacesContextUtils.setFocusId(facesContext, page.getFocusId());
+    }
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    // reset responseWriter and render page
+    facesContext.setResponseWriter(writer);
+
+    ResponseUtils.ensureNoCacheHeader(facesContext);
+
+    ResponseUtils.ensureContentSecurityPolicyHeader(facesContext, tobagoConfig.getContentSecurityPolicy());
+
+    if (LOG.isDebugEnabled()) {
+      for (final Object o : page.getAttributes().entrySet()) {
+        final Map.Entry entry = (Map.Entry) o;
+        LOG.debug("*** '" + entry.getKey() + "' -> '" + entry.getValue() + "'");
+      }
+    }
+
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    final String contextPath = externalContext.getRequestContextPath();
+    final Object request = externalContext.getRequest();
+    final Object response = externalContext.getResponse();
+    final Application application = facesContext.getApplication();
+    final ViewHandler viewHandler = application.getViewHandler();
+    final UIViewRoot viewRoot = facesContext.getViewRoot();
+    final String viewId = viewRoot.getViewId();
+    final String formAction = externalContext.encodeActionURL(viewHandler.getActionURL(facesContext, viewId));
+    final String partialAction;
+    final boolean portlet = PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse;
+    if (portlet) {
+      final MimeResponse mimeResponse = (MimeResponse) response;
+      final ResourceURL resourceURL = mimeResponse.createResourceURL();
+      partialAction = externalContext.encodeResourceURL(resourceURL.toString());
+    } else {
+      partialAction = null;
+    }
+
+    final String contentType = writer.getContentTypeWithCharSet();
+    ResponseUtils.ensureContentTypeHeader(facesContext, contentType);
+    if (tobagoConfig.isSetNosniffHeader()) {
+      ResponseUtils.ensureNosniffHeader(facesContext);
+    }
+
+    final Theme theme = TobagoContext.getInstance(facesContext).getTheme();
+    if (response instanceof HttpServletResponse && request instanceof HttpServletRequest) {
+      CookieUtils.setThemeNameToCookie((HttpServletRequest) request, (HttpServletResponse) response, theme.getName());
+    }
+
+    final String clientId = page.getClientId(facesContext);
+    final boolean productionMode = tobagoConfig.getProjectStage() == ProjectStage.Production;
+    final boolean preventFrameAttacks = tobagoConfig.isPreventFrameAttacks();
+    final Markup markup = page.getMarkup();
+    final TobagoClass spread = markup != null && markup.contains(Markup.SPREAD) ? TobagoClass.SPREAD : null;
+
+    if (!facesContext.getPartialViewContext().isAjaxRequest()) {
+      final String title = page.getLabel();
+
+      if (!PortletUtils.isPortletApiAvailable() || !(response instanceof MimeResponse)) {
+        writer.startElement(HtmlElements.HTML);
+        final Locale locale = viewRoot.getLocale();
+        if (locale != null) {
+          final String language = locale.getLanguage();
+          if (language != null) {
+            writer.writeAttribute(HtmlAttributes.LANG, language, false);
+          }
+        }
+      }
+      writer.writeClassAttribute(spread);
+
+      writer.startElement(HtmlElements.HEAD);
+
+      // meta tags
+
+      // this is needed, because websphere 6.0? ignores the setting of the content type on the response
+      writer.startElement(HtmlElements.META);
+      writer.writeAttribute(HtmlAttributes.HTTP_EQUIV, "Content-Type", false);
+      writer.writeAttribute(HtmlAttributes.CONTENT, contentType, false);
+      writer.endElement(HtmlElements.META);
+
+      writer.startElement(HtmlElements.META);
+      writer.writeAttribute(HtmlAttributes.NAME, "viewport", false);
+      writer.writeAttribute(HtmlAttributes.CONTENT, "width=device-width, initial-scale=1.0", false);
+      writer.endElement(HtmlElements.META);
+
+      // title
+      writer.startElement(HtmlElements.TITLE);
+      writer.writeText(title != null ? title : "");
+      writer.endElement(HtmlElements.TITLE);
+
+      // style files from theme
+      for (final String styleFile : theme.getStyleResources(productionMode)) {
+        writeStyle(writer, contextPath + styleFile);
+      }
+
+      // style files individual files
+      for (final String styleFile : FacesContextUtils.getStyleFiles(facesContext)) {
+        writeStyle(writer, styleFile);
+      }
+
+      if (!productionMode) {
+        checkDuplicates(theme.getStyleResources(productionMode), FacesContextUtils.getStyleFiles(facesContext));
+      }
+
+      final String icon = page.getApplicationIcon();
+      if (icon != null) {
+        writer.startElement(HtmlElements.LINK);
+        if (icon.endsWith(".ico")) {
+          writer.writeAttribute(HtmlAttributes.REL, "shortcut icon", false);
+          writer.writeAttribute(HtmlAttributes.HREF, icon, true);
+        } else {
+          // XXX IE only supports ICO files for favicons
+          writer.writeAttribute(HtmlAttributes.REL, "icon", false);
+          writer.writeAttribute(HtmlAttributes.TYPE, MimeTypeUtils.getMimeTypeForFile(icon), true);
+          writer.writeAttribute(HtmlAttributes.HREF, icon, true);
+        }
+        writer.endElement(HtmlElements.LINK);
+      }
+      List<UIComponent> componentResources = viewRoot.getComponentResources(facesContext, HEAD_TARGET);
+
+      for (int i = 0, childCount = componentResources.size(); i < childCount; i++) {
+        UIComponent child = componentResources.get(i);
+        // XXX hack to remove jsf.js
+        if ("jsf.js".equals(child.getAttributes().get("name"))) {
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("Skip rendering resource jsf.js");
+          }
+          continue;
+        }
+        child.encodeAll(facesContext);
+      }
+
+      // script files from theme
+      for (final String scriptFile : theme.getScriptResources(productionMode)) {
+        encodeScript(writer, contextPath + scriptFile);
+      }
+
+      // script files individual files
+      for (final String scriptFile : FacesContextUtils.getScriptFiles(facesContext)) {
+        encodeScript(writer, scriptFile);
+      }
+
+      if (!productionMode) {
+        checkDuplicates(theme.getScriptResources(productionMode), FacesContextUtils.getScriptFiles(facesContext));
+      }
+
+      writer.endElement(HtmlElements.HEAD);
+    }
+
+    writer.startElement(portlet ? HtmlElements.DIV : HtmlElements.BODY);
+    writer.writeClassAttribute(
+        portlet ? Classes.create(page, Markup.PORTLET) : Classes.create(page),
+        BootstrapClass.CONTAINER_FLUID,
+        spread,
+        page.getCustomClass());
+    writer.writeIdAttribute(clientId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, page);
+    writer.writeStyleAttribute(page.getStyle());
+
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, page)));
+
+    writer.startElement(HtmlElements.FORM);
+    writer.writeClassAttribute(
+        preventFrameAttacks && !facesContext.getPartialViewContext().isAjaxRequest()
+            ? Classes.create(page, "preventFrameAttacks", Markup.NULL)
+            : null,
+        spread);
+    writer.writeAttribute(HtmlAttributes.ACTION, formAction, true);
+    if (partialAction != null) {
+      writer.writeAttribute(DataAttributes.PARTIAL_ACTION, partialAction, true);
+    }
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("partial action = " + partialAction);
+    }
+    writer.writeIdAttribute(page.getFormId(facesContext));
+    writer.writeAttribute(HtmlAttributes.METHOD, getMethod(page), false);
+    final String enctype = FacesContextUtils.getEnctype(facesContext);
+    if (enctype != null) {
+      writer.writeAttribute(HtmlAttributes.ENCTYPE, enctype, false);
+    }
+    // TODO: enable configuration of  'accept-charset'
+    writer.writeAttribute(HtmlAttributes.ACCEPT_CHARSET, AbstractUIPage.FORM_ACCEPT_CHARSET, false);
+    // TODO evaluate 'accept' attribute usage
+    //writer.writeAttribute(HtmlAttributes.ACCEPT, );
+    writer.writeAttribute(DataAttributes.CONTEXT_PATH, contextPath, true);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeNameAttribute("javax.faces.source");
+    writer.writeIdAttribute("javax.faces.source");
+    writer.writeAttribute(HtmlAttributes.DISABLED, true);
+    writer.endElement(HtmlElements.INPUT);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeNameAttribute(clientId + ComponentUtils.SUB_SEPARATOR + "lastFocusId");
+    writer.writeIdAttribute(clientId + ComponentUtils.SUB_SEPARATOR + "lastFocusId");
+    writer.writeAttribute(HtmlAttributes.VALUE, FacesContextUtils.getFocusId(facesContext), true);
+    writer.endElement(HtmlElements.INPUT);
+
+    if (TobagoConfig.getInstance(FacesContext.getCurrentInstance()).isCheckSessionSecret()) {
+      Secret.encode(facesContext, writer);
+    }
+
+    if (component.getFacet("backButtonDetector") != null) {
+      final UIComponent hidden = component.getFacet("backButtonDetector");
+      RenderUtils.encode(facesContext, hidden);
+    }
+
+// TODO: this is needed for the "BACK-BUTTON-PROBLEM"
+// but may no longer needed
+/*
+    if (ViewHandlerImpl.USE_VIEW_MAP) {
+      writer.startElement(HtmlElements.INPUT, null);
+      writer.writeAttribute(HtmlAttributes.type, "hidden", null);
+      writer.writeNameAttribute(ViewHandlerImpl.PAGE_ID);
+      writer.writeIdAttribute(ViewHandlerImpl.PAGE_ID);
+      Object value = facesContext.getViewRoot().getAttributes().get(
+          ViewHandlerImpl.PAGE_ID);
+      writer.writeAttribute(HtmlAttributes.value, (value != null ? value : ""), null);
+      writer.endElement(HtmlElements.INPUT);
+    }
+*/
+  }
+
+  private void checkDuplicates(final String[] resources, final Collection<String> files) {
+    for (final String resource : resources) {
+      if (files.contains(resource)) {
+        throw new RuntimeException("The resource '" + resource + "' will be included twice! "
+            + "The resource is in the theme list, and explicit in the page. "
+            + "Please remove it from the page!");
+      }
+    }
+  }
+
+  private void writeStyle(final TobagoResponseWriter writer, final String style) throws IOException {
+    writer.startElement(HtmlElements.LINK);
+    writer.writeAttribute(HtmlAttributes.REL, "stylesheet", false);
+    writer.writeAttribute(HtmlAttributes.HREF, style, true);
+//    writer.writeAttribute(HtmlAttributes.MEDIA, "screen", false);
+    writer.writeAttribute(HtmlAttributes.TYPE, "text/css", false);
+    writer.endElement(HtmlElements.LINK);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UIPage page = (UIPage) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final String clientId = page.getClientId(facesContext);
+    final Application application = facesContext.getApplication();
+    final ViewHandler viewHandler = application.getViewHandler();
+
+    // placeholder for menus
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(TobagoClass.PAGE__MENU_STORE);
+    writer.endElement(HtmlElements.DIV);
+
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeIdAttribute(clientId + ComponentUtils.SUB_SEPARATOR + "jsf-state-container");
+    writer.flush();
+    if (!facesContext.getPartialViewContext().isAjaxRequest()) {
+      viewHandler.writeState(facesContext);
+    }
+    writer.endElement(HtmlElements.SPAN);
+
+    writer.endElement(HtmlElements.FORM);
+
+    writer.startElement(HtmlElements.NOSCRIPT);
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(Classes.create(page, "noscript"));
+    writer.writeText(TobagoResourceBundle.getString(facesContext, "pageNoscript"));
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.NOSCRIPT);
+
+    final Object response = facesContext.getExternalContext().getResponse();
+    if (PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse) {
+      writer.endElement(HtmlElements.DIV);
+    } else {
+      writer.endElement(HtmlElements.BODY);
+      writer.endElement(HtmlElements.HTML);
+    }
+
+    AccessKeyLogger.logStatus(facesContext);
+
+    if (facesContext.getExternalContext().getRequestParameterMap().get("X") != null) {
+      throw new RuntimeException("Debugging activated via X parameter");
+    }
+  }
+
+  private void encodeScript(final TobagoResponseWriter writer, final String script) throws IOException {
+    writer.startElement(HtmlElements.SCRIPT);
+    writer.writeAttribute(HtmlAttributes.SRC, script, true);
+//   XXX with defer activated, pages are not shown reliable
+//        writer.writeAttribute(HtmlAttributes.DEFER, true);
+    writer.writeAttribute(HtmlAttributes.TYPE, "text/javascript", false);
+    writer.endElement(HtmlElements.SCRIPT);
+  }
+
+  private String getMethod(final UIPage page) {
+    return ComponentUtils.getStringAttribute(page, Attributes.method, "post");
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRenderer.java
new file mode 100644
index 0000000..f18417d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRenderer.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.UIPanel;
+import org.apache.myfaces.tobago.component.UIReload;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.model.CollapseMode;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class PanelRenderer extends PanelRendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UIPanel panel = (UIPanel) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final String clientId = panel.getClientId(facesContext);
+    final boolean collapsed = panel.isCollapsed();
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(clientId);
+    writer.writeClassAttribute(
+        Classes.create(panel),
+        panel.getCustomClass(),
+        collapsed ? TobagoClass.COLLAPSED : null);
+    writer.writeStyleAttribute(panel.getStyle());
+
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, panel);
+    final String tip = panel.getTip();
+    if (tip != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
+    }
+
+    final UIComponent reloadFacet = ComponentUtils.getFacet(panel, Facets.reload);
+    if (reloadFacet instanceof UIReload && reloadFacet.isRendered()) {
+      final UIReload update = (UIReload) reloadFacet;
+      writer.writeAttribute(DataAttributes.RELOAD, Integer.toString(update.getFrequency()), false);
+    }
+
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, panel)));
+
+    if (panel.getCollapsedMode() != CollapseMode.none) {
+      encodeHidden(writer, clientId, collapsed);
+    }
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRendererBase.java
new file mode 100644
index 0000000..7020b7e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PanelRendererBase.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUICollapsiblePanel;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.Map;
+
+public class PanelRendererBase extends RendererBase {
+
+  private static final String SUFFIX_COLLAPSE = "collapse";
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    super.decode(facesContext, component);
+
+    final AbstractUICollapsiblePanel collapsible = (AbstractUICollapsiblePanel) component;
+    final String clientId = collapsible.getClientId(facesContext);
+    final String hiddenId = clientId + ComponentUtils.SUB_SEPARATOR + SUFFIX_COLLAPSE;
+
+    final Map<String, String> requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
+    if (requestParameterMap.containsKey(hiddenId)) {
+      final String newValue = requestParameterMap.get(hiddenId);
+      if (StringUtils.isNotBlank(newValue)) {
+        collapsible.setSubmittedCollapsed(Boolean.valueOf(newValue));
+      }
+    }
+  }
+
+  protected void encodeHidden(final TobagoResponseWriter writer, final String clientId, final boolean collapsed)
+      throws IOException {
+    final String hiddenId = clientId + ComponentUtils.SUB_SEPARATOR + SUFFIX_COLLAPSE;
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeNameAttribute(hiddenId);
+    writer.writeIdAttribute(hiddenId);
+    writer.writeAttribute(HtmlAttributes.VALUE, Boolean.toString(collapsed), false);
+    writer.endElement(HtmlElements.INPUT);
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
+    if (((AbstractUICollapsiblePanel) component).isNormalLifecycle()) {
+      super.encodeChildren(facesContext, component);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PopupRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PopupRenderer.java
new file mode 100644
index 0000000..0a229f8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/PopupRenderer.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIPopup;
+import org.apache.myfaces.tobago.model.CollapseMode;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class PopupRenderer extends PanelRendererBase {
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final AbstractUIPopup popup = (AbstractUIPopup) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final String clientId = popup.getClientId(facesContext);
+    final boolean collapsed = popup.isCollapsed();
+
+    ComponentUtils.putDataAttribute(popup, "backdrop", "static");
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(
+        Classes.create(popup),
+        BootstrapClass.MODAL,
+        BootstrapClass.FADE,
+        popup.getCustomClass());
+    writer.writeIdAttribute(clientId);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, -1);
+    writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.DIALOG.toString(), false);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, popup);
+    // todo: aria-labelledby
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.MODAL_DIALOG);
+    writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.DOCUMENT.toString(), false);
+/*
+    final Style style = new Style();
+    style.setWidth(popup.getWidth());
+    style.setHeight(popup.getHeight());
+    writer.writeStyleAttribute(style);
+*/
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.MODAL_CONTENT);
+
+    if (popup.getCollapsedMode() != CollapseMode.none) {
+      encodeHidden(writer, clientId, collapsed);
+    }
+  }
+
+  @Override
+  public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ProgressRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ProgressRenderer.java
new file mode 100644
index 0000000..aa0ad64
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ProgressRenderer.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIProgress;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class ProgressRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ProgressRenderer.class);
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UIProgress progress = (UIProgress) component;
+
+    final double value = progress.getRangeValue();
+    final double max = progress.getRangeMax();
+
+    String title = progress.getTip();
+    if (title == null && max > 0) {
+      title = Integer.toString((int) (value / max)) + " %";
+    }
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.PROGRESS);
+    writer.writeIdAttribute(progress.getClientId(facesContext));
+    writer.writeClassAttribute(Classes.create(progress), progress.getCustomClass(), BootstrapClass.PROGRESS);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, progress);
+    writer.writeStyleAttribute(progress.getStyle());
+    writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    writer.writeAttribute(HtmlAttributes.MAX, Double.toString(max), false);
+    writer.writeAttribute(HtmlAttributes.VALUE, Double.toString(value), false);
+
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, progress)));
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.PROGRESS);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/RowRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/RowRenderer.java
new file mode 100644
index 0000000..2e09c16
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/RowRenderer.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIEvent;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.ActionEvent;
+
+public class RowRenderer extends DecodingCommandRendererBase {
+
+  // XXX hack to fix TOBAGO-1572
+  @Override
+  protected void commandActivated(UIComponent component) {
+
+    AbstractUIEvent event = null;
+    for (UIComponent uiComponent : component.getChildren()) {
+      if (uiComponent instanceof AbstractUIEvent) {
+        event = (AbstractUIEvent) uiComponent;
+      }
+    }
+    if (event != null) {
+      event.queueEvent(new ActionEvent(event));
+    } else {
+      component.queueEvent(new ActionEvent(component));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ScriptRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ScriptRenderer.java
new file mode 100644
index 0000000..f3a26cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/ScriptRenderer.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIScript;
+import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PostAddToViewEvent;
+
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
+public class ScriptRenderer extends RendererBase implements ComponentSystemEventListener {
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final UIScript scriptComponent = (UIScript) event.getComponent();
+    final String file = scriptComponent.getFile();
+    if (file != null) {
+      FacesContextUtils.addScriptFile(facesContext, file);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SectionRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SectionRenderer.java
new file mode 100644
index 0000000..6d63f75
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SectionRenderer.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.internal.component.AbstractUISection;
+import org.apache.myfaces.tobago.model.CollapseMode;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class SectionRenderer extends PanelRendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUISection section = (AbstractUISection) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final String clientId = section.getClientId(facesContext);
+    final boolean collapsed = section.isCollapsed();
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(clientId);
+    writer.writeClassAttribute(
+        Classes.create(section),
+        collapsed ? TobagoClass.COLLAPSED : null,
+        section.getCustomClass());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, section);
+
+    String label = section.getLabelToRender();
+    final HtmlElements tag;
+    switch (section.getLevel()) {
+      case 1:
+        tag = HtmlElements.H1;
+        break;
+      case 2:
+        tag = HtmlElements.H2;
+        break;
+      case 3:
+        tag = HtmlElements.H3;
+        break;
+      case 4:
+        tag = HtmlElements.H4;
+        break;
+      case 5:
+        tag = HtmlElements.H5;
+        break;
+      default:
+        tag = HtmlElements.H6;
+    }
+
+    if (section.getCollapsedMode() != CollapseMode.none) {
+      encodeHidden(writer, clientId, collapsed);
+    }
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(TobagoClass.SECTION__HEADER);
+    writer.startElement(tag);
+    final String image = section.getImage();
+    HtmlRendererUtils.encodeIconWithLabel(writer, image, label);
+    writer.endElement(tag);
+
+    final UIComponent bar = ComponentUtils.getFacet(section, Facets.bar);
+    if (bar != null) {
+      RenderUtils.encode(facesContext, bar);
+    }
+
+    writer.endElement(HtmlElements.DIV);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(TobagoClass.SECTION__CONTENT);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SegmentLayoutRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SegmentLayoutRenderer.java
new file mode 100644
index 0000000..e6e51a7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SegmentLayoutRenderer.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.SupportsLabelLayout;
+import org.apache.myfaces.tobago.component.UISegmentLayout;
+import org.apache.myfaces.tobago.internal.component.AbstractUISegmentLayout;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Renders the 12 columns grid layout.
+ */
+public class SegmentLayoutRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SegmentLayoutRenderer.class);
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final AbstractUISegmentLayout layout = (AbstractUISegmentLayout) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.DIV);
+//    writer.writeClassAttribute(BootstrapClass.FORM_HORIZONTAL, BootstrapClass.CONTAINER_FLUID);
+    writer.writeClassAttribute(Classes.create(layout), BootstrapClass.ROW);
+//    writer.writeClassAttribute(Classes.create(layout), BootstrapClass.FORM_GROUP);
+    writer.writeIdAttribute(layout.getClientId(facesContext));
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final UISegmentLayout segmentLayout = (UISegmentLayout) component;
+
+    if (!segmentLayout.isRendered()) {
+      return;
+    }
+
+    final List<UIComponent> children = segmentLayout.getChildren();
+    final BootstrapClass.Generator generator = new BootstrapClass.Generator(
+        segmentLayout.getExtraSmall(),
+        segmentLayout.getSmall(),
+        segmentLayout.getMedium(),
+        segmentLayout.getLarge());
+    for (UIComponent child : children) {
+      if (child.isRendered()) {
+        encodeChild(facesContext, writer, generator, child);
+      }
+    }
+  }
+
+  private void encodeChild(
+      final FacesContext facesContext, final TobagoResponseWriter writer,
+      final BootstrapClass.Generator generator, final UIComponent child) throws IOException {
+
+    if (child instanceof SupportsLabelLayout
+        && LabelLayout.isSegment(((SupportsLabelLayout) child).getLabelLayout())) {
+
+      // left part
+      LabelLayout.setSegment(facesContext, LabelLayout.segmentLeft);
+      encodeDiv(facesContext, writer, generator, child);
+      generator.next();
+
+      // right part
+      LabelLayout.setSegment(facesContext, LabelLayout.segmentRight);
+      encodeDiv(facesContext, writer, generator, child);
+      generator.next();
+
+      LabelLayout.removeSegment(facesContext);
+    } else { // normal case
+      encodeDiv(facesContext, writer, generator, child);
+      generator.next();
+    }
+  }
+
+  private void encodeDiv(
+      FacesContext facesContext, TobagoResponseWriter writer, BootstrapClass.Generator generator, UIComponent child)
+      throws IOException {
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(null, null, generator.generate());
+    RenderUtils.encode(facesContext, child);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectBooleanCheckboxRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectBooleanCheckboxRenderer.java
new file mode 100644
index 0000000..2da9360
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectBooleanCheckboxRenderer.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUISelectBooleanCheckbox;
+import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
+import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class SelectBooleanCheckboxRenderer extends LabelLayoutRendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SelectBooleanCheckboxRenderer.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+
+    final UIInput input = (UIInput) component;
+
+    if (ComponentUtils.isOutputOnly(input)) {
+      return;
+    }
+
+    final String newValue = facesContext.getExternalContext()
+        .getRequestParameterMap().get(input.getClientId(facesContext));
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("new value = '" + newValue + "'");
+    }
+
+    input.setSubmittedValue("true".equals(newValue) ? "true" : "false");
+
+    RenderUtils.decodeClientBehaviors(facesContext, input);
+  }
+
+  @Override
+  protected void encodeBeginField(FacesContext facesContext, UIComponent component) throws IOException {
+    final AbstractUISelectBooleanCheckbox select = (AbstractUISelectBooleanCheckbox) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String clientId = select.getClientId(facesContext);
+    final String fieldId = select.getFieldId(facesContext);
+    final String currentValue = getCurrentValue(facesContext, select);
+    final boolean checked = "true".equals(currentValue);
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+    final boolean disabled = select.isDisabled();
+    final LabelWithAccessKey label = new LabelWithAccessKey(select, true);
+    final String itemLabel = select.getItemLabel();
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(clientId);
+    writer.writeStyleAttribute(select.getStyle());
+    writer.writeClassAttribute(
+        Classes.create(select),
+        BootstrapClass.FORM_CHECK,
+        disabled ? BootstrapClass.DISABLED : null,
+        select.getCustomClass());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+
+    writer.startElement(HtmlElements.LABEL);
+    writer.writeClassAttribute(BootstrapClass.FORM_CHECK_LABEL);
+    if (!disabled && label.getAccessKey() != null) {
+      writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
+      AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), clientId);
+    }
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
+    writer.writeAttribute(HtmlAttributes.VALUE, "true", false);
+    writer.writeNameAttribute(clientId);
+    writer.writeIdAttribute(fieldId);
+    writer.writeAttribute(HtmlAttributes.CHECKED, checked);
+    writer.writeAttribute(HtmlAttributes.READONLY, select.isReadonly());
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeAttribute(HtmlAttributes.REQUIRED, select.isRequired());
+    HtmlRendererUtils.renderFocus(clientId, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+    writer.endElement(HtmlElements.INPUT);
+
+    if (itemLabel != null) {
+      writer.writeText(itemLabel);
+    }
+  }
+
+  @Override
+  protected void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.LABEL);
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectItemsRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectItemsRenderer.java
new file mode 100644
index 0000000..13fcf13
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectItemsRenderer.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+
+public class SelectItemsRenderer extends RendererBase {
+
+}
+
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyCheckboxRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyCheckboxRenderer.java
new file mode 100644
index 0000000..71caf3f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyCheckboxRenderer.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UISelectManyCheckbox;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.IOException;
+
+public class SelectManyCheckboxRenderer extends SelectManyRendererBase {
+
+  @Override
+  public void encodeBeginField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UISelectManyCheckbox select = (UISelectManyCheckbox) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String id = select.getClientId(facesContext);
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+    final boolean disabled = select.isDisabled();
+    final boolean readonly = select.isReadonly();
+    final boolean required = select.isRequired();
+    final boolean inline = select.isInline();
+
+    writer.startElement(HtmlElements.OL);
+    writer.writeStyleAttribute(select.getStyle());
+    writer.writeClassAttribute(
+        Classes.create(select),
+        inline ? TobagoClass.SELECT_MANY_CHECKBOX__INLINE : null,
+        select.getCustomClass());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+    boolean first = true;
+    final Object[] values = select.getSelectedValues();
+    final String[] submittedValues = getSubmittedValues(select);
+    int i = 0;
+    for (final SelectItem item : SelectItemUtils.getItemIterator(facesContext, select)) {
+      final boolean itemDisabled = item.isDisabled() || disabled;
+      final String itemId = id + ComponentUtils.SUB_SEPARATOR + i++;
+      writer.startElement(HtmlElements.LI);
+      writer.writeClassAttribute(
+          BootstrapClass.FORM_CHECK,
+          inline ? BootstrapClass.FORM_CHECK_INLINE : null,
+          itemDisabled ? BootstrapClass.DISABLED : null);
+      writer.startElement(HtmlElements.LABEL);
+      writer.writeClassAttribute(BootstrapClass.FORM_CHECK_LABEL);
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeClassAttribute(BootstrapClass.FORM_CHECK_INPUT);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
+      final String formattedValue = ComponentUtils.getFormattedValue(facesContext, select, item.getValue());
+      boolean checked;
+      if (submittedValues == null) {
+        checked = RenderUtils.contains(values, item.getValue());
+      } else {
+        checked = RenderUtils.contains(submittedValues, formattedValue);
+      }
+      writer.writeAttribute(HtmlAttributes.CHECKED, checked);
+      writer.writeNameAttribute(id);
+      writer.writeIdAttribute(itemId);
+      writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
+      writer.writeAttribute(HtmlAttributes.DISABLED, itemDisabled);
+      writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+      writer.writeAttribute(HtmlAttributes.REQUIRED, required);
+      if (first) {
+        HtmlRendererUtils.renderFocus(id, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
+        first = false;
+      }
+      writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+      writer.endElement(HtmlElements.INPUT);
+
+      final String label = item.getLabel();
+      if (label != null) {
+        writer.writeText(label);
+      }
+
+      writer.endElement(HtmlElements.LABEL);
+      writer.endElement(HtmlElements.LI);
+    }
+  }
+
+  @Override
+  public void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.OL);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListboxRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListboxRenderer.java
new file mode 100644
index 0000000..11cde8e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyListboxRenderer.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UISelectManyListbox;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.IOException;
+import java.util.List;
+
+public class SelectManyListboxRenderer extends SelectManyRendererBase {
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeBeginField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UISelectManyListbox select = (UISelectManyListbox) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String clientId = select.getClientId(facesContext);
+    final String fieldId = select.getFieldId(facesContext);
+    final List<SelectItem> items = SelectItemUtils.getItemList(facesContext, select);
+    final boolean readonly = select.isReadonly();
+    final boolean disabled = !items.iterator().hasNext() || select.isDisabled() || readonly;
+    Integer size = select.getSize();
+    size = Math.max(size != null ? size : items.size(), 2); // must be > 1
+
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+    writer.startElement(HtmlElements.SELECT);
+    writer.writeIdAttribute(fieldId);
+    writer.writeNameAttribute(clientId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+    writer.writeAttribute(HtmlAttributes.REQUIRED, select.isRequired());
+    HtmlRendererUtils.renderFocus(clientId, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+    writer.writeStyleAttribute(select.getStyle());
+    writer.writeClassAttribute(Classes.create(select), BootstrapClass.FORM_CONTROL, select.getCustomClass());
+    writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
+    writer.writeAttribute(HtmlAttributes.SIZE, size);
+    writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+    final Object[] values = select.getSelectedValues();
+    final String[] submittedValues = getSubmittedValues(select);
+
+    HtmlRendererUtils.renderSelectItems(select, items, values, submittedValues, writer, facesContext);
+  }
+
+  @Override
+  public void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.SELECT);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java
new file mode 100644
index 0000000..394c694
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyRendererBase.java
@@ -0,0 +1,810 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.util.ArrayUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.FacesException;
+import javax.faces.application.ProjectStage;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UISelectItem;
+import javax.faces.component.UISelectItems;
+import javax.faces.component.UISelectMany;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
+import java.lang.reflect.Array;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Queue;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+public abstract class SelectManyRendererBase extends LabelLayoutRendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SelectManyRendererBase.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    if (ComponentUtils.isOutputOnly(component)) {
+      return;
+    }
+
+    final UISelectMany select = (UISelectMany) component;
+
+    String[] newValues =
+        facesContext.getExternalContext().getRequestParameterValuesMap().get(select.getClientId(facesContext));
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("decode: key='" + component.getClientId(facesContext)
+          + "' value='" + Arrays.toString(newValues) + "'");
+      LOG.debug("size ... '" + (newValues != null ? newValues.length : -1) + "'");
+      if (newValues != null) {
+        for (final String newValue : newValues) {
+          LOG.debug("newValues[i] = '" + newValue + "'");
+        }
+      }
+    }
+
+    if (newValues == null) {
+      newValues = ArrayUtils.EMPTY_STRING_ARRAY; // because no selection will not submitted by browsers
+    }
+    select.setSubmittedValue(newValues);
+
+    RenderUtils.decodeClientBehaviors(facesContext, select);
+  }
+
+  public String[] getSubmittedValues(UIInput input) {
+    return (String[]) input.getSubmittedValue();
+  }
+
+  @Override
+  public Object getConvertedValue(
+      final FacesContext facesContext, final UIComponent component, final Object submittedValue)
+      throws ConverterException {
+
+    if (submittedValue == null) {
+      return null;
+    } else {
+      if (!(submittedValue instanceof String[])) {
+        throw new ConverterException("Submitted value not of type String[] for component : "
+            + component.getClientId(facesContext) + "expected");
+      }
+    }
+    return getConvertedUISelectManyValue(facesContext, (UISelectMany) component, (String[]) submittedValue);
+  }
+
+  // #################################################################################################################
+  // #################################################################################################################
+  // ###  The following methods and classes are copied from myfaces api 2.2.8,
+  // ###  slightly modified to compile in this context.
+  // ###  We copy this to avoid the dependency
+  // #################################################################################################################
+  // #################################################################################################################
+
+  // #################################################################################################################
+  // ### BEGIN copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_SharedRendererUtils.java
+  // #################################################################################################################
+  static final String COLLECTION_TYPE_KEY = "collectionType";
+  static final String VALUE_TYPE_KEY = "valueType";
+
+  static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany component,
+                                              String[] submittedValue) throws ConverterException {
+    return getConvertedUISelectManyValue(facesContext, component,
+        submittedValue, false);
+  }
+
+  /**
+   * Gets the converted value of a UISelectMany component.
+   * If the considerValueType is true, this method will also consider the
+   * valueType attribute of Tomahawk UISelectMany components.
+   *
+   * @param facesContext
+   * @param component
+   * @param submittedValue
+   * @param considerValueType
+   * @return
+   * @throws ConverterException
+   */
+  static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany component,
+                                              String[] submittedValue, boolean considerValueType)
+      throws ConverterException {
+    // Attention!
+    // This code is duplicated in shared renderkit package (except for considerValueType).
+    // If you change something here please do the same in the other class!
+
+    if (submittedValue == null) {
+      throw new NullPointerException("submittedValue");
+    }
+
+    ValueExpression expression = component.getValueExpression("value");
+    Object targetForConvertedValues = null;
+
+    // if the component has an attached converter, use it
+    Converter converter = component.getConverter();
+    // at this point the valueType attribute is handled in shared.
+    if (converter == null && considerValueType) {
+      // try to get a converter from the valueType attribute
+      converter = getValueTypeConverter(facesContext, component);
+    }
+
+    if (expression != null) {
+      Class<?> modelType = expression
+          .getType(facesContext.getELContext());
+      if (modelType == null) {
+        // FIXME temporal workaround for MYFACES-2552
+        return submittedValue;
+      } else if (modelType.isArray()) {
+        // the target should be an array
+        Class<?> componentType = modelType.getComponentType();
+        // check for optimization if the target is
+        // a string array --> no conversion needed
+        if (String.class.equals(componentType)) {
+          return submittedValue;
+        }
+        if (converter == null) {
+          // the compononent does not have an attached converter
+          // --> try to get a registered-by-class converter
+          converter = facesContext.getApplication().createConverter(
+              componentType);
+
+          if (converter == null && !Object.class.equals(componentType)) {
+            // could not obtain a Converter
+            // --> check if we maybe do not really have to convert
+
+            // target is not an Object array
+            // and not a String array (checked some lines above)
+            // and we do not have a Converter
+            throw new ConverterException(
+                "Could not obtain a Converter for "
+                    + componentType.getName());
+          }
+        }
+        // instantiate the array
+        targetForConvertedValues = Array.newInstance(componentType,
+            submittedValue.length);
+      } else if (Collection.class.isAssignableFrom(modelType) || Object.class.equals(modelType)) {
+        if (converter == null) {
+          // try to get the by-type-converter from the type of the SelectItems
+          SelectItemsIterator iterator = new SelectItemsIterator(component, facesContext);
+          converter = getSelectItemsValueConverter(iterator, facesContext);
+        }
+
+        Object collectionTypeAttr = component.getAttributes().get(
+            COLLECTION_TYPE_KEY);
+        if (collectionTypeAttr != null) {
+          Class<?> collectionType = getClassFromAttribute(facesContext, collectionTypeAttr);
+          if (collectionType == null) {
+            throw new FacesException(
+                "The attribute "
+                    + COLLECTION_TYPE_KEY
+                    + " of component "
+                    + component.getClientId(facesContext)
+                    + " does not evaluate to a "
+                    + "String, a Class object or a ValueExpression pointing "
+                    + "to a String or a Class object.");
+          }
+          // now we have a collectionType --> but is it really some kind of Collection
+          if (!Collection.class.isAssignableFrom(collectionType)) {
+            throw new FacesException("The attribute "
+                + COLLECTION_TYPE_KEY + " of component "
+                + component.getClientId(facesContext)
+                + " does not point to a valid type of Collection.");
+          }
+          // now we have a real collectionType --> try to instantiate it
+          try {
+            targetForConvertedValues = collectionType.newInstance();
+          } catch (Exception e) {
+            throw new FacesException("The Collection "
+                + collectionType.getName()
+                + "can not be instantiated.", e);
+          }
+        } else if (Collection.class.isAssignableFrom(modelType)) {
+          // component.getValue() will implement Collection at this point
+          Collection<?> componentValue = (Collection<?>) component
+              .getValue();
+          // can we clone the Collection
+          if (componentValue instanceof Cloneable) {
+            // clone method of Object is protected --> use reflection
+            try {
+              Method cloneMethod = componentValue.getClass()
+                  .getMethod("clone");
+              Collection<?> clone = (Collection<?>) cloneMethod
+                  .invoke(componentValue);
+              clone.clear();
+              targetForConvertedValues = clone;
+            } catch (Exception e) {
+              LOG.error("Could not clone " + componentValue.getClass().getName(), e);
+            }
+          }
+
+          // if clone did not work
+          if (targetForConvertedValues == null) {
+            // try to create the (concrete) collection from modelType
+            // or with the class object of componentValue (if any)
+            try {
+              targetForConvertedValues = (componentValue != null
+                  ? componentValue.getClass()
+                  : modelType).newInstance();
+            } catch (Exception e) {
+              // this did not work either
+              // use the standard concrete type
+              if (SortedSet.class.isAssignableFrom(modelType)) {
+                targetForConvertedValues = new TreeSet();
+              } else if (Queue.class.isAssignableFrom(modelType)) {
+                targetForConvertedValues = new LinkedList();
+              } else if (Set.class.isAssignableFrom(modelType)) {
+                targetForConvertedValues = new HashSet(
+                    submittedValue.length);
+              } else {
+                targetForConvertedValues = new ArrayList(
+                    submittedValue.length);
+              }
+            }
+          }
+        } else /* if (Object.class.equals(modelType)) */ {
+          // a modelType of Object is also permitted, in order to support
+          // managed bean properties of type Object
+
+          // optimization: if we don't have a converter, we can return the submittedValue
+          if (converter == null) {
+            return submittedValue;
+          }
+
+          targetForConvertedValues = new Object[submittedValue.length];
+        }
+      } else {
+        // the expression does neither point to an array nor to a collection
+        throw new ConverterException(
+            "ValueExpression for UISelectMany must be of type Collection or Array.");
+      }
+    } else {
+      targetForConvertedValues = new Object[submittedValue.length];
+    }
+
+    // convert the values with the selected converter (if any)
+    // and store them in targetForConvertedValues
+    boolean isArray = (targetForConvertedValues.getClass().isArray());
+    for (int i = 0; i < submittedValue.length; i++) {
+      // get the value
+      Object value;
+      if (converter != null) {
+        value = converter.getAsObject(facesContext, component,
+            submittedValue[i]);
+      } else {
+        value = submittedValue[i];
+      }
+      // store it in targetForConvertedValues
+      if (isArray) {
+        Array.set(targetForConvertedValues, i, value);
+      } else {
+        ((Collection) targetForConvertedValues).add(value);
+      }
+    }
+
+    return targetForConvertedValues;
+  }
+
+  /**
+   * Gets a Class object from a given component attribute. The attribute can
+   * be a ValueExpression (that evaluates to a String or a Class) or a
+   * String (that is a fully qualified Java class name) or a Class object.
+   *
+   * @param facesContext
+   * @param attribute
+   * @return
+   * @throws FacesException if the value is a String and the represented
+   *                        class cannot be found
+   */
+  static Class<?> getClassFromAttribute(FacesContext facesContext,
+                                        Object attribute) throws FacesException {
+    // Attention!
+    // This code is duplicated in shared renderkit package.
+    // If you change something here please do the same in the other class!
+
+    Class<?> type = null;
+
+    // if there is a value, it must be a ...
+    // ... a ValueExpression that evaluates to a String or a Class
+    if (attribute instanceof ValueExpression) {
+      // get the value of the ValueExpression
+      attribute = ((ValueExpression) attribute)
+          .getValue(facesContext.getELContext());
+    }
+    // ... String that is a fully qualified Java class name
+    if (attribute instanceof String) {
+      try {
+        type = Class.forName((String) attribute);
+      } catch (ClassNotFoundException cnfe) {
+        throw new FacesException(
+            "Unable to find class "
+                + attribute
+                + " on the classpath.", cnfe);
+      }
+    } else if (attribute instanceof Class) {
+      // ... a Class object
+      type = (Class<?>) attribute;
+    }
+
+    return type;
+  }
+
+  /**
+   * Uses the valueType attribute of the given UISelectMany component to
+   * get a by-type converter.
+   *
+   * @param facesContext
+   * @param component
+   * @return
+   */
+  static Converter getValueTypeConverter(FacesContext facesContext, UISelectMany component) {
+    Converter converter = null;
+
+    Object valueTypeAttr = component.getAttributes().get(VALUE_TYPE_KEY);
+    if (valueTypeAttr != null) {
+      // treat the valueType attribute exactly like the collectionType attribute
+      Class<?> valueType = getClassFromAttribute(facesContext, valueTypeAttr);
+      if (valueType == null) {
+        throw new FacesException(
+            "The attribute "
+                + VALUE_TYPE_KEY
+                + " of component "
+                + component.getClientId(facesContext)
+                + " does not evaluate to a "
+                + "String, a Class object or a ValueExpression pointing "
+                + "to a String or a Class object.");
+      }
+      // now we have a valid valueType
+      // --> try to get a registered-by-class converter
+      converter = facesContext.getApplication().createConverter(valueType);
+
+      if (converter == null) {
+        facesContext.getExternalContext().log("Found attribute valueType on component "
+            + getPathToComponent(component)
+            + ", but could not get a by-type converter for type "
+            + valueType.getName());
+      }
+    }
+
+    return converter;
+  }
+
+  /**
+   * Iterates through the SelectItems with the given Iterator and tries to obtain
+   * a by-class-converter based on the Class of SelectItem.getValue().
+   *
+   * @param iterator
+   * @param facesContext
+   * @return The first suitable Converter for the given SelectItems or null.
+   */
+  static Converter getSelectItemsValueConverter(Iterator<SelectItem> iterator, FacesContext facesContext) {
+    // Attention!
+    // This code is duplicated in jsfapi component package.
+    // If you change something here please do the same in the other class!
+
+    Converter converter = null;
+    while (converter == null && iterator.hasNext()) {
+      SelectItem item = iterator.next();
+      if (item instanceof SelectItemGroup) {
+        Iterator<SelectItem> groupIterator = Arrays.asList(
+            ((SelectItemGroup) item).getSelectItems()).iterator();
+        converter = getSelectItemsValueConverter(groupIterator, facesContext);
+      } else {
+        Class<?> selectItemsType = item.getValue().getClass();
+
+        // optimization: no conversion for String values
+        if (String.class.equals(selectItemsType)) {
+          return null;
+        }
+
+        try {
+          converter = facesContext.getApplication().createConverter(selectItemsType);
+        } catch (FacesException e) {
+          // nothing - try again
+        }
+      }
+    }
+    return converter;
+  }
+  // #################################################################################################################
+  // ### END copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_SharedRendererUtils.java
+  // #################################################################################################################
+
+  // #################################################################################################################
+  // ### BEGIN copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_ComponentUtils.java
+  // #################################################################################################################
+  static String getPathToComponent(UIComponent component) {
+    StringBuilder builder = new StringBuilder();
+
+    if (component == null) {
+      builder.append("{Component-Path : ");
+      builder.append("[null]}");
+      return builder.toString();
+    }
+
+    getPathToComponent(component, builder);
+
+    builder.insert(0, "{Component-Path : ");
+    builder.append("}");
+
+    return builder.toString();
+  }
+
+  private static void getPathToComponent(UIComponent component, StringBuilder builder) {
+    if (component == null) {
+      return;
+    }
+
+    StringBuilder intBuilder = new StringBuilder();
+
+    intBuilder.append("[Class: ");
+    intBuilder.append(component.getClass().getName());
+    if (component instanceof UIViewRoot) {
+      intBuilder.append(",ViewId: ");
+      intBuilder.append(((UIViewRoot) component).getViewId());
+    } else {
+      intBuilder.append(",Id: ");
+      intBuilder.append(component.getId());
+    }
+    intBuilder.append("]");
+
+    builder.insert(0, intBuilder.toString());
+
+    getPathToComponent(component.getParent(), builder);
+  }
+  // #################################################################################################################
+  // ### END copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_ComponentUtils.java
+  // #################################################################################################################
+
+  // #################################################################################################################
+  // ### BEGIN copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_SelectItemsIterator.java
+  // #################################################################################################################
+  private static class SelectItemsIterator implements Iterator<SelectItem> {
+
+    private static final Iterator<UIComponent> EMPTY_UICOMPONENT_ITERATOR = new EmptyIterator<UIComponent>();
+
+    // org.apache.myfaces.shared.util.SelectItemsIterator uses JSFAttr
+    private static final String VAR_ATTR = "var";
+    private static final String ITEM_VALUE_ATTR = "itemValue";
+    private static final String ITEM_LABEL_ATTR = "itemLabel";
+    private static final String ITEM_DESCRIPTION_ATTR = "itemDescription";
+    private static final String ITEM_DISABLED_ATTR = "itemDisabled";
+    private static final String ITEM_LABEL_ESCAPED_ATTR = "itemLabelEscaped";
+    private static final String NO_SELECTION_VALUE_ATTR = "noSelectionValue";
+
+    private final Iterator<UIComponent> children;
+    private Iterator<?> nestedItems;
+    private SelectItem nextItem;
+    private UIComponent currentComponent;
+    private UISelectItems currentUISelectItems;
+    private FacesContext facesContext;
+
+    public SelectItemsIterator(UIComponent selectItemsParent, FacesContext facesContext) {
+      children = selectItemsParent.getChildCount() > 0
+          ? selectItemsParent.getChildren().iterator()
+          : EMPTY_UICOMPONENT_ITERATOR;
+      this.facesContext = facesContext;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public boolean hasNext() {
+      if (nextItem != null) {
+        return true;
+      }
+      if (nestedItems != null) {
+        if (nestedItems.hasNext()) {
+          return true;
+        }
+        nestedItems = null;
+        currentComponent = null;
+      }
+      if (children.hasNext()) {
+        UIComponent child = children.next();
+        // When there is other components nested that does
+        // not extends from UISelectItem or UISelectItems
+        // the behavior for this iterator is just skip this
+        // element(s) until an element that extends from these
+        // classes are found. If there is no more elements
+        // that conform this condition, just return false.
+        while (!(child instanceof UISelectItem) && !(child instanceof UISelectItems)) {
+          // Try to skip it
+          if (children.hasNext()) {
+            // Skip and do the same check
+            child = children.next();
+          } else {
+            // End loop, so the final result is return false,
+            // since there are no more components to iterate.
+            return false;
+          }
+        }
+        if (child instanceof UISelectItem) {
+          UISelectItem uiSelectItem = (UISelectItem) child;
+          Object item = uiSelectItem.getValue();
+          if (item == null) {
+            // no value attribute --> create the SelectItem out of the other attributes
+            Object itemValue = uiSelectItem.getItemValue();
+            String label = uiSelectItem.getItemLabel();
+            String description = uiSelectItem.getItemDescription();
+            boolean disabled = uiSelectItem.isItemDisabled();
+            boolean escape = uiSelectItem.isItemEscaped();
+            boolean noSelectionOption = uiSelectItem.isNoSelectionOption();
+            if (label == null) {
+              label = itemValue.toString();
+            }
+            item = new SelectItem(itemValue, label, description, disabled, escape, noSelectionOption);
+          } else if (!(item instanceof SelectItem)) {
+            ValueExpression expression = uiSelectItem.getValueExpression("value");
+            throw new IllegalArgumentException("ValueExpression '"
+                + (expression == null ? null : expression.getExpressionString()) + "' of UISelectItem : "
+                + getPathToComponent(child) + " does not reference an Object of type SelectItem");
+          }
+          nextItem = (SelectItem) item;
+          currentComponent = child;
+          return true;
+        } else if (child instanceof UISelectItems) {
+          currentUISelectItems = ((UISelectItems) child);
+          Object value = currentUISelectItems.getValue();
+          currentComponent = child;
+
+          if (value instanceof SelectItem) {
+            nextItem = (SelectItem) value;
+            return true;
+          } else if (value != null && value.getClass().isArray()) {
+            // value is any kind of array (primitive or non-primitive)
+            // --> we have to use class Array to get the values
+            int length = Array.getLength(value);
+            Collection<Object> items = new ArrayList<Object>(length);
+            for (int i = 0; i < length; i++) {
+              items.add(Array.get(value, i));
+            }
+            nestedItems = items.iterator();
+            return hasNext();
+          } else if (value instanceof Iterable) {
+            // value is Iterable --> Collection, DataModel,...
+            nestedItems = ((Iterable<?>) value).iterator();
+            return hasNext();
+          } else if (value instanceof Map) {
+            Map<Object, Object> map = ((Map<Object, Object>) value);
+            Collection<SelectItem> items = new ArrayList<SelectItem>(map.size());
+            for (Map.Entry<Object, Object> entry : map.entrySet()) {
+              items.add(new SelectItem(entry.getValue(), entry.getKey().toString()));
+            }
+
+            nestedItems = items.iterator();
+            return hasNext();
+          } else {
+
+            if ((facesContext.isProjectStage(ProjectStage.Production) && LOG.isDebugEnabled())
+                || LOG.isWarnEnabled()) {
+              ValueExpression expression = currentUISelectItems.getValueExpression("value");
+              Object[] objects = {
+                  (expression == null ? null : expression.getExpressionString()),
+                  getPathToComponent(child),
+                  (value == null ? null : value.getClass().getName())
+              };
+              String message = "ValueExpression {0} of UISelectItems with component-path {1}"
+                  + " does not reference an Object of type SelectItem,"
+                  + " array, Iterable or Map, but of type: {2}";
+              if (facesContext.isProjectStage(ProjectStage.Production)) {
+                LOG.debug(message, objects);
+              } else {
+                LOG.warn(message, objects);
+              }
+            }
+          }
+        } else {
+          currentComponent = null;
+        }
+      }
+      return false;
+    }
+
+    @Override
+    public SelectItem next() {
+      if (!hasNext()) {
+        throw new NoSuchElementException();
+      }
+      if (nextItem != null) {
+        SelectItem value = nextItem;
+        nextItem = null;
+        return value;
+      }
+      if (nestedItems != null) {
+        Object item = nestedItems.next();
+
+        if (!(item instanceof SelectItem)) {
+          // check new params of SelectItems (since 2.0): itemValue, itemLabel, itemDescription,...
+          // Note that according to the spec UISelectItems does not provide Getter and Setter
+          // methods for this values, so we have to use the attribute map
+          Map<String, Object> attributeMap = currentUISelectItems.getAttributes();
+
+          // write the current item into the request map under the key listed in var, if available
+          boolean wroteRequestMapVarValue = false;
+          Object oldRequestMapVarValue = null;
+          String var = (String) attributeMap.get(VAR_ATTR);
+          if (var != null && !"".equals(var)) {
+            // save the current value of the key listed in var from the request map
+            oldRequestMapVarValue = facesContext.getExternalContext().getRequestMap().put(var, item);
+            wroteRequestMapVarValue = true;
+          }
+
+          // check the itemValue attribute
+          Object itemValue = attributeMap.get(ITEM_VALUE_ATTR);
+          if (itemValue == null) {
+            // the itemValue attribute was not provided
+            // --> use the current item as the itemValue
+            itemValue = item;
+          }
+
+          // Spec: When iterating over the select items, toString()
+          // must be called on the string rendered attribute values
+          Object itemLabel = attributeMap.get(ITEM_LABEL_ATTR);
+          if (itemLabel == null) {
+            itemLabel = itemValue.toString();
+          } else {
+            itemLabel = itemLabel.toString();
+          }
+          Object itemDescription = attributeMap.get(ITEM_DESCRIPTION_ATTR);
+          if (itemDescription != null) {
+            itemDescription = itemDescription.toString();
+          }
+          Boolean itemDisabled = getBooleanAttribute(currentUISelectItems, ITEM_DISABLED_ATTR, false);
+          Boolean itemLabelEscaped = getBooleanAttribute(currentUISelectItems, ITEM_LABEL_ESCAPED_ATTR, true);
+          Object noSelectionValue = attributeMap.get(NO_SELECTION_VALUE_ATTR);
+          item = new SelectItem(itemValue,
+              (String) itemLabel,
+              (String) itemDescription,
+              itemDisabled,
+              itemLabelEscaped,
+              itemValue.equals(noSelectionValue));
+
+          // remove the value with the key from var from the request map, if previously written
+          if (wroteRequestMapVarValue) {
+            // If there was a previous value stored with the key from var in the request map, restore it
+            if (oldRequestMapVarValue != null) {
+              facesContext.getExternalContext()
+                  .getRequestMap().put(var, oldRequestMapVarValue);
+            } else {
+              facesContext.getExternalContext()
+                  .getRequestMap().remove(var);
+            }
+          }
+        }
+        return (SelectItem) item;
+      }
+      throw new NoSuchElementException();
+    }
+
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+
+    public UIComponent getCurrentComponent() {
+      return currentComponent;
+    }
+
+    private boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue) {
+      Object value = component.getAttributes().get(attrName);
+      if (value == null) {
+        return defaultValue;
+      } else if (value instanceof Boolean) {
+        return (Boolean) value;
+      } else {
+        // If the value is a String, parse the boolean.
+        // This makes the following code work: <tag attribute="true" />,
+        // otherwise you would have to write <tag attribute="#{true}" />.
+        return Boolean.valueOf(value.toString());
+      }
+    }
+
+    private String getPathToComponent(UIComponent component) {
+      StringBuilder builder = new StringBuilder();
+
+      if (component == null) {
+        builder.append("{Component-Path : ");
+        builder.append("[null]}");
+        return builder.toString();
+      }
+
+      getPathToComponent(component, builder);
+
+      builder.insert(0, "{Component-Path : ");
+      builder.append("}");
+
+      return builder.toString();
+    }
+
+    private void getPathToComponent(UIComponent component, StringBuilder builder) {
+      if (component == null) {
+        return;
+      }
+
+      StringBuilder intBuilder = new StringBuilder();
+
+      intBuilder.append("[Class: ");
+      intBuilder.append(component.getClass().getName());
+      if (component instanceof UIViewRoot) {
+        intBuilder.append(",ViewId: ");
+        intBuilder.append(((UIViewRoot) component).getViewId());
+      } else {
+        intBuilder.append(",Id: ");
+        intBuilder.append(component.getId());
+      }
+      intBuilder.append("]");
+
+      builder.insert(0, intBuilder);
+
+      getPathToComponent(component.getParent(), builder);
+    }
+  }
+  // #################################################################################################################
+  // ### END copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_SelectItemsIterator.java
+  // #################################################################################################################
+
+  // #################################################################################################################
+  // ### BEGIN copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_EmptyIterator.java
+  // #################################################################################################################
+  private static class EmptyIterator<T> implements Iterator<T> {
+
+    @Override
+    public boolean hasNext() {
+      return false;
+    }
+
+    @Override
+    public T next() {
+      throw new NoSuchElementException();
+    }
+
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+  // #################################################################################################################
+  // ### END copy out of https://svn.apache.org/repos/asf/myfaces/core/tags/myfaces-core-module-2.2.8/
+  // ###     api/src/main/java/javax/faces/component/_EmptyIterator.java
+  // #################################################################################################################
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyShuttleRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyShuttleRenderer.java
new file mode 100644
index 0000000..57ca2fb
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectManyShuttleRenderer.java
@@ -0,0 +1,154 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UISelectManyShuttle;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.Icons;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.IOException;
+import java.util.List;
+
+public class SelectManyShuttleRenderer extends SelectManyRendererBase {
+
+  @Override
+  public void encodeBeginField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UISelectManyShuttle select = (UISelectManyShuttle) component;
+    final String clientId = select.getClientId(facesContext);
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.startElement(HtmlElements.DIV);
+    if(select.isLabelLayoutSkip()) {
+      writer.writeIdAttribute(clientId);
+    }
+    writer.writeClassAttribute(Classes.create(select), select.getCustomClass());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+    final boolean hasLabel = select.hasLabel();
+    final List<SelectItem> items = SelectItemUtils.getItemList(facesContext, select);
+    final boolean disabled = !items.iterator().hasNext() || select.isDisabled();
+    final boolean readonly = select.isReadonly();
+
+    final String unselectedLabel = select.getUnselectedLabel();
+    if (unselectedLabel != null) {
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(Classes.create(select, "unselectedLabel"));
+      writer.write(unselectedLabel);
+      writer.endElement(HtmlElements.DIV);
+    }
+    Integer size = select.getSize();
+    size = Math.max(size != null ? size : items.size(), 2); // must be > 1
+
+    writer.startElement(HtmlElements.SELECT);
+    final String unselectedClientId = clientId + ComponentUtils.SUB_SEPARATOR + "unselected";
+    writer.writeIdAttribute(unselectedClientId);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+
+    // TODO tabIndex
+    writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+
+    writer.writeClassAttribute(Classes.create(select, "unselected"), BootstrapClass.FORM_CONTROL);
+
+    writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
+    writer.writeAttribute(HtmlAttributes.SIZE, size);
+
+    final Object[] values = select.getSelectedValues();
+    final String[] submittedValues = getSubmittedValues(select);
+    HtmlRendererUtils.renderSelectItems(select, items, values, submittedValues, false, writer, facesContext);
+
+    writer.endElement(HtmlElements.SELECT);
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(Classes.create(select, "toolBar"));
+    writer.startElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+    createButton(facesContext, component, writer, disabled | readonly, Icons.ANGLE_DOUBLE_RIGHT, "addAll");
+    createButton(facesContext, component, writer, disabled | readonly, Icons.ANGLE_RIGHT, "add");
+    createButton(facesContext, component, writer, disabled | readonly, Icons.ANGLE_LEFT, "remove");
+    createButton(facesContext, component, writer, disabled | readonly, Icons.ANGLE_DOUBLE_LEFT, "removeAll");
+    writer.startElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+    final String selectedLabel = select.getSelectedLabel();
+    if (selectedLabel != null) {
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(Classes.create(select, "selectedLabel"));
+      writer.write(selectedLabel);
+      writer.endElement(HtmlElements.DIV);
+    }
+
+    writer.startElement(HtmlElements.SELECT);
+    final String selectedClientId = clientId + ComponentUtils.SUB_SEPARATOR + "selected";
+    writer.writeIdAttribute(selectedClientId);
+
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+    writer.writeClassAttribute(Classes.create(select, "selected"), BootstrapClass.FORM_CONTROL);
+    writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
+    writer.writeAttribute(HtmlAttributes.SIZE, size);
+    HtmlRendererUtils.renderSelectItems(select, items, values, submittedValues, true, writer, facesContext);
+
+    writer.endElement(HtmlElements.SELECT);
+    writer.startElement(HtmlElements.SELECT);
+    writer.writeClassAttribute(Classes.create(component, "hidden"));
+    final String hiddenClientId = clientId + ComponentUtils.SUB_SEPARATOR + "hidden";
+    writer.writeIdAttribute(hiddenClientId);
+    writer.writeNameAttribute(clientId);
+    writer.writeAttribute(HtmlAttributes.MULTIPLE, true);
+    writer.writeAttribute(HtmlAttributes.REQUIRED, select.isRequired());
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+    HtmlRendererUtils.renderSelectItems(select, items, values, submittedValues, writer, facesContext);
+    writer.endElement(HtmlElements.SELECT);
+  }
+
+  @Override
+  public void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.DIV);
+  }
+
+  private void createButton(
+      final FacesContext context, final UIComponent component, final TobagoResponseWriter writer,
+      final boolean disabled, final Icons icon, final String sub) throws IOException {
+    writer.startElement(HtmlElements.BUTTON);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+    writer.writeClassAttribute(Classes.create(component, sub), BootstrapClass.BTN, BootstrapClass.BTN_SECONDARY);
+    writer.writeIdAttribute(component.getClientId(context) + ComponentUtils.SUB_SEPARATOR + sub);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeIcon(icon);
+    writer.endElement(HtmlElements.BUTTON);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneChoiceRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneChoiceRenderer.java
new file mode 100644
index 0000000..a25c2f3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneChoiceRenderer.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UISelectOneChoice;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.IOException;
+
+public class SelectOneChoiceRenderer extends SelectOneRendererBase {
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  protected void encodeBeginField(FacesContext facesContext, UIComponent component) throws IOException {
+    final UISelectOneChoice select = (UISelectOneChoice) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String clientId = select.getClientId(facesContext);
+    final String fieldId = select.getFieldId(facesContext);
+    final Iterable<SelectItem> items = SelectItemUtils.getItemIterator(facesContext, select);
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+    final boolean disabled = !items.iterator().hasNext() || select.isDisabled() || select.isReadonly();
+
+    writer.startElement(HtmlElements.SELECT);
+    writer.writeIdAttribute(fieldId);
+    writer.writeNameAttribute(clientId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+    writer.writeStyleAttribute(select.getStyle());
+    writer.writeClassAttribute(Classes.create(select), BootstrapClass.FORM_CONTROL, select.getCustomClass());
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+    HtmlRendererUtils.renderFocus(clientId, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
+
+    HtmlRendererUtils.renderSelectItems(select, items, select.getValue(), (String) select.getSubmittedValue(), writer,
+        facesContext);
+
+  }
+
+  @Override
+  protected void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.SELECT);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListboxRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListboxRenderer.java
new file mode 100644
index 0000000..fb30ece
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneListboxRenderer.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UISelectOneListbox;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.IOException;
+import java.util.List;
+
+public class SelectOneListboxRenderer extends SelectOneRendererBase {
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeBeginField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UISelectOneListbox select = (UISelectOneListbox) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String clientId = select.getClientId(facesContext);
+    final String fieldId = select.getFieldId(facesContext);
+    final List<SelectItem> items = SelectItemUtils.getItemList(facesContext, select);
+    final boolean disabled = !items.iterator().hasNext() || select.isDisabled() || select.isReadonly();
+    Integer size = select.getSize();
+    size = Math.max(size != null ? size : items.size(), 2); // must be > 1
+
+    writer.startElement(HtmlElements.SELECT);
+    writer.writeIdAttribute(fieldId);
+    writer.writeNameAttribute(clientId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.writeAttribute(HtmlAttributes.READONLY, select.isReadonly());
+    writer.writeAttribute(HtmlAttributes.REQUIRED, select.isRequired());
+    HtmlRendererUtils.renderFocus(clientId, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
+
+    writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+    writer.writeStyleAttribute(select.getStyle());
+    writer.writeClassAttribute(Classes.create(select), BootstrapClass.FORM_CONTROL, select.getCustomClass());
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+    writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    writer.writeAttribute(HtmlAttributes.SIZE, size);
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+    HtmlRendererUtils.renderSelectItems(select, items, select.getValue(), (String) select.getSubmittedValue(),
+        writer, facesContext);
+
+  }
+
+  @Override
+  protected void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.SELECT);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRadioRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRadioRenderer.java
new file mode 100644
index 0000000..2e71934
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRadioRenderer.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UISelectOneRadio;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.ObjectUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.IOException;
+
+public class SelectOneRadioRenderer extends SelectOneRendererBase {
+
+  @Override
+  protected void encodeBeginField(FacesContext facesContext, UIComponent component) throws IOException {
+    final UISelectOneRadio select = (UISelectOneRadio) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String id = select.getClientId(facesContext);
+    final Iterable<SelectItem> items = SelectItemUtils.getItemIterator(facesContext, select);
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+    final boolean disabled = select.isDisabled();
+    final boolean readonly = select.isReadonly();
+    final boolean required = select.isRequired();
+    final boolean inline = select.isInline();
+
+    writer.startElement(HtmlElements.OL);
+    writer.writeStyleAttribute(select.getStyle());
+    writer.writeClassAttribute(
+        Classes.create(select),
+        inline ? TobagoClass.SELECT_ONE_RADIO__INLINE : null,
+        select.getCustomClass());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+    if (title != null) {
+      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    }
+    boolean first = true;
+    final Object value = select.getValue();
+    final String submittedValue = (String) select.getSubmittedValue();
+    int i = 0;
+    for (final SelectItem item : items) {
+      final boolean itemDisabled = item.isDisabled() || disabled;
+      final String itemId = id + ComponentUtils.SUB_SEPARATOR + i++;
+      writer.startElement(HtmlElements.LI);
+      writer.writeClassAttribute(
+          BootstrapClass.FORM_CHECK,
+          inline ? BootstrapClass.FORM_CHECK_INLINE : null,
+          itemDisabled ? BootstrapClass.DISABLED : null);
+      writer.startElement(HtmlElements.LABEL);
+      writer.writeClassAttribute(BootstrapClass.FORM_CHECK_LABEL);
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeClassAttribute(BootstrapClass.FORM_CHECK_INPUT);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.RADIO);
+      final String formattedValue = ComponentUtils.getFormattedValue(facesContext, select, item.getValue());
+      boolean checked;
+      if (submittedValue == null) {
+        checked = ObjectUtils.equals(item.getValue(), value);
+      } else {
+        checked = ObjectUtils.equals(formattedValue, submittedValue);
+      }
+      writer.writeAttribute(HtmlAttributes.CHECKED, checked);
+      writer.writeNameAttribute(id);
+      writer.writeIdAttribute(itemId);
+      writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
+      writer.writeAttribute(HtmlAttributes.DISABLED, itemDisabled);
+      writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+      writer.writeAttribute(HtmlAttributes.REQUIRED, required);
+      if (first) {
+        HtmlRendererUtils.renderFocus(id, select.isFocus(), ComponentUtils.isError(select), facesContext, writer);
+        first = false;
+      }
+      writer.writeAttribute(HtmlAttributes.TABINDEX, select.getTabIndex());
+      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+      writer.endElement(HtmlElements.INPUT);
+
+      if (item instanceof org.apache.myfaces.tobago.model.SelectItem) {
+        org.apache.myfaces.tobago.model.SelectItem tobagoItem = (org.apache.myfaces.tobago.model.SelectItem) item;
+        final String image = tobagoItem.getImage();
+        if (image != null) {
+          writer.startElement(HtmlElements.IMG);
+          writer.writeAttribute(HtmlAttributes.SRC, image, true);
+          writer.writeAttribute(HtmlAttributes.ALT, "", false);
+          writer.endElement(HtmlElements.IMG);
+        }
+      }
+
+      final String label = item.getLabel();
+      if (label != null) {
+        writer.writeText(label);
+      }
+
+      writer.endElement(HtmlElements.LABEL);
+      writer.endElement(HtmlElements.LI);
+    }
+  }
+
+  @Override
+  protected void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.OL);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRendererBase.java
new file mode 100644
index 0000000..4fa8352
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectOneRendererBase.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UISelectOne;
+import javax.faces.context.FacesContext;
+
+public abstract class SelectOneRendererBase extends LabelLayoutRendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SelectOneRendererBase.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    if (ComponentUtils.isOutputOnly(component)) {
+      return;
+    }
+
+    final UISelectOne select = (UISelectOne) component;
+
+    final String clientId = select.getClientId(facesContext);
+    final Object newValue =
+        facesContext.getExternalContext().getRequestParameterMap().get(clientId);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("decode: key='" + clientId + "' value='" + newValue + "'");
+    }
+    select.setSubmittedValue(newValue);
+
+    RenderUtils.decodeClientBehaviors(facesContext, select);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectReferenceRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectReferenceRenderer.java
new file mode 100644
index 0000000..9287019
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SelectReferenceRenderer.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class SelectReferenceRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SelectReferenceRenderer.class);
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext,
+                        final UIComponent component)
+      throws IOException {
+    final String referenceId = ComponentUtils.getStringAttribute(component, Attributes.forValue);
+    final UIComponent reference = component.findComponent(referenceId);
+
+    final Object renderRange = ComponentUtils.getAttribute(component, Attributes.renderRange);
+    ComponentUtils.setAttribute(reference, Attributes.renderRangeExtern, renderRange);
+
+    RenderUtils.encode(facesContext, reference);
+
+    ComponentUtils.removeAttribute(reference, Attributes.renderRangeExtern);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SeparatorRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SeparatorRenderer.java
new file mode 100644
index 0000000..8f3ffde
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SeparatorRenderer.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.UILabel;
+import org.apache.myfaces.tobago.component.UISeparator;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class SeparatorRenderer extends RendererBase {
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UISeparator separator = (UISeparator) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final String clientId = separator.getClientId(facesContext);
+    final String label = getLabel(separator);
+
+    if (label != null) {
+      writer.startElement(HtmlElements.P);
+      writer.writeIdAttribute(clientId);
+      writer.writeClassAttribute(Classes.create(separator), separator.getCustomClass());
+      writer.writeText(label);
+      writer.endElement(HtmlElements.P);
+    } else {
+      writer.startElement(HtmlElements.HR);
+      writer.writeIdAttribute(clientId);
+      writer.writeClassAttribute(Classes.create(separator), separator.getCustomClass());
+      writer.endElement(HtmlElements.HR);
+    }
+  }
+
+  private String getLabel(final UISeparator separator) {
+    String label = separator.getLabel();
+    final UIComponent facet = ComponentUtils.getFacet(separator, Facets.label);
+    if (label == null && facet != null) {
+      label = String.valueOf(((UILabel) facet).getValue());
+    }
+    return label;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetPageCommandRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetPageCommandRenderer.java
new file mode 100644
index 0000000..2851038
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetPageCommandRenderer.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.event.SheetAction;
+import org.apache.myfaces.tobago.event.PageActionEvent;
+import org.apache.myfaces.tobago.event.SortActionEvent;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIColumn;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIData;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+import java.util.Map;
+
+public class SheetPageCommandRenderer extends LinkRenderer {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SheetPageCommandRenderer.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    final String sourceId = facesContext.getExternalContext().getRequestParameterMap().get("javax.faces.source");
+    final String clientId = component.getClientId(facesContext);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("sourceId = '" + sourceId + "'");
+      LOG.debug("clientId = '" + clientId + "'");
+    }
+
+    if (clientId.equals(sourceId)) {
+
+      final SheetAction action = (SheetAction) ComponentUtils.getAttribute(component, Attributes.sheetAction);
+      ActionEvent event = null;
+
+      switch (action) {
+        case first:
+        case prev:
+        case next:
+        case last:
+          event = new PageActionEvent(component.getParent(), action);
+          break;
+        case toPage:
+        case toRow:
+          event = new PageActionEvent(component.getParent(), action);
+          Integer target = (Integer) ComponentUtils.getAttribute(component, Attributes.pagingTarget);
+          if (target == null) {
+            final Map map = facesContext.getExternalContext().getRequestParameterMap();
+            final Object value = map.get(clientId);
+            try {
+              target = Integer.parseInt((String) value);
+            } catch (final NumberFormatException e) {
+              LOG.error("Can't parse integer value for action " + action.name() + ": " + value);
+              break;
+            }
+          }
+          ((PageActionEvent) event).setValue(target);
+          break;
+        case sort:
+          final UIColumn column = (UIColumn) component.getParent();
+          final UIData data = (UIData) column.getParent();
+          event = new SortActionEvent(data, column);
+          break;
+        default:
+          LOG.error("Unknown action '{}' found!", action);
+      }
+      component.queueEvent(event);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java
new file mode 100644
index 0000000..c8c3d6d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SheetRenderer.java
@@ -0,0 +1,1168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.LabelLayout;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.UIColumnSelector;
+import org.apache.myfaces.tobago.component.UILink;
+import org.apache.myfaces.tobago.component.UIOut;
+import org.apache.myfaces.tobago.component.UIPanel;
+import org.apache.myfaces.tobago.component.UIReload;
+import org.apache.myfaces.tobago.component.UISheet;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.context.TobagoResourceBundle;
+import org.apache.myfaces.tobago.event.SheetAction;
+import org.apache.myfaces.tobago.internal.component.AbstractUIColumn;
+import org.apache.myfaces.tobago.internal.component.AbstractUIColumnBase;
+import org.apache.myfaces.tobago.internal.component.AbstractUIColumnNode;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.component.AbstractUIOut;
+import org.apache.myfaces.tobago.internal.component.AbstractUIRow;
+import org.apache.myfaces.tobago.internal.component.AbstractUISheet;
+import org.apache.myfaces.tobago.internal.layout.Cell;
+import org.apache.myfaces.tobago.internal.layout.Grid;
+import org.apache.myfaces.tobago.internal.layout.OriginCell;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.layout.Display;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.ShowPosition;
+import org.apache.myfaces.tobago.layout.TextAlign;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.Selectable;
+import org.apache.myfaces.tobago.model.SheetState;
+import org.apache.myfaces.tobago.model.TreePath;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.CssItem;
+import org.apache.myfaces.tobago.renderkit.css.Icons;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.Arias;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.application.Application;
+import javax.faces.component.UIColumn;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.AjaxBehavior;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+public class SheetRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SheetRenderer.class);
+
+  private static final String SUFFIX_WIDTHS = ComponentUtils.SUB_SEPARATOR + "widths";
+  private static final String SUFFIX_COLUMN_RENDERED = ComponentUtils.SUB_SEPARATOR + "rendered";
+  private static final String SUFFIX_SCROLL_POSITION = ComponentUtils.SUB_SEPARATOR + "scrollPosition";
+  private static final String SUFFIX_SELECTED = ComponentUtils.SUB_SEPARATOR + "selected";
+  private static final String SUFFIX_SELECTOR_DROPDOWN = ComponentUtils.SUB_SEPARATOR + "selectorDropdown";
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+
+    final UISheet sheet = (UISheet) component;
+    final List<AbstractUIColumnBase> columns = sheet.getAllColumns();
+    final String clientId = sheet.getClientId(facesContext);
+
+    String key = clientId + SUFFIX_WIDTHS;
+    final Map requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
+    final SheetState state = sheet.getState();
+    if (requestParameterMap.containsKey(key)) {
+      final String widths = (String) requestParameterMap.get(key);
+      ensureColumnWidthsSize(state.getColumnWidths(), columns, JsonUtils.decodeIntegerArray(widths));
+    }
+
+    key = clientId + SUFFIX_SELECTED;
+    if (requestParameterMap.containsKey(key)) {
+      final String selected = (String) requestParameterMap.get(key);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("selected = " + selected);
+      }
+      List<Integer> selectedRows;
+      try {
+        selectedRows = StringUtils.parseIntegerList(selected);
+      } catch (final NumberFormatException e) {
+        LOG.warn(selected, e);
+        selectedRows = Collections.emptyList();
+      }
+
+      ComponentUtils.setAttribute(sheet, Attributes.selectedListString, selectedRows);
+    }
+
+    final String value
+        = facesContext.getExternalContext().getRequestParameterMap().get(clientId + SUFFIX_SCROLL_POSITION);
+    if (value != null) {
+      state.getScrollPosition().update(value);
+    }
+    RenderUtils.decodedStateOfTreeData(facesContext, sheet);
+
+/* this will be done by the javax.faces.component.UIData.processDecodes() because these are facets.
+    for (UIComponent facet : sheet.getFacets().values()) {
+      facet.decode(facesContext);
+    }
+*/
+  }
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UISheet sheet = (UISheet) component;
+    final String sheetId = sheet.getClientId(facesContext);
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    UIComponent header = sheet.getHeader();
+    if (header == null) {
+      header = ComponentUtils.createComponent(facesContext, UIPanel.COMPONENT_TYPE, null, "_header");
+      final List<AbstractUIColumnBase> columns = sheet.getAllColumns();
+      int i = 0;
+      for (final AbstractUIColumnBase column : columns) {
+        if (!(column instanceof AbstractUIRow)) {
+          final AbstractUIOut out = (AbstractUIOut) ComponentUtils.createComponent(
+              facesContext, UIOut.COMPONENT_TYPE, RendererTypes.Out, "_col" + i);
+//        out.setValue(column.getLabel());
+          ValueExpression valueExpression = column.getValueExpression(Attributes.label.getName());
+          if (valueExpression != null) {
+            out.setValueExpression(Attributes.value.getName(), valueExpression);
+          } else {
+            out.setValue(ComponentUtils.getAttribute(column, Attributes.label));
+          }
+          valueExpression = column.getValueExpression(Attributes.rendered.getName());
+          if (valueExpression != null) {
+            out.setValueExpression(Attributes.rendered.getName(), valueExpression);
+          } else {
+            out.setRendered(ComponentUtils.getBooleanAttribute(column, Attributes.rendered));
+          }
+          out.setLabelLayout(LabelLayout.skip);
+          header.getChildren().add(out);
+        }
+        i++;
+      }
+      sheet.setHeader(header);
+    }
+    sheet.init(facesContext);
+
+    // Outer sheet div
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(sheetId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, sheet);
+    writer.writeClassAttribute(Classes.create(sheet), sheet.getCustomClass());
+    writer.writeStyleAttribute(sheet.getStyle());
+    final UIComponent facetReload = ComponentUtils.getFacet(sheet, Facets.reload);
+    if (facetReload != null && facetReload instanceof UIReload && facetReload.isRendered()) {
+      final UIReload update = (UIReload) facetReload;
+      writer.writeAttribute(DataAttributes.RELOAD, update.getFrequency());
+    }
+// todo    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, sheet)));
+    final CommandMap commands = RenderUtils.getBehaviorCommands(facesContext, sheet);
+    writer.writeAttribute(DataAttributes.BEHAVIOR_COMMANDS, JsonUtils.encode(commands), false);
+    writer.writeAttribute(DataAttributes.SELECTION_MODE, sheet.getSelectable().name(), false);
+    writer.writeAttribute(DataAttributes.FIRST, Integer.toString(sheet.getFirst()), false);
+    final StringBuilder builder = new StringBuilder();
+
+    final boolean autoLayout = sheet.isAutoLayout();
+    if (!autoLayout) {
+      builder.append("{\"columns\":");
+      JsonUtils.encode(sheet.getColumnLayout(), builder);
+      builder.append("}");
+      writer.writeAttribute(DataAttributes.LAYOUT, builder.toString(), true);
+    }
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext context, final UIComponent component) throws IOException {
+    // DO Nothing
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent uiComponent) throws IOException {
+
+    final UISheet sheet = (UISheet) uiComponent;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String sheetId = sheet.getClientId(facesContext);
+    final Selectable selectable = sheet.getSelectable();
+    final Application application = facesContext.getApplication();
+    final SheetState state = sheet.getSheetState(facesContext);
+    final List<Integer> columnWidths = sheet.getState().getColumnWidths();
+    final boolean definedColumnWidths = sheet.getState().isDefinedColumnWidths();
+    final List<Integer> selectedRows = getSelectedRows(sheet, state);
+    final List<AbstractUIColumnBase> columns = sheet.getAllColumns();
+    final boolean showHeader = sheet.isShowHeader();
+    final boolean autoLayout = sheet.isAutoLayout();
+    Markup sheetMarkup = sheet.getMarkup() != null ? sheet.getMarkup() : Markup.NULL;
+
+    ensureColumnWidthsSize(columnWidths, columns, Collections.<Integer>emptyList());
+
+    if (!autoLayout) {
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeIdAttribute(sheetId + SUFFIX_WIDTHS);
+      writer.writeNameAttribute(sheetId + SUFFIX_WIDTHS);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+      writer.writeAttribute(
+          HtmlAttributes.VALUE,
+          JsonUtils.encode(definedColumnWidths ? columnWidths : Collections.<Integer>emptyList()),
+          false);
+      writer.endElement(HtmlElements.INPUT);
+
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeIdAttribute(sheetId + SUFFIX_COLUMN_RENDERED);
+      writer.writeNameAttribute(sheetId + SUFFIX_COLUMN_RENDERED);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+      final ArrayList<String> encodedRendered = new ArrayList<String>();
+      for (AbstractUIColumnBase column : columns) {
+        if (!(column instanceof AbstractUIRow)) {
+          encodedRendered.add(Boolean.toString(column.isRendered()));
+        }
+      }
+      writer.writeAttribute(HtmlAttributes.VALUE,
+          JsonUtils.encode(encodedRendered.toArray(new String[encodedRendered.size()])), false);
+      writer.endElement(HtmlElements.INPUT);
+    }
+
+    final String clientId = sheet.getClientId(facesContext);
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeIdAttribute(clientId + SUFFIX_SCROLL_POSITION);
+    writer.writeNameAttribute(clientId + SUFFIX_SCROLL_POSITION);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeAttribute(HtmlAttributes.VALUE, sheet.getState().getScrollPosition().encode(), false);
+    writer.writeAttribute(DataAttributes.SCROLL_POSITION, Boolean.TRUE.toString(), true);
+    writer.endElement(HtmlElements.INPUT);
+
+    if (selectable != Selectable.none) {
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeIdAttribute(sheetId + SUFFIX_SELECTED);
+      writer.writeNameAttribute(sheetId + SUFFIX_SELECTED);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+      writer.writeAttribute(
+          HtmlAttributes.VALUE, StringUtils.joinWithSurroundingSeparator(selectedRows), true);
+      writer.endElement(HtmlElements.INPUT);
+    }
+
+    ExpandedState expandedState = null;
+    StringBuilder expandedValue = null;
+    if (sheet.isTreeModel()) {
+      expandedState = sheet.getExpandedState();
+      expandedValue = new StringBuilder(",");
+    }
+
+// BEGIN RENDER BODY CONTENT
+
+    if (showHeader && !autoLayout) {
+      // if no autoLayout, we render the header in a separate table.
+
+      writer.startElement(HtmlElements.HEADER);
+      writer.writeClassAttribute(TobagoClass.SHEET__HEADER);
+      writer.startElement(HtmlElements.TABLE);
+      writer.writeAttribute(HtmlAttributes.CELLSPACING, "0", false);
+      writer.writeAttribute(HtmlAttributes.CELLPADDING, "0", false);
+      writer.writeAttribute(HtmlAttributes.SUMMARY, "", false);
+      writer.writeClassAttribute(
+          BootstrapClass.TABLE,
+          TobagoClass.SHEET__HEADER_TABLE,
+          sheetMarkup.contains(Markup.INVERSE) ? BootstrapClass.TABLE_INVERSE : null,
+          sheetMarkup.contains(Markup.BORDERED) ? BootstrapClass.TABLE_BORDERED : null,
+          sheetMarkup.contains(Markup.SMALL) ? BootstrapClass.TABLE_SM : null,
+          !autoLayout ? TobagoClass.TABLE_LAYOUT__FIXED : null);
+
+      writeColgroup(writer, columnWidths, columns, true);
+
+      writer.startElement(HtmlElements.TBODY);
+      encodeHeaderRows(facesContext, sheet, writer, columns);
+      writer.endElement(HtmlElements.TBODY);
+      writer.endElement(HtmlElements.TABLE);
+      writer.endElement(HtmlElements.HEADER);
+    }
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(sheetId + ComponentUtils.SUB_SEPARATOR + "data_div");
+    writer.writeClassAttribute(Classes.create(sheet, "body"));
+
+    writer.startElement(HtmlElements.TABLE);
+    writer.writeAttribute(HtmlAttributes.CELLSPACING, "0", false);
+    writer.writeAttribute(HtmlAttributes.CELLPADDING, "0", false);
+    writer.writeAttribute(HtmlAttributes.SUMMARY, "", false);
+    writer.writeClassAttribute(
+        BootstrapClass.TABLE,
+        TobagoClass.SHEET__BODY_TABLE,
+        sheetMarkup.contains(Markup.INVERSE) ? BootstrapClass.TABLE_INVERSE : null,
+        sheetMarkup.contains(Markup.STRIPED) ? BootstrapClass.TABLE_STRIPED : null,
+        sheetMarkup.contains(Markup.BORDERED) ? BootstrapClass.TABLE_BORDERED : null,
+        sheetMarkup.contains(Markup.HOVER) ? BootstrapClass.TABLE_HOVER : null,
+        sheetMarkup.contains(Markup.SMALL) ? BootstrapClass.TABLE_SM : null,
+        !autoLayout ? TobagoClass.TABLE_LAYOUT__FIXED : null);
+
+    if (showHeader && autoLayout) {
+      writer.startElement(HtmlElements.THEAD);
+      encodeHeaderRows(facesContext, sheet, writer, columns);
+      writer.endElement(HtmlElements.THEAD);
+    }
+
+    if (!autoLayout) {
+      writeColgroup(writer, columnWidths, columns, false);
+    }
+
+    // Print the Content
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("first = " + sheet.getFirst() + "   rows = " + sheet.getRows());
+    }
+
+    writer.startElement(HtmlElements.TBODY);
+
+    final String var = sheet.getVar();
+
+    boolean emptySheet = true;
+    // rows = 0 means: show all
+    final int last = sheet.isRowsUnlimited() ? Integer.MAX_VALUE : sheet.getFirst() + sheet.getRows();
+    for (int rowIndex = sheet.getFirst(); rowIndex < last; rowIndex++) {
+      sheet.setRowIndex(rowIndex);
+      if (!sheet.isRowAvailable()) {
+        break;
+      }
+
+      final Object rowRendered = sheet.getAttributes().get("rowRendered");
+      if (rowRendered instanceof Boolean && !((Boolean) rowRendered)) {
+        continue;
+      }
+
+      emptySheet = false;
+
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("var       " + var);
+        LOG.debug("list      " + sheet.getValue());
+      }
+
+      if (sheet.isTreeModel()) {
+        final TreePath path = sheet.getPath();
+        if (sheet.isFolder() && expandedState.isExpanded(path)) {
+          expandedValue.append(rowIndex);
+          expandedValue.append(",");
+        }
+      }
+
+      writer.startElement(HtmlElements.TR);
+      if (rowRendered instanceof Boolean) {
+        // if rowRendered attribute is set we need the rowIndex on the client
+        writer.writeAttribute(DataAttributes.ROW_INDEX, rowIndex);
+      }
+
+      final boolean selected = selectedRows.contains(rowIndex);
+      final String[] rowMarkups = (String[]) sheet.getAttributes().get("rowMarkup");
+      Markup rowMarkup = Markup.NULL;
+      if (selected) {
+        rowMarkup = rowMarkup.add(Markup.SELECTED);
+      }
+      if (rowMarkups != null) {
+        rowMarkup = rowMarkup.add(Markup.valueOf(rowMarkups));
+      }
+      writer.writeClassAttribute(Classes.create(sheet, "row", rowMarkup), selected ? BootstrapClass.TABLE_INFO : null);
+      if (!sheet.isRowVisible()) {
+        final Style rowStyle = new Style();
+        rowStyle.setDisplay(Display.none);
+        writer.writeStyleAttribute(rowStyle);
+      }
+      final String parentId = sheet.getRowParentClientId();
+      if (parentId != null) {
+        writer.writeAttribute(DataAttributes.TREE_PARENT, parentId, false);
+      }
+
+      for (final UIColumn column : columns) {
+        if (column.isRendered()) {
+          if (column instanceof AbstractUIRow) {
+            final AbstractUIRow row = (AbstractUIRow) column;
+            writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, row)));
+            writer.writeIdAttribute(row.getClientId(facesContext));
+
+            // todo: Markup.CLICKABLE ???
+          }
+        }
+      }
+
+      for (final UIColumn column : columns) {
+        if (column.isRendered()) {
+          if (column instanceof AbstractUIColumn) {
+            AbstractUIColumn normalColumn = (AbstractUIColumn) column;
+            writer.startElement(HtmlElements.TD);
+            Markup markup = normalColumn.getMarkup();
+            if (markup == null) {
+              markup = Markup.NULL;
+            }
+            markup = markup.add(getMarkupForAlign(normalColumn));
+            writer.writeClassAttribute(Classes.create(sheet, "cell", markup), normalColumn.getCustomClass());
+            writer.writeStyleAttribute(normalColumn.getStyle());
+
+            if (normalColumn instanceof UIColumnSelector) {
+              UIColumnSelector selector = (UIColumnSelector) normalColumn;
+              writer.startElement(HtmlElements.INPUT);
+              if (selectable.isSingle()) {
+                writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.RADIO);
+              } else {
+                writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
+              }
+              writer.writeAttribute(HtmlAttributes.CHECKED, selected);
+              writer.writeAttribute(HtmlAttributes.DISABLED, selector.isDisabled());
+              writer.writeClassAttribute(
+                  BootstrapClass.FORM_CHECK_INLINE,
+                  Classes.create(sheet, "columnSelector"));
+              writer.endElement(HtmlElements.INPUT);
+            } else if (normalColumn instanceof AbstractUIColumnNode) {
+              RenderUtils.encode(facesContext, normalColumn);
+            } else {
+              final List<UIComponent> children = sheet.getRenderedChildrenOf(normalColumn);
+              for (final UIComponent grandKid : children) {
+                RenderUtils.encode(facesContext, grandKid);
+              }
+            }
+
+            writer.endElement(HtmlElements.TD);
+          }
+        }
+      }
+
+      if (!autoLayout) {
+        writer.startElement(HtmlElements.TD);
+        writer.writeClassAttribute(Classes.create(sheet, "cell", Markup.FILLER));
+//      writer.write("&nbsp;");
+        writer.startElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.TD);
+      }
+
+      writer.endElement(HtmlElements.TR);
+    }
+
+    sheet.setRowIndex(-1);
+
+    if (emptySheet && showHeader) {
+      writer.startElement(HtmlElements.TR);
+      for (final UIColumn column : columns) {
+        if (!(column instanceof AbstractUIRow)) {
+          writer.startElement(HtmlElements.TD);
+          writer.startElement(HtmlElements.DIV);
+          writer.endElement(HtmlElements.DIV);
+          writer.endElement(HtmlElements.TD);
+        }
+      }
+      if (!autoLayout) {
+        writer.startElement(HtmlElements.TD);
+        writer.writeClassAttribute(Classes.create(sheet, "cell", Markup.FILLER));
+//      writer.write("&nbsp;");
+        writer.startElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.DIV);
+        writer.endElement(HtmlElements.TD);
+      }
+      writer.endElement(HtmlElements.TR);
+    }
+
+    writer.endElement(HtmlElements.TBODY);
+
+    writer.endElement(HtmlElements.TABLE);
+    writer.endElement(HtmlElements.DIV);
+
+// END RENDER BODY CONTENT
+
+    if (sheet.isPagingVisible()) {
+      writer.startElement(HtmlElements.FOOTER);
+      writer.writeClassAttribute(Classes.create(sheet, "footer"));
+
+      // show row range
+      final Markup showRowRange = markupForLeftCenterRight(sheet.getShowRowRange());
+      if (showRowRange != Markup.NULL) {
+        final UILink command
+            = ensurePagingCommand(application, sheet, Facets.pagerRow.name(), SheetAction.toRow, false);
+        final String pagerCommandId = command.getClientId(facesContext);
+
+        writer.startElement(HtmlElements.UL);
+        writer.writeClassAttribute(Classes.create(sheet, "paging", showRowRange), BootstrapClass.PAGINATION);
+        writer.startElement(HtmlElements.LI);
+        writer.writeClassAttribute(BootstrapClass.PAGE_ITEM);
+        writer.writeAttribute(HtmlAttributes.TITLE,
+            TobagoResourceBundle.getString(facesContext, "sheetPagingInfoRowPagingTip"), true);
+        writer.startElement(HtmlElements.SPAN);
+        writer.writeClassAttribute(Classes.create(sheet, "pagingText"), BootstrapClass.PAGE_LINK);
+        if (sheet.getRowCount() != 0) {
+          final Locale locale = facesContext.getViewRoot().getLocale();
+          final int first = sheet.getFirst() + 1;
+          final int last1 = sheet.hasRowCount()
+              ? sheet.getLastRowIndexOfCurrentPage()
+              : -1;
+          final boolean unknown = !sheet.hasRowCount();
+          final String key; // plural
+          if (unknown) {
+            if (first == last1) {
+              key = "sheetPagingInfoUndefinedSingleRow";
+            } else {
+              key = "sheetPagingInfoUndefinedRows";
+            }
+          } else {
+            if (first == last1) {
+              key = "sheetPagingInfoSingleRow";
+            } else {
+              key = "sheetPagingInfoRows";
+            }
+          }
+          final String inputMarker = "{#}";
+          final Object[] args = {inputMarker, last1 == -1 ? "?" : last1, unknown ? "" : sheet.getRowCount()};
+          final MessageFormat detail = new MessageFormat(
+              TobagoResourceBundle.getString(facesContext, key), locale);
+          final String formatted = detail.format(args);
+          final int pos = formatted.indexOf(inputMarker);
+          if (pos >= 0) {
+            writer.writeText(formatted.substring(0, pos));
+            writer.startElement(HtmlElements.SPAN);
+            writer.writeClassAttribute(TobagoClass.SHEET__PAGING_OUTPUT);
+            writer.writeText(Integer.toString(first));
+            writer.endElement(HtmlElements.SPAN);
+            writer.startElement(HtmlElements.INPUT);
+            writer.writeIdAttribute(pagerCommandId);
+            writer.writeNameAttribute(pagerCommandId);
+            writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.TEXT);
+            writer.writeClassAttribute(TobagoClass.SHEET__PAGING_INPUT);
+            writer.writeAttribute(HtmlAttributes.VALUE, first);
+            if (!unknown) {
+              writer.writeAttribute(HtmlAttributes.MAXLENGTH, Integer.toString(sheet.getRowCount()).length());
+            }
+            writer.endElement(HtmlElements.INPUT);
+            writer.writeText(formatted.substring(pos + inputMarker.length()));
+          } else {
+            writer.writeText(formatted);
+          }
+        } else {
+          writer.write(TobagoResourceBundle.getString(facesContext, "sheetPagingInfoEmptyRow"));
+        }
+        writer.endElement(HtmlElements.SPAN);
+        writer.endElement(HtmlElements.LI);
+        writer.endElement(HtmlElements.UL);
+      }
+
+      // show direct links
+      final Markup showDirectLinks = markupForLeftCenterRight(sheet.getShowDirectLinks());
+      if (showDirectLinks != Markup.NULL) {
+        writer.startElement(HtmlElements.UL);
+        writer.writeClassAttribute(
+            Classes.create(sheet, "paging", showDirectLinks), BootstrapClass.PAGINATION);
+        if (sheet.isShowDirectLinksArrows()) {
+          final boolean disabled = sheet.isAtBeginning();
+          encodeLink(facesContext, sheet, application, disabled, SheetAction.first, null, Icons.STEP_BACKWARD, null);
+          encodeLink(facesContext, sheet, application, disabled, SheetAction.prev, null, Icons.BACKWARD, null);
+        }
+        encodeDirectPagingLinks(facesContext, application, sheet);
+        if (sheet.isShowDirectLinksArrows()) {
+          final boolean disabled = sheet.isAtEnd();
+          encodeLink(facesContext, sheet, application, disabled, SheetAction.next, null, Icons.FORWARD, null);
+          encodeLink(facesContext, sheet, application, disabled || !sheet.hasRowCount(), SheetAction.last, null,
+              Icons.STEP_FORWARD, null);
+        }
+        writer.endElement(HtmlElements.UL);
+      }
+
+      // show page range
+      final Markup showPageRange = markupForLeftCenterRight(sheet.getShowPageRange());
+      if (showPageRange != Markup.NULL) {
+        final UILink command
+            = ensurePagingCommand(application, sheet, Facets.pagerPage.name(), SheetAction.toPage, false);
+        final String pagerCommandId = command.getClientId(facesContext);
+
+        writer.startElement(HtmlElements.UL);
+        writer.writeClassAttribute(Classes.create(sheet, "paging", showPageRange), BootstrapClass.PAGINATION);
+
+        if (sheet.isShowPageRangeArrows()) {
+          final boolean disabled = sheet.isAtBeginning();
+          encodeLink(facesContext, sheet, application, disabled, SheetAction.first, null, Icons.STEP_BACKWARD, null);
+          encodeLink(facesContext, sheet, application, disabled, SheetAction.prev, null, Icons.BACKWARD, null);
+        }
+        writer.startElement(HtmlElements.LI);
+        writer.writeClassAttribute(BootstrapClass.PAGE_ITEM);
+        writer.startElement(HtmlElements.SPAN);
+        writer.writeClassAttribute(Classes.create(sheet, "pagingText"), BootstrapClass.PAGE_LINK);
+        writer.writeAttribute(HtmlAttributes.TITLE,
+            TobagoResourceBundle.getString(facesContext, "sheetPagingInfoPagePagingTip"), true);
+        if (sheet.getRowCount() != 0) {
+          final Locale locale = facesContext.getViewRoot().getLocale();
+          final int first = sheet.getCurrentPage() + 1;
+          final boolean unknown = !sheet.hasRowCount();
+          final int pages = unknown ? -1 : sheet.getPages();
+          final String key;
+          if (unknown) {
+            if (first == pages) {
+              key = "sheetPagingInfoUndefinedSinglePage";
+            } else {
+              key = "sheetPagingInfoUndefinedPages";
+            }
+          } else {
+            if (first == pages) {
+              key = "sheetPagingInfoSinglePage";
+            } else {
+              key = "sheetPagingInfoPages";
+            }
+          }
+          final String inputMarker = "{#}";
+          final Object[] args = {inputMarker, pages == -1 ? "?" : pages};
+          final MessageFormat detail = new MessageFormat(
+              TobagoResourceBundle.getString(facesContext, key), locale);
+          final String formatted = detail.format(args);
+          final int pos = formatted.indexOf(inputMarker);
+          if (pos >= 0) {
+            writer.writeText(formatted.substring(0, pos));
+            writer.startElement(HtmlElements.SPAN);
+            writer.writeClassAttribute(TobagoClass.SHEET__PAGING_OUTPUT);
+            writer.writeText(Integer.toString(first));
+            writer.endElement(HtmlElements.SPAN);
+            writer.startElement(HtmlElements.INPUT);
+            writer.writeIdAttribute(pagerCommandId);
+            writer.writeNameAttribute(pagerCommandId);
+            writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.TEXT);
+            writer.writeClassAttribute(TobagoClass.SHEET__PAGING_INPUT);
+            writer.writeAttribute(HtmlAttributes.VALUE, first);
+            if (!unknown) {
+              writer.writeAttribute(HtmlAttributes.MAXLENGTH, Integer.toString(pages).length());
+            }
+            writer.endElement(HtmlElements.INPUT);
+            writer.writeText(formatted.substring(pos + inputMarker.length()));
+          } else {
+            writer.writeText(formatted);
+          }
+        } else {
+          writer.writeText(TobagoResourceBundle.getString(facesContext, "sheetPagingInfoEmptyPage"));
+        }
+        writer.endElement(HtmlElements.SPAN);
+        writer.endElement(HtmlElements.LI);
+        if (sheet.isShowPageRangeArrows()) {
+          final boolean disabled = sheet.isAtEnd();
+          encodeLink(facesContext, sheet, application, disabled, SheetAction.next, null, Icons.FORWARD, null);
+          encodeLink(facesContext, sheet, application, disabled || !sheet.hasRowCount(), SheetAction.last, null,
+              Icons.STEP_FORWARD, null);
+        }
+        writer.endElement(HtmlElements.UL);
+      }
+
+      writer.endElement(HtmlElements.FOOTER);
+    }
+
+    if (sheet.isTreeModel()) {
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+      final String expandedId = sheetId + ComponentUtils.SUB_SEPARATOR + AbstractUIData.SUFFIX_EXPANDED;
+      writer.writeNameAttribute(expandedId);
+      writer.writeIdAttribute(expandedId);
+      writer.writeClassAttribute(Classes.create(sheet, AbstractUIData.SUFFIX_EXPANDED));
+      writer.writeAttribute(HtmlAttributes.VALUE, expandedValue.toString(), false);
+      writer.endElement(HtmlElements.INPUT);
+    }
+
+    writer.endElement(HtmlElements.DIV);
+  }
+
+  private void ensureColumnWidthsSize(
+      final List<Integer> columnWidths, final List<AbstractUIColumnBase> columns, final List<Integer> samples) {
+    // we have to fill the non rendered positions with some values.
+    // on client site, we don't know nothing about the non-rendered columns.
+    int i = 0;
+    int j = 0;
+    for (AbstractUIColumnBase column : columns) {
+      if (!(column instanceof AbstractUIRow)) {
+        Integer newValue;
+        if (j < samples.size()) {
+          newValue = samples.get(j);
+          j++;
+        } else {
+          newValue = null;
+        }
+        if (columnWidths.size() > i) {
+          if (newValue != null) {
+            columnWidths.set(i, newValue);
+          }
+        } else {
+          columnWidths.add(newValue != null ? newValue : -1); // -1 means unknown or undefined
+        }
+        i++;
+      }
+    }
+  }
+
+  private Markup getMarkupForAlign(UIColumn column) {
+    final String textAlign = ComponentUtils.getStringAttribute(column, Attributes.align);
+    if (textAlign != null) {
+      switch (TextAlign.valueOf(textAlign)) {
+        case right:
+          return Markup.RIGHT;
+        case center:
+          return Markup.CENTER;
+        case justify:
+          return Markup.JUSTIFY;
+        default:
+          // nothing to do
+      }
+    }
+    return null;
+  }
+
+  private void encodeHeaderRows(
+      final FacesContext facesContext, final UISheet sheet, final TobagoResponseWriter writer,
+      final List<AbstractUIColumnBase> columns)
+      throws IOException {
+
+    final Selectable selectable = sheet.getSelectable();
+    final Grid grid = sheet.getHeaderGrid();
+    final boolean autoLayout = sheet.isAutoLayout();
+    final boolean multiHeader = grid.getRowCount() > 1;
+    int offset = 0;
+
+    for (int i = 0; i < grid.getRowCount(); i++) {
+      writer.startElement(HtmlElements.TR);
+      for (int j = 0; j < columns.size(); j++) {
+        final AbstractUIColumnBase column = columns.get(j);
+        if (!column.isRendered() || column instanceof AbstractUIRow) {
+          offset++;
+        } else {
+          final Cell cell = grid.getCell(j - offset, i);
+          if (cell instanceof OriginCell) {
+            writer.startElement(HtmlElements.TH);
+            writer.writeClassAttribute(column.getCustomClass());
+            writer.writeStyleAttribute(column.getStyle());
+            if (cell.getColumnSpan() > 1) {
+              writer.writeAttribute(HtmlAttributes.COLSPAN, cell.getColumnSpan());
+            }
+            if (cell.getRowSpan() > 1) {
+              writer.writeAttribute(HtmlAttributes.ROWSPAN, cell.getRowSpan());
+            }
+
+            final UIComponent cellComponent = cell.getComponent();
+
+            final CssItem align;
+            final String alignString = ComponentUtils.getStringAttribute(column, Attributes.align);
+            if (multiHeader && cell.getColumnSpan() > 1) {
+              align = TobagoClass.SHEET__CELL__MARKUP__CENTER;
+            } else if (alignString != null) {
+              switch (TextAlign.valueOf(alignString)) {
+                case right:
+                  align = TobagoClass.SHEET__CELL__MARKUP__RIGHT;
+                  break;
+                case center:
+                  align = TobagoClass.SHEET__CELL__MARKUP__CENTER;
+                  break;
+                case justify:
+                  align = TobagoClass.SHEET__CELL__MARKUP__JUSTIFY;
+                  break;
+                default:
+                  align = null;
+              }
+            } else {
+              align = null;
+            }
+            writer.writeClassAttribute(Classes.create(sheet, "headerCell"), align);
+            writer.startElement(HtmlElements.SPAN);
+            Icons sorterIcon = null;
+            Markup markup = Markup.NULL;
+            String tip = ComponentUtils.getStringAttribute(column, Attributes.tip);
+            // sorter icons should only displayed when there is only 1 column and not input
+            if (cell.getColumnSpan() == 1 && cellComponent instanceof UIOut) {
+              final boolean sortable = ComponentUtils.getBooleanAttribute(column, Attributes.sortable);
+              if (sortable) {
+                UILink sortCommand = (UILink) ComponentUtils.getFacet(column, Facets.sorter);
+                if (sortCommand == null) {
+                  final String columnId = column.getClientId(facesContext);
+                  final String sorterId = columnId.substring(columnId.lastIndexOf(":") + 1) + "_" + UISheet.SORTER_ID;
+                  sortCommand = (UILink) ComponentUtils.createComponent(
+                      facesContext, UILink.COMPONENT_TYPE, RendererTypes.Link, sorterId);
+                  final AjaxBehavior reloadBehavior = createReloadBehavior(sheet);
+                  sortCommand.addClientBehavior("click", reloadBehavior);
+                  sortCommand.setRendererType(RendererTypes.SHEET_PAGE_COMMAND);
+                  ComponentUtils.setAttribute(sortCommand, Attributes.sheetAction, SheetAction.sort);
+                  ComponentUtils.setFacet(column, Facets.sorter, sortCommand);
+                }
+                writer.writeIdAttribute(sortCommand.getClientId(facesContext));
+                writer.writeCommandMapAttribute(
+                    JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, sortCommand)));
+
+                if (tip == null) {
+                  tip = "";
+                } else {
+                  tip += " - ";
+                }
+                tip += TobagoResourceBundle.getString(facesContext, "sheetTipSorting");
+
+                markup = markup.add(Markup.SORTABLE);
+
+                final SheetState sheetState = sheet.getSheetState(facesContext);
+                if (column.getId().equals(sheetState.getSortedColumnId())) {
+                  final String sortTitle;
+                  if (sheetState.isAscending()) {
+                    sorterIcon = Icons.ANGLE_UP;
+                    sortTitle = TobagoResourceBundle.getString(facesContext, "sheetAscending");
+                    markup = markup.add(Markup.ASCENDING);
+                  } else {
+                    sorterIcon = Icons.ANGLE_DOWN;
+                    sortTitle = TobagoResourceBundle.getString(facesContext, "sheetDescending");
+                    markup = markup.add(Markup.DESCENDING);
+                  }
+                  if (sortTitle != null) {
+                    tip += " - " + sortTitle;
+                  }
+                }
+              }
+            }
+
+            writer.writeClassAttribute(Classes.create(sheet, "header", markup));
+            writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
+
+            if (column instanceof UIColumnSelector && selectable.isMulti()) {
+              writer.writeClassAttribute(Classes.create(sheet, "selectorDropdown"));
+
+              writer.startElement(HtmlElements.DIV);
+              writer.writeClassAttribute(BootstrapClass.DROPDOWN);
+              writer.startElement(HtmlElements.BUTTON);
+              writer.writeClassAttribute(
+                  BootstrapClass.BTN, BootstrapClass.BTN_SECONDARY, BootstrapClass.DROPDOWN_TOGGLE);
+              writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+              writer.writeIdAttribute(sheet.getClientId(facesContext) + SUFFIX_SELECTOR_DROPDOWN);
+              writer.writeAttribute(DataAttributes.TOGGLE, "dropdown", false);
+              writer.writeAttribute(Arias.HASPOPUP, Boolean.TRUE.toString(), false);
+              writer.writeAttribute(Arias.EXPANDED, Boolean.FALSE.toString(), false);
+              writer.endElement(HtmlElements.BUTTON);
+              writer.startElement(HtmlElements.DIV);
+              writer.writeClassAttribute(BootstrapClass.DROPDOWN_MENU);
+              writer
+                  .writeAttribute(Arias.LABELLEDBY, sheet.getClientId(facesContext) + SUFFIX_SELECTOR_DROPDOWN, false);
+              writer.startElement(HtmlElements.BUTTON);
+              writer.writeClassAttribute(BootstrapClass.DROPDOWN_ITEM);
+              writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+              writer.writeAttribute(DataAttributes.COMMAND, "sheetSelectAll", false);
+              writer.writeText(TobagoResourceBundle.getString(facesContext, "sheetMenuSelect"));
+              writer.endElement(HtmlElements.BUTTON);
+              writer.startElement(HtmlElements.BUTTON);
+              writer.writeClassAttribute(BootstrapClass.DROPDOWN_ITEM);
+              writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+              writer.writeAttribute(DataAttributes.COMMAND, "sheetDeselectAll", false);
+              writer.writeText(TobagoResourceBundle.getString(facesContext, "sheetMenuUnselect"));
+              writer.endElement(HtmlElements.BUTTON);
+              writer.startElement(HtmlElements.BUTTON);
+              writer.writeClassAttribute(BootstrapClass.DROPDOWN_ITEM);
+              writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
+              writer.writeAttribute(DataAttributes.COMMAND, "sheetToggleAll", false);
+              writer
+                  .writeText(TobagoResourceBundle.getString(facesContext, "sheetMenuToggleselect"));
+              writer.endElement(HtmlElements.BUTTON);
+              writer.endElement(HtmlElements.DIV);
+              writer.endElement(HtmlElements.DIV);
+            } else {
+              RenderUtils.encode(facesContext, cellComponent);
+            }
+
+            if (sorterIcon != null) {
+              writer.writeIcon(sorterIcon);
+            }
+
+            writer.endElement(HtmlElements.SPAN);
+            if (!autoLayout) {
+              if (column.isResizable()) {
+                encodeResizing(writer, sheet, j - offset + cell.getColumnSpan() - 1);
+              }
+            }
+
+            writer.endElement(HtmlElements.TH);
+          }
+        }
+      }
+      if (!autoLayout) {
+        // Add two filler columns. The second one get the size of the scrollBar via JavaScript.
+        encodeHeaderFiller(writer, sheet);
+        encodeHeaderFiller(writer, sheet);
+      }
+
+      writer.endElement(HtmlElements.TR);
+    }
+  }
+
+  private void encodeHeaderFiller(final TobagoResponseWriter writer, final UISheet sheet) throws IOException {
+    writer.startElement(HtmlElements.TH);
+    writer.writeClassAttribute(Classes.create(sheet, "headerCell", Markup.FILLER));
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(Classes.create(sheet, "header"));
+    final Style headerStyle = new Style();
+    headerStyle.setHeight(Measure.valueOf(14)); // XXX todo
+    writer.writeStyleAttribute(headerStyle);
+    writer.endElement(HtmlElements.SPAN);
+    writer.endElement(HtmlElements.TH);
+  }
+
+  private void writeColgroup(
+      final TobagoResponseWriter writer, final List<Integer> columnWidths,
+      final List<AbstractUIColumnBase> columns, boolean isHeader) throws IOException {
+    writer.startElement(HtmlElements.COLGROUP);
+
+    int i = 0;
+    for (AbstractUIColumnBase column : columns) {
+      if (!(column instanceof AbstractUIRow)) {
+        if (column.isRendered()) {
+          final Integer width = columnWidths.get(i);
+          writeCol(writer, width >= 0 ? width : null);
+        }
+        i++;
+      }
+    }
+    writeCol(writer, null); // extra entry for resizing...
+    if (isHeader) {
+      writeCol(writer, null); // extra entry for headerFiller
+    }
+    // TODO: the value should be added to the list
+    writer.endElement(HtmlElements.COLGROUP);
+  }
+
+  private void writeCol(final TobagoResponseWriter writer, final Integer columnWidth) throws IOException {
+    writer.startElement(HtmlElements.COL);
+    writer.writeAttribute(HtmlAttributes.WIDTH, columnWidth);
+    writer.endElement(HtmlElements.COL);
+  }
+
+  private Markup markupForLeftCenterRight(final ShowPosition position) {
+    switch (position) {
+      case left:
+        return Markup.LEFT;
+      case center:
+        return Markup.CENTER;
+      case right:
+        return Markup.RIGHT;
+      default:
+        return Markup.NULL;
+    }
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  private List<Integer> getSelectedRows(final UISheet data, final SheetState state) {
+    List<Integer> selected = (List<Integer>) ComponentUtils.getAttribute(data, Attributes.selectedListString);
+    if (selected == null && state != null) {
+      selected = state.getSelectedRows();
+    }
+    if (selected == null) {
+      selected = Collections.emptyList();
+    }
+    return selected;
+  }
+
+  private void encodeLink(
+      final FacesContext facesContext, final UISheet data, final Application application,
+      final boolean disabled, final SheetAction action, Integer target, Icons icon, CssItem liClass)
+      throws IOException {
+
+    final String facet = action == SheetAction.toPage || action == SheetAction.toRow
+        ? action.name() + "-" + target
+        : action.name();
+    final UILink command = ensurePagingCommand(application, data, facet, action, disabled);
+    if (target != null) {
+      ComponentUtils.setAttribute(command, Attributes.pagingTarget, target);
+    }
+
+    final Locale locale = facesContext.getViewRoot().getLocale();
+    final String message = TobagoResourceBundle.getString(facesContext, action.getBundleKey());
+    final String tip = new MessageFormat(message, locale).format(new Integer[]{target}); // needed fot ToPage
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.startElement(HtmlElements.LI);
+    writer.writeClassAttribute(liClass, disabled ? BootstrapClass.DISABLED : null, BootstrapClass.PAGE_ITEM);
+// todo button
+    writer.startElement(HtmlElements.A);
+    writer.writeClassAttribute(BootstrapClass.PAGE_LINK);
+    writer.writeAttribute(HtmlAttributes.HREF, "#/", false);
+    writer.writeIdAttribute(command.getClientId(facesContext));
+    writer.writeAttribute(HtmlAttributes.TITLE, tip, true);
+    if (!disabled) {
+      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, command)));
+    }
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    if (icon != null) {
+      writer.writeIcon(icon);
+    } else {
+      writer.writeText(String.valueOf(target));
+    }
+    writer.endElement(HtmlElements.A);
+    writer.endElement(HtmlElements.LI);
+  }
+
+  // TODO sheet.getColumnLayout() may return the wrong number of column...
+  // TODO
+  // TODO
+
+  private void encodeResizing(final TobagoResponseWriter writer, final AbstractUISheet sheet, final int columnIndex)
+      throws IOException {
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(Classes.create(sheet, "headerResize"));
+    writer.writeAttribute(DataAttributes.COLUMN_INDEX, Integer.toString(columnIndex), false);
+    writer.write("&nbsp;&nbsp;"); // is needed for IE
+    writer.endElement(HtmlElements.SPAN);
+  }
+
+  private void encodeDirectPagingLinks(
+      final FacesContext facesContext, final Application application, final UISheet sheet)
+      throws IOException {
+
+    final UILink command
+        = ensurePagingCommand(application, sheet, Facets.PAGER_PAGE_DIRECT, SheetAction.toPage, false);
+    int linkCount = ComponentUtils.getIntAttribute(sheet, Attributes.directLinkCount);
+    linkCount--;  // current page needs no link
+    final ArrayList<Integer> prevs = new ArrayList<Integer>(linkCount);
+    int page = sheet.getCurrentPage() + 1;
+    for (int i = 0; i < linkCount && page > 1; i++) {
+      page--;
+      if (page > 0) {
+        prevs.add(0, page);
+      }
+    }
+
+    final ArrayList<Integer> nexts = new ArrayList<Integer>(linkCount);
+    page = sheet.getCurrentPage() + 1;
+    final int pages = sheet.hasRowCount() || sheet.isRowsUnlimited() ? sheet.getPages() : Integer.MAX_VALUE;
+    for (int i = 0; i < linkCount && page < pages; i++) {
+      page++;
+      if (page > 1) {
+        nexts.add(page);
+      }
+    }
+
+    if (prevs.size() > (linkCount / 2)
+        && nexts.size() > (linkCount - (linkCount / 2))) {
+      while (prevs.size() > (linkCount / 2)) {
+        prevs.remove(0);
+      }
+      while (nexts.size() > (linkCount - (linkCount / 2))) {
+        nexts.remove(nexts.size() - 1);
+      }
+    } else if (prevs.size() <= (linkCount / 2)) {
+      while (prevs.size() + nexts.size() > linkCount) {
+        nexts.remove(nexts.size() - 1);
+      }
+    } else {
+      while (prevs.size() + nexts.size() > linkCount) {
+        prevs.remove(0);
+      }
+    }
+
+    int skip = prevs.size() > 0 ? prevs.get(0) : 1;
+    if (!sheet.isShowDirectLinksArrows() && skip > 1) {
+      skip -= (linkCount - (linkCount / 2));
+      skip--;
+      if (skip < 1) {
+        skip = 1;
+      }
+      encodeLink(facesContext, sheet, application, false, SheetAction.toPage, skip, Icons.ELLIPSIS_H, null);
+    }
+    for (final Integer prev : prevs) {
+      encodeLink(facesContext, sheet, application, false, SheetAction.toPage, prev, null, null);
+    }
+    encodeLink(facesContext, sheet, application, false, SheetAction.toPage,
+        sheet.getCurrentPage() + 1, null, BootstrapClass.ACTIVE);
+
+    for (final Integer next : nexts) {
+      encodeLink(facesContext, sheet, application, false, SheetAction.toPage, next, null, null);
+    }
+
+    skip = nexts.size() > 0 ? nexts.get(nexts.size() - 1) : pages;
+    if (!sheet.isShowDirectLinksArrows() && skip < pages) {
+      skip += linkCount / 2;
+      skip++;
+      if (skip > pages) {
+        skip = pages;
+      }
+      encodeLink(facesContext, sheet, application, false, SheetAction.toPage, skip, Icons.ELLIPSIS_H, null);
+    }
+  }
+
+  private UILink ensurePagingCommand(
+      final Application application, final UISheet sheet, final String facet, final SheetAction action,
+      final boolean disabled) {
+
+    final Map<String, UIComponent> facets = sheet.getFacets();
+    UILink command = (UILink) facets.get(facet);
+    if (command == null) {
+      command = (UILink) application.createComponent(UILink.COMPONENT_TYPE);
+      command.setRendererType(RendererTypes.SHEET_PAGE_COMMAND);
+//      command.addActionListener(new SheetActionListener()); XXX to activate: remove RendererType
+      command.setRendered(true);
+      ComponentUtils.setAttribute(command, Attributes.sheetAction, action);
+      command.setDisabled(disabled);
+      facets.put(facet, command);
+
+      // add AjaxBehavior
+      final AjaxBehavior behavior = createReloadBehavior(sheet);
+      command.addClientBehavior("click", behavior);
+    }
+    return command;
+  }
+
+  private AjaxBehavior createReloadBehavior(UISheet sheet) {
+    AjaxBehavior reloadBehavior = findReloadBehavior(sheet);
+    final ArrayList<String> renderIds = new ArrayList<String>();
+    if (!renderIds.contains(sheet.getId())) {
+      renderIds.add(sheet.getId());
+    }
+    if (reloadBehavior != null) {
+      renderIds.addAll(reloadBehavior.getRender());
+    }
+    final ArrayList<String> executeIds = new ArrayList<String>();
+    if (!executeIds.contains(sheet.getId())) {
+      executeIds.add(sheet.getId());
+    }
+    if (reloadBehavior != null) {
+      executeIds.addAll(reloadBehavior.getExecute());
+    }
+    final AjaxBehavior behavior = new AjaxBehavior();
+    behavior.setExecute(executeIds);
+    behavior.setRender(renderIds);
+    return behavior;
+  }
+
+  private AjaxBehavior findReloadBehavior(ClientBehaviorHolder holder) {
+    final List<ClientBehavior> reload = holder.getClientBehaviors().get("reload");
+    if (reload != null && !reload.isEmpty() && reload.get(0) instanceof AjaxBehavior) {
+      return (AjaxBehavior) reload.get(0);
+    } else {
+      return null;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StyleRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StyleRenderer.java
new file mode 100644
index 0000000..b05779e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/StyleRenderer.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UIStyle;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.internal.util.FacesContextUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.CustomClass;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PostAddToViewEvent;
+
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
+public class StyleRenderer extends RendererBase implements ComponentSystemEventListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(StyleRenderer.class);
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final UIStyle styleComponent = (UIStyle) event.getComponent();
+    final String file = styleComponent.getFile();
+    if (file != null) {
+      FacesContextUtils.addStyleFile(facesContext, file);
+    }
+
+    final Style style = new Style(styleComponent);
+    if (!style.isEmpty()) {
+      final UIComponent parent = styleComponent.getParent();
+      if (parent instanceof Visual) {
+        ((Visual) parent).setStyle(style);
+      } else {
+        LOG.warn("The parent of a style component doesn't support style: " + parent.getClientId(facesContext));
+      }
+    }
+
+    final CustomClass customClass = styleComponent.getCustomClass();
+    if (customClass != null) {
+      final UIComponent parent = styleComponent.getParent();
+      if (parent instanceof Visual) {
+        ((Visual) parent).setCustomClass(customClass);
+      } else {
+        LOG.warn("The parent of a style component doesn't support style: " + parent.getClientId(facesContext));
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SubviewRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SubviewRenderer.java
new file mode 100644
index 0000000..0fbce65
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SubviewRenderer.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class SubviewRenderer extends RendererBase {
+
+    private static final Logger LOG = LoggerFactory.getLogger(SubviewRenderer.class);
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component)
+      throws IOException {
+    if (LOG.isInfoEnabled()) {
+      LOG.info("SSSSSSSSSSSSSSSSSSS Subview component = " + component.getClass().getName());
+    }
+    super.encodeBegin(facesContext, component);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext,
+                        final UIComponent component) throws IOException {
+
+  }
+
+}
+
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SuggestRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SuggestRenderer.java
new file mode 100644
index 0000000..7d8cdca
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/SuggestRenderer.java
@@ -0,0 +1,163 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIInput;
+import org.apache.myfaces.tobago.internal.component.AbstractUISuggest;
+import org.apache.myfaces.tobago.model.AutoSuggestItem;
+import org.apache.myfaces.tobago.model.AutoSuggestItems;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.SelectItemUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.MethodExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+public class SuggestRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SuggestRenderer.class);
+
+  @Override
+  public void decode(FacesContext facesContext, UIComponent component) {
+    final AbstractUISuggest suggest = (AbstractUISuggest) component;
+    final String clientId = suggest.getClientId(facesContext);
+    final Map<String, String> requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
+    if (requestParameterMap.containsKey(clientId)) {
+      final String query = requestParameterMap.get(clientId);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("suggest query='{}'", query);
+      }
+      // XXX this is for the old way: for "suggestMethod"
+      final AbstractUIInput input = ComponentUtils.findAncestor(suggest, AbstractUIInput.class);
+      if (input != null) {
+        input.setSubmittedValue(query);
+      }
+      // this is the new way: for select items
+      suggest.setQuery(query);
+    }
+  }
+
+  @Override
+  public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
+    final AbstractUISuggest suggest = (AbstractUISuggest) component;
+    final AbstractUIInput input = ComponentUtils.findAncestor(suggest, AbstractUIInput.class);
+    final MethodExpression suggestMethodExpression = suggest.getSuggestMethodExpression();
+
+    int totalCount = suggest.getTotalCount();
+    String[] array;
+
+    if (suggestMethodExpression != null && input != null) { // old way (deprecated)
+      final AutoSuggestItems autoSuggestItems
+          = createAutoSuggestItems(suggestMethodExpression.invoke(facesContext.getELContext(), new Object[]{input}));
+      final List<AutoSuggestItem> items = autoSuggestItems.getItems();
+
+      if (totalCount == -1 || items.size() < totalCount) {
+        totalCount = items.size();
+      }
+
+      array = new String[totalCount];
+      for (int i = 0; i < totalCount; i++) {
+        array[i] = items.get(i).getLabel();
+      }
+    } else {
+      final List<SelectItem> items = SelectItemUtils.getItemList(facesContext, suggest);
+
+      if (totalCount == -1 || items.size() < totalCount) {
+        totalCount = items.size();
+      }
+
+      array = new String[totalCount];
+      for (int i = 0; i < totalCount; i++) {
+        array[i] = items.get(i).getLabel();
+      }
+    }
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeClassAttribute(TobagoClass.SUGGEST);
+    final String clientId = suggest.getClientId(facesContext);
+    writer.writeIdAttribute(clientId);
+    writer.writeNameAttribute(clientId);
+    if (input != null) {
+      writer.writeAttribute(DataAttributes.SUGGEST_FOR, input.getFieldId(facesContext), false);
+    } else {
+      LOG.error("No ancestor with type AbstractUIInput found for suggest id={}", clientId);
+    }
+    writer.writeAttribute(DataAttributes.SUGGEST_MIN_CHARS, suggest.getMinimumCharacters());
+    writer.writeAttribute(DataAttributes.SUGGEST_DELAY, suggest.getDelay());
+    writer.writeAttribute(DataAttributes.SUGGEST_MAX_ITEMS, suggest.getMaximumItems());
+    writer.writeAttribute(DataAttributes.SUGGEST_UPDATE, suggest.isUpdate());
+    writer.writeAttribute(DataAttributes.SUGGEST_TOTAL_COUNT, totalCount);
+    writer.writeAttribute(DataAttributes.SUGGEST_DATA, JsonUtils.encode(array), true);
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("suggest list: " + JsonUtils.encode(array));
+    }
+
+    writer.endElement(HtmlElements.INPUT);
+  }
+
+  private AutoSuggestItems createAutoSuggestItems(final Object object) {
+    if (object instanceof AutoSuggestItems) {
+      return (AutoSuggestItems) object;
+    }
+    final AutoSuggestItems autoSuggestItems = new AutoSuggestItems();
+    if (object instanceof List && !((List) object).isEmpty()) {
+      if (((List) object).get(0) instanceof AutoSuggestItem) {
+        //noinspection unchecked
+        autoSuggestItems.setItems((List<AutoSuggestItem>) object);
+      } else if (((List) object).get(0) instanceof String) {
+        final List<AutoSuggestItem> items = new ArrayList<AutoSuggestItem>(((List) object).size());
+        for (int i = 0; i < ((List) object).size(); i++) {
+          final AutoSuggestItem item = new AutoSuggestItem();
+          item.setLabel((String) ((List) object).get(i));
+          item.setValue((String) ((List) object).get(i));
+          items.add(item);
+        }
+        autoSuggestItems.setItems(items);
+      } else {
+        throw new ClassCastException("Can't create AutoSuggestItems from '" + object + "'. "
+            + "Elements needs to be " + String.class.getName() + " or " + AutoSuggestItem.class.getName());
+      }
+    } else {
+      autoSuggestItems.setItems(Collections.<AutoSuggestItem>emptyList());
+    }
+    return autoSuggestItems;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabGroupRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabGroupRenderer.java
new file mode 100644
index 0000000..212bd4d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabGroupRenderer.java
@@ -0,0 +1,338 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.UIEvent;
+import org.apache.myfaces.tobago.component.UITab;
+import org.apache.myfaces.tobago.component.UITabGroup;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.event.TabChangeEvent;
+import org.apache.myfaces.tobago.internal.behavior.EventBehavior;
+import org.apache.myfaces.tobago.internal.component.AbstractUIPanelBase;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.model.SwitchType;
+import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.behavior.AjaxBehavior;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ComponentSystemEvent;
+import javax.faces.event.ComponentSystemEventListener;
+import javax.faces.event.ListenerFor;
+import javax.faces.event.PostAddToViewEvent;
+import java.io.IOException;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+
+@ListenerFor(systemEventClass = PostAddToViewEvent.class)
+public class TabGroupRenderer extends RendererBase implements ComponentSystemEventListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TabGroupRenderer.class);
+
+  private static final String ACTIVE_INDEX_POSTFIX = ComponentUtils.SUB_SEPARATOR + "activeIndex";
+
+  @Override
+  public void processEvent(ComponentSystemEvent event) {
+
+    final UITabGroup tabGroup = (UITabGroup) event.getComponent();
+
+    for (final UIComponent child : tabGroup.getChildren()) {
+      if (child instanceof UITab) {
+        final UITab tab = (UITab) child;
+        if (tab.isRendered()) {
+          final FacesContext facesContext = FacesContext.getCurrentInstance();
+          final ClientBehaviors click = ClientBehaviors.click;
+          switch (tabGroup.getSwitchType()) {
+            case none:
+              break;
+            case client:
+              // todo: implement a client behavior which can call local scripts (respect CSP)
+              break;
+            case reloadTab:
+              final AjaxBehavior ajaxBehavior = new AjaxBehavior();
+              final Collection<String> ids = Collections.singleton(
+                  UINamingContainer.getSeparatorChar(facesContext) + tabGroup.getClientId(facesContext));
+              ajaxBehavior.setExecute(ids);
+              ajaxBehavior.setRender(ids);
+              tab.addClientBehavior(click.name(), ajaxBehavior);
+              break;
+            case reloadPage:
+              final EventBehavior eventBehavior = new EventBehavior();
+              tab.addClientBehavior(click.name(), eventBehavior);
+              final UIEvent component = (UIEvent) ComponentUtils.createComponent(
+                  facesContext, UIEvent.COMPONENT_TYPE, RendererTypes.Event, "_click");
+              component.setEvent(click);
+              tab.getChildren().add(component);
+              break;
+            default:
+              LOG.error("Unknown switch type: '{}'", tabGroup.getSwitchType());
+          }
+        }
+      }
+    }
+  }
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    if (ComponentUtils.isOutputOnly(component)) {
+      return;
+    }
+
+    final int oldIndex = ((UITabGroup) component).getRenderedIndex();
+
+    final String clientId = component.getClientId(facesContext);
+    final Map parameters = facesContext.getExternalContext().getRequestParameterMap();
+    final String newValue = (String) parameters.get(clientId + ACTIVE_INDEX_POSTFIX);
+    try {
+      final int activeIndex = Integer.parseInt(newValue);
+      if (activeIndex != oldIndex) {
+        final TabChangeEvent event = new TabChangeEvent(component, oldIndex, activeIndex);
+        component.queueEvent(event);
+      }
+    } catch (final NumberFormatException e) {
+      LOG.error("Can't parse activeIndex: '" + newValue + "'");
+    }
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent uiComponent) throws IOException {
+
+    final UITabGroup tabGroup = (UITabGroup) uiComponent;
+
+    final int activeIndex = ensureRenderedActiveIndex(facesContext, tabGroup);
+
+    final String clientId = tabGroup.getClientId(facesContext);
+    final String hiddenId = clientId + TabGroupRenderer.ACTIVE_INDEX_POSTFIX;
+    final SwitchType switchType = tabGroup.getSwitchType();
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(clientId);
+    writer.writeClassAttribute(Classes.create(tabGroup), tabGroup.getCustomClass());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, tabGroup);
+    writer.writeStyleAttribute(tabGroup.getStyle());
+    writer.writeAttribute(HtmlAttributes.SWITCHTYPE, switchType.name(), false);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeAttribute(HtmlAttributes.VALUE, activeIndex);
+    writer.writeNameAttribute(hiddenId);
+    writer.writeIdAttribute(hiddenId);
+    writer.endElement(HtmlElements.INPUT);
+
+    encodeHeader(facesContext, writer, tabGroup, activeIndex, switchType);
+
+    encodeContent(facesContext, writer, tabGroup, activeIndex, switchType);
+
+    writer.endElement(HtmlElements.DIV);
+  }
+
+  private int ensureRenderedActiveIndex(final FacesContext context, final UITabGroup tabGroup) {
+    final int activeIndex = tabGroup.getSelectedIndex();
+    // ensure to select a rendered tab
+    int index = -1;
+    int closestRenderedTabIndex = -1;
+    for (final UIComponent tab : tabGroup.getChildren()) {
+      index++;
+      if (tab instanceof AbstractUIPanelBase) {
+        if (index == activeIndex) {
+          if (tab.isRendered()) {
+            return index;
+          } else if (closestRenderedTabIndex > -1) {
+            break;
+          }
+        }
+        if (tab.isRendered()) {
+          closestRenderedTabIndex = index;
+          if (index > activeIndex) {
+            break;
+          }
+        }
+      }
+    }
+    if (closestRenderedTabIndex == -1) {
+      // resetting index to 0
+      closestRenderedTabIndex = 0;
+    }
+    final ValueExpression expression = tabGroup.getValueExpression(Attributes.selectedIndex.getName());
+    if (expression != null) {
+      expression.setValue(context.getELContext(), closestRenderedTabIndex);
+    } else {
+      tabGroup.setSelectedIndex(closestRenderedTabIndex);
+    }
+    return closestRenderedTabIndex;
+  }
+
+  private void encodeHeader(
+      final FacesContext facesContext, final TobagoResponseWriter writer, final UITabGroup tabGroup,
+      final int activeIndex, final SwitchType switchType)
+      throws IOException {
+
+    writer.startElement(HtmlElements.UL);
+    writer.writeClassAttribute(Classes.create(tabGroup, "header"), BootstrapClass.NAV, BootstrapClass.NAV_TABS);
+    writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TABLIST.toString(), false);
+    final CommandMap tabGroupMap = RenderUtils.getBehaviorCommands(facesContext, tabGroup);
+
+    int index = 0;
+    for (final UIComponent child : tabGroup.getChildren()) {
+      if (child instanceof UITab) {
+        final UITab tab = (UITab) child;
+        if (tab.isRendered()) {
+          final LabelWithAccessKey label = new LabelWithAccessKey(tab);
+          final boolean disabled = tab.isDisabled();
+          final String tabId = tab.getClientId(facesContext);
+
+          Markup markup = activeIndex == index ? Markup.SELECTED : Markup.NULL;
+          final FacesMessage.Severity maxSeverity
+              = ComponentUtils.getMaximumSeverityOfChildrenMessages(facesContext, tab);
+          if (maxSeverity != null) {
+            markup = markup.add(ComponentUtils.markupOfSeverity(maxSeverity));
+          }
+
+          writer.startElement(HtmlElements.LI);
+          writer.writeIdAttribute(tabId);
+          writer.writeClassAttribute(Classes.create(tab, markup), BootstrapClass.NAV_ITEM);
+          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.PRESENTATION.toString(), false);
+          writer.writeAttribute(HtmlAttributes.TABGROUPINDEX, index);
+          final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, tab);
+          if (title != null) {
+            writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+          }
+
+          final CommandMap map = RenderUtils.getBehaviorCommands(facesContext, tab);
+          CommandMap.merge(map, tabGroupMap);
+          writer.writeAttribute(DataAttributes.COMMANDS, JsonUtils.encode(map), false);
+
+          writer.startElement(HtmlElements.A);
+          if (!tab.isDisabled()) {
+            writer.writeAttribute(DataAttributes.TOGGLE, "tab", false);
+          }
+          if (activeIndex == index) {
+            writer.writeClassAttribute(BootstrapClass.NAV_LINK, BootstrapClass.ACTIVE);
+          } else if (tab.isDisabled()) {
+            writer.writeClassAttribute(BootstrapClass.NAV_LINK, BootstrapClass.DISABLED);
+          } else {
+            writer.writeClassAttribute(BootstrapClass.NAV_LINK);
+          }
+          if (!disabled && switchType == SwitchType.client) {
+            writer.writeAttribute(HtmlAttributes.HREF, '#' + getTabPanelId(facesContext, tab), false);
+            writer.writeAttribute(
+                DataAttributes.TARGET, '#' + getTabPanelId(facesContext, tab).replaceAll(":", "\\\\:"), false);
+          }
+
+          if (!disabled && label.getAccessKey() != null) {
+            writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
+            AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), tabId);
+          }
+          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TAB.toString(), false);
+
+          String image = tab.getImage();
+          // tab.getImage() resolves to empty string if el-expression resolves to null
+          if (image != null && !image.isEmpty()) {
+            writer.startElement(HtmlElements.IMG);
+            writer.writeAttribute(HtmlAttributes.SRC, image, true);
+// TBD      writer.writeClassAttribute(Classes.create(tab, (label.getLabel() != null? "image-right-margin" : "image")));
+            writer.endElement(HtmlElements.IMG);
+          }
+          if (label.getLabel() != null) {
+            HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
+          } else if (image == null) {
+            writer.writeText(Integer.toString(index + 1));
+          }
+          writer.endElement(HtmlElements.A);
+
+          final UIComponent bar = ComponentUtils.getFacet(tab, Facets.bar);
+          if (bar != null) {
+            RenderUtils.encode(facesContext, bar);
+          }
+
+          writer.endElement(HtmlElements.LI);
+        }
+      }
+      index++;
+    }
+    writer.endElement(HtmlElements.UL);
+    if (tabGroup.isShowNavigationBar()) {
+      LOG.warn("Currently not supported: showNavigationBar");
+//      final UIToolBar toolBar = createToolBar(facesContext, tabGroup);
+//      renderToolBar(facesContext, writer, tabGroup, toolBar);
+    }
+  }
+
+  protected void encodeContent(
+      FacesContext facesContext, TobagoResponseWriter writer, UITabGroup tabGroup,
+      int activeIndex, SwitchType switchType) throws IOException {
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(BootstrapClass.TAB_CONTENT);
+    int index = 0;
+    for (final UIComponent tab : tabGroup.getChildren()) {
+      if (tab instanceof UITab) {
+        if (tab.isRendered() && (switchType == SwitchType.client || index == activeIndex)) {
+
+          if (((UITab) tab).isDisabled()) {
+            continue;
+          }
+
+          writer.startElement(HtmlElements.DIV);
+          writer.writeClassAttribute(Classes.create(tab, "content"),
+              BootstrapClass.TAB_PANE, index == activeIndex ? BootstrapClass.ACTIVE : null);
+          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TABPANEL.toString(), false);
+          writer.writeIdAttribute(getTabPanelId(facesContext, (UITab) tab));
+
+          writer.writeAttribute(HtmlAttributes.TABGROUPINDEX, index);
+
+          RenderUtils.encode(facesContext, tab);
+
+          writer.endElement(HtmlElements.DIV);
+        }
+        index++;
+      }
+    }
+    writer.endElement(HtmlElements.DIV);
+  }
+
+  private String getTabPanelId(FacesContext facesContext, UITab tab) {
+    return tab.getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "content";
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabRenderer.java
new file mode 100644
index 0000000..1482159
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TabRenderer.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+
+public class TabRenderer extends RendererBase {
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TextareaRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TextareaRenderer.java
new file mode 100644
index 0000000..063330f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TextareaRenderer.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITextarea;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.sanitizer.SanitizeMode;
+import org.apache.myfaces.tobago.sanitizer.Sanitizer;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.LengthValidator;
+import javax.faces.validator.Validator;
+import java.io.IOException;
+
+public class TextareaRenderer extends LabelLayoutRendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TextareaRenderer.class);
+
+  @Override
+  public void encodeBeginField(final FacesContext facesContext, final UIComponent component) throws IOException {
+    if (!(component instanceof UITextarea)) {
+      LOG.error("Wrong type: Need " + UITextarea.class.getName() + ", but was " + component.getClass().getName());
+      return;
+    }
+
+    final UITextarea input = (UITextarea) component;
+    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, component);
+    final String clientId = input.getClientId(facesContext);
+    final String fieldId = input.getFieldId(facesContext);
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final Integer rows = input.getRows();
+
+    writer.startElement(HtmlElements.TEXTAREA);
+    writer.writeNameAttribute(clientId);
+    writer.writeIdAttribute(fieldId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, input);
+    writer.writeAttribute(HtmlAttributes.ROWS, rows);
+    writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+    writer.writeAttribute(HtmlAttributes.READONLY, input.isReadonly());
+    writer.writeAttribute(HtmlAttributes.DISABLED, input.isDisabled());
+    writer.writeAttribute(HtmlAttributes.REQUIRED, input.isRequired());
+    writer.writeAttribute(HtmlAttributes.TABINDEX, input.getTabIndex());
+
+    if (input.getAccessKey() != null) {
+      writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(input.getAccessKey()), false);
+      AccessKeyLogger.addAccessKey(facesContext, input.getAccessKey(), clientId);
+    }
+
+    writer.writeClassAttribute(Classes.create(input), BootstrapClass.FORM_CONTROL, input.getCustomClass());
+    writer.writeStyleAttribute(input.getStyle());
+    int maxLength = -1;
+    final String pattern = null;
+    for (final Validator validator : input.getValidators()) {
+      if (validator instanceof LengthValidator) {
+        final LengthValidator lengthValidator = (LengthValidator) validator;
+        maxLength = lengthValidator.getMaximum();
+      }
+      /*if (validator instanceof RegexValidator) {
+        RegexValidator regexValidator = (RegexValidator) validator;
+        pattern = regexValidator.getPattern();
+      }*/
+    }
+    if (maxLength > 0) {
+      writer.writeAttribute(HtmlAttributes.MAXLENGTH, maxLength);
+    }
+    if (pattern != null) {
+      writer.writeAttribute(HtmlAttributes.PATTERN, pattern, false);
+    }
+
+    writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, input)));
+
+    HtmlRendererUtils.renderFocus(clientId, input.isFocus(), ComponentUtils.isError(input), facesContext, writer);
+
+    /*String placeholder = input.getPlaceholder();
+    if (placeholder != null) {
+      writer.writeAttribute(HtmlAttributes.PLACEHOLDER, placeholder, true);
+    }*/
+    String currentValue = RenderUtils.currentValue(input);
+    if (currentValue != null) {
+      if (ComponentUtils.getDataAttribute(input, "html-editor") != null
+          && SanitizeMode.auto == input.getSanitize()) {
+        final Sanitizer sanitizer = TobagoConfig.getInstance(facesContext).getSanitizer();
+        currentValue = sanitizer.sanitize(currentValue);
+      }
+      // this is because browsers eat the first CR+LF of <textarea>
+      if (currentValue.startsWith("\r\n")) {
+        currentValue = "\r\n" + currentValue;
+      } else if (currentValue.startsWith("\n")) {
+        currentValue = "\n" + currentValue;
+      } else if (currentValue.startsWith("\r")) {
+        currentValue = "\r" + currentValue;
+      }
+      writer.writeText(currentValue);
+    }
+  }
+
+  @Override
+  protected void encodeEndField(FacesContext facesContext, UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.TEXTAREA);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
new file mode 100644
index 0000000..c990901
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TobagoClientBehaviorRenderer.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.internal.behavior.EventBehavior;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.component.AbstractUIEvent;
+import org.apache.myfaces.tobago.internal.component.AbstractUIOperation;
+import org.apache.myfaces.tobago.internal.renderkit.Collapse;
+import org.apache.myfaces.tobago.internal.renderkit.Command;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.ActionSource;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.behavior.AjaxBehavior;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.faces.event.PhaseId;
+import java.util.Collection;
+import java.util.List;
+
+public class TobagoClientBehaviorRenderer extends javax.faces.render.ClientBehaviorRenderer {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoClientBehaviorRenderer.class);
+
+  @Override
+  public String getScript(ClientBehaviorContext behaviorContext, ClientBehavior behavior) {
+
+    final FacesContext facesContext = behaviorContext.getFacesContext();
+    final UIComponent uiComponent = behaviorContext.getComponent();
+    final ClientBehaviors eventName = ClientBehaviors.valueOf(behaviorContext.getEventName());
+
+    //// TBD: is this nice? May be implemented with a JSF behaviour?
+    final Collapse collapse = createCollapsible(facesContext, uiComponent);
+
+    String executeIds = null;
+    String renderIds = null;
+    Boolean transition = null;
+    String target = null;
+    String actionId = null;
+    boolean omit = false;
+    if (behavior instanceof AjaxBehavior) {
+      AjaxBehavior ajaxBehavior = (AjaxBehavior) behavior;
+      final Collection<String> execute = ajaxBehavior.getExecute();
+      final Collection<String> render = ajaxBehavior.getRender();
+      final String clientId = uiComponent.getClientId(facesContext);
+
+      executeIds
+          = ComponentUtils.evaluateClientIds(facesContext, uiComponent, execute.toArray(new String[execute.size()]));
+      if (executeIds != null) {
+        executeIds = executeIds + " " + clientId;
+      } else {
+        executeIds = clientId;
+      }
+      if (uiComponent instanceof AbstractUICommand) { // <f:ajax> inside of a command
+        AbstractUICommand command = (AbstractUICommand) uiComponent;
+        transition = command.isTransition();
+        target = command.getTarget();
+        omit = command.isOmit() || StringUtils.isNotBlank(RenderUtils.generateUrl(facesContext, command));
+      }
+      renderIds =
+          ComponentUtils.evaluateClientIds(facesContext, uiComponent, render.toArray(new String[render.size()]));
+      actionId = clientId;
+    } else if (behavior instanceof EventBehavior) { // <tc:event>
+      AbstractUIEvent event = findEvent(uiComponent, eventName);
+      transition = event.isTransition();
+      target = event.getTarget();
+      actionId = event.getClientId(facesContext);
+      omit = event.isOmit() || StringUtils.isNotBlank(RenderUtils.generateUrl(facesContext, event));
+    } else {
+      LOG.warn("Unknown behavior '{}'!", behavior.getClass().getName());
+    }
+
+    final Command command = new Command(
+        actionId,
+        transition,
+        target,
+        executeIds,
+        renderIds,
+        null,
+        null, // getConfirmation(command), // todo
+        null,
+        collapse,
+        omit);
+
+    final CommandMap map = new CommandMap();
+    map.addCommand(eventName, command);
+    CommandMap.storeCommandMap(facesContext, map);
+
+    // XXX the return value is a string, but we should use a CommandMap
+    return "dummy";
+  }
+
+  private AbstractUIEvent findEvent(final UIComponent component, final ClientBehaviors eventName) {
+    for (UIComponent child : component.getChildren()) {
+      if (child instanceof AbstractUIEvent) {
+        AbstractUIEvent event = (AbstractUIEvent) child;
+        if (eventName == event.getEvent()) {
+          return event;
+        }
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public void decode(FacesContext context, UIComponent component, ClientBehavior behavior) {
+    AjaxBehavior ajaxBehavior = (AjaxBehavior) behavior;
+    if (ajaxBehavior.isDisabled() || !component.isRendered()) {
+      return;
+    }
+
+    dispatchBehaviorEvent(component, ajaxBehavior);
+  }
+
+  private void dispatchBehaviorEvent(UIComponent component, AjaxBehavior ajaxBehavior) {
+
+    AjaxBehaviorEvent event = new AjaxBehaviorEvent(component, ajaxBehavior);
+    boolean isImmediate = isImmediate(ajaxBehavior, component);
+    event.setPhaseId(isImmediate ? PhaseId.APPLY_REQUEST_VALUES : PhaseId.INVOKE_APPLICATION);
+    component.queueEvent(event);
+  }
+
+  private boolean isImmediate(AjaxBehavior ajaxBehavior, UIComponent component) {
+    if (ajaxBehavior.isImmediateSet()) {
+      return ajaxBehavior.isImmediate();
+    }
+    if (component instanceof EditableValueHolder) {
+      return ((EditableValueHolder) component).isImmediate();
+    }
+    if (component instanceof ActionSource) {
+      return ((ActionSource) component).isImmediate();
+    }
+    return false;
+  }
+
+  /**
+   * @deprecated TBD
+   */
+  public static Collapse createCollapsible(FacesContext facesContext, UIComponent component) {
+    //// TBD: is this nice? May be implemented with a JSF behaviour?
+    //// BEGIN
+
+    // XXX too complicated
+    final List<AbstractUIOperation> operations =
+        ComponentUtils.findDescendantList(component, AbstractUIOperation.class);
+    Collapse collapse = null;
+    if (operations.size() > 0) {
+      final AbstractUIOperation operation = operations.get(0);
+      final String forId = ComponentUtils.evaluateClientId(facesContext, component, operation.getFor());
+      collapse = new Collapse(Collapse.Action.valueOf(operation.getName()), forId);
+    }
+
+    //// TBD: is this nice?
+    //// END
+    return collapse;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeCommandRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeCommandRenderer.java
new file mode 100644
index 0000000..641c063
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeCommandRenderer.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+public class TreeCommandRenderer extends LinkRenderer {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIconRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIconRenderer.java
new file mode 100644
index 0000000..d9ec3f9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIconRenderer.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITreeIcon;
+import org.apache.myfaces.tobago.component.UITreeNode;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.FontAwesomeIconEncoder;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class TreeIconRenderer extends RendererBase {
+
+  protected static final String OPEN_FOLDER = "image/treeNode-icon-open";
+  protected static final String CLOSED_FOLDER = "image/treeNode-icon";
+  protected static final String LEAF = "image/treeNode-icon-leaf";
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UITreeIcon image = (UITreeIcon) component;
+    final AbstractUIData data = ComponentUtils.findAncestor(image, AbstractUIData.class);
+    final UITreeNode node = ComponentUtils.findAncestor(image, UITreeNode.class);
+    final boolean folder = node.isFolder();
+    final boolean expanded = folder && data.getExpandedState().isExpanded(node.getPath());
+
+    String value = (String) image.getValue();
+    String closed = image.getClosed();
+    String open = image.getOpen();
+
+    final String source;
+    if (folder) {
+      if (expanded) {
+        source = open;
+      } else {
+        source = closed;
+      }
+    } else {
+      source = value;
+    }
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    if (StringUtils.startsWith(source, "fa-")) {
+      writer.writeIcon(null, image.getStyle(), FontAwesomeIconEncoder.generateClass(source));
+    } else {
+      writer.startElement(HtmlElements.IMG);
+      writer.writeClassAttribute(Classes.create(node, "toggle", Markup.NULL));
+      HtmlRendererUtils.writeDataAttributes(facesContext, writer, image);
+      writer.writeAttribute(HtmlAttributes.SRC, source, true);
+      if (folder) {
+        writer.writeAttribute(DataAttributes.SRC_OPEN, open, true);
+        writer.writeAttribute(DataAttributes.SRC_CLOSED, closed, true);
+      }
+      writer.writeAttribute(HtmlAttributes.ALT, "", false);
+      writer.endElement(HtmlElements.IMG);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIndentRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIndentRenderer.java
new file mode 100644
index 0000000..4075c84
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeIndentRenderer.java
@@ -0,0 +1,172 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITree;
+import org.apache.myfaces.tobago.component.UITreeIndent;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeNodeBase;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.Icons;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.List;
+
+public class TreeIndentRenderer extends RendererBase {
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UITreeIndent indent = (UITreeIndent) component;
+    final AbstractUITreeNodeBase node = ComponentUtils.findAncestor(indent, AbstractUITreeNodeBase.class);
+    final AbstractUIData data = ComponentUtils.findAncestor(indent, AbstractUIData.class);
+
+    final boolean folder = node.isFolder();
+    final int level = node.getLevel();
+    final List<Boolean> junctions = node.getJunctions();
+
+    final boolean showRoot = data.isShowRoot();
+    final boolean showJunctions = indent.isShowJunctions();
+    final boolean showRootJunction = data.isShowRootJunction();
+    final boolean expanded = folder && data.getExpandedState().isExpanded(node.getPath());
+    final boolean showLines = showJunctions && data instanceof UITree; // sheet should not show lines
+    final boolean showIcons = showJunctions;
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeIdAttribute(indent.getClientId(facesContext));
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, indent);
+    writer.writeClassAttribute(Classes.create(node, "toggle", Markup.NULL));
+
+    encodeIndent(
+        facesContext, writer, node, showLines, showIcons, showRootJunction, showRoot, junctions);
+
+    encodeTreeJunction(
+        facesContext, writer, node, showLines, showIcons, showRootJunction, junctions, expanded, folder, level == 0);
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.endElement(HtmlElements.SPAN);
+  }
+
+  private void encodeIndent(
+      final FacesContext facesContext, final TobagoResponseWriter writer, final AbstractUITreeNodeBase node,
+      final boolean showLines, final boolean showIcons, final boolean showRootJunction, final boolean showRoot,
+      final List<Boolean> junctions)
+      throws IOException {
+
+    final boolean dropFirst = !showRoot || !showRootJunction && (showLines || showIcons);
+//    final String blank = ResourceManagerUtils.getImage(facesContext, "image/blank");
+//    final String perpendicular = ResourceManagerUtils.getImage(facesContext, "image/I");
+
+    for (int i = dropFirst ? 1 : 0; i < junctions.size() - 1; i++) {
+      final Boolean junction = junctions.get(i);
+/*
+      writer.startElement(HtmlElements.IMG, null);
+      writer.writeClassAttribute(Classes.create(node, "junction"));
+      writer.writeAttribute(HtmlAttributes.alt, "", false);
+      if (junction && showLines) {
+        writer.writeAttribute("src", perpendicular, true);
+      } else {
+        writer.writeAttribute("src", blank, true);
+      }
+      writer.endElement(HtmlElements.IMG);
+*/
+      writer.writeIcon(Icons.SQUARE_O, BootstrapClass.INVISIBLE); // FIXME TOBAGO-1495
+    }
+  }
+
+  private void encodeTreeJunction(
+      final FacesContext facesContext, final TobagoResponseWriter writer, final AbstractUITreeNodeBase node,
+      final boolean showLines, final boolean showIcons, final boolean showRootJunction, final List<Boolean> junctions,
+      final boolean expanded, final boolean folder, final boolean root)
+      throws IOException {
+    if (!showIcons || !showRootJunction && root) {
+      return;
+    }
+    final boolean hasNextSibling = junctions.get(junctions.size() - 1); // last element
+
+    writer.writeIcon(folder ? expanded ? Icons.MINUS_SQUARE_O : Icons.PLUS_SQUARE_O : Icons.SQUARE_O);
+
+/*
+    writer.startElement(HtmlElements.IMG, null);
+    writer.writeClassAttribute(Classes.create(node, "toggle", Markup.NULL));
+
+    final String open;
+    final String close;
+    if (showLines) {
+      if (root) {
+        open = "Rminus";
+        close = "Rplus";
+      } else {
+        if (hasNextSibling) {
+          if (folder) {
+            open = "Tminus";
+            close = "Tplus";
+          } else {
+            open = "T";
+            close = "T";
+          }
+        } else {
+          if (folder) {
+            open = "Lminus";
+            close = "Lplus";
+          } else {
+            open = "L";
+            close = "L";
+          }
+        }
+      }
+    } else {
+      if (folder) {
+        open = "minus";
+        close = "plus";
+      } else {
+        open = "blank";
+        close = "blank";
+      }
+    }
+
+    final String srcOpen = ResourceManagerUtils.getImage(facesContext, "image/" + open);
+    final String srcClose = ResourceManagerUtils.getImage(facesContext, "image/" + close);
+    final String src = expanded ? srcOpen : srcClose;
+    writer.writeAttribute(HtmlAttributes.src, src, true);
+    if (folder) {
+      writer.writeAttribute(DataAttributes.SRC_OPEN, srcOpen, true);
+      writer.writeAttribute(DataAttributes.SRC_CLOSED, srcClose, true);
+    }
+    writer.writeAttribute(HtmlAttributes.alt, "", false);
+    writer.endElement(HtmlElements.IMG);
+*/
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeLabelRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeLabelRenderer.java
new file mode 100644
index 0000000..56c2fef
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeLabelRenderer.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITreeLabel;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeListbox;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class TreeLabelRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TreeLabelRenderer.class);
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUIData data = ComponentUtils.findAncestor(component, AbstractUIData.class);
+    final boolean listbox = data instanceof AbstractUITreeListbox;
+
+    final UITreeLabel label = (UITreeLabel) component;
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    final String text = StringUtils.defaultString((String) label.getValue());
+
+    if (listbox) {
+      writer.writeText(text);
+    } else {
+      writer.startElement(HtmlElements.LABEL);
+      writer.writeClassAttribute(Classes.create(label));
+      HtmlRendererUtils.writeDataAttributes(facesContext, writer, label);
+      writer.writeStyleAttribute(label.getStyle());
+      final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, label);
+      if (title != null) {
+        writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+      }
+
+      writer.writeText(text);
+
+      writer.endElement(HtmlElements.LABEL);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeListboxRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeListboxRenderer.java
new file mode 100644
index 0000000..2a123dc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeListboxRenderer.java
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITreeLabel;
+import org.apache.myfaces.tobago.component.UITreeListbox;
+import org.apache.myfaces.tobago.component.UITreeNode;
+import org.apache.myfaces.tobago.component.UITreeSelect;
+import org.apache.myfaces.tobago.internal.component.AbstractUITree;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeListbox;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TreeListboxRenderer extends RendererBase {
+
+  @Override
+  public void encodeChildren(final FacesContext context, final UIComponent component) throws IOException {
+    // will be rendered in encodeEnd()
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UITreeListbox tree = (UITreeListbox) component;
+    final String clientId = tree.getClientId(facesContext);
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    //    final Style scrollDivStyle = new Style();
+
+    writer.startElement(HtmlElements.DIV);
+//    scrollDivStyle.setWidth(Measure.valueOf(6 * 160)); // todo: depth * width of a select
+//    scrollDivStyle.setHeight(style.getHeight() // todo: what, when there is no scrollbar?
+//        .subtract(15)); // todo: scrollbar height
+//    scrollDivStyle.setPosition(Position.ABSOLUTE);
+//    writer.writeStyleAttribute(scrollDivStyle);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(Classes.create(tree));
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, tree);
+    writer.writeStyleAttribute(tree.getStyle());
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeNameAttribute(clientId);
+    writer.writeIdAttribute(clientId);
+    writer.writeAttribute(HtmlAttributes.VALUE, ";", false);
+    writer.endElement(HtmlElements.INPUT);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeNameAttribute(clientId + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_MARKED);
+    writer.writeIdAttribute(clientId + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_MARKED);
+    writer.writeAttribute(HtmlAttributes.VALUE, "", false);
+    writer.endElement(HtmlElements.INPUT);
+
+    if (tree.getSelectable().isSupportedByTreeListbox()) {
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+      writer.writeNameAttribute(clientId + AbstractUITree.SELECT_STATE);
+      writer.writeIdAttribute(clientId + AbstractUITree.SELECT_STATE);
+      writer.writeAttribute(HtmlAttributes.VALUE, ";", false);
+      writer.writeAttribute(DataAttributes.SELECTION_MODE, tree.getSelectable().name(), false);
+      writer.endElement(HtmlElements.INPUT);
+    }
+
+    List<Integer> thisLevel = new ArrayList<Integer>();
+    thisLevel.add(0);
+    List<Integer> nextLevel = new ArrayList<Integer>();
+    Integer size = tree.getSize();
+    size = Math.max(size != null ? size : 10, 2); // must be > 1, default is 10, if not set
+    final int depth = tree.getTreeDataModel().getDepth() != -1
+        ? tree.getTreeDataModel().getDepth()
+        : 7;  // XXX not a fix value!!!
+    // todo: use (TreeListbox ?)Layout
+//    final Measure currentWidth = tree.getCurrentWidth();
+//    final Measure width = currentWidth.divide(depth);
+    for (int level = 0; level < depth; level++) {
+
+      writer.startElement(HtmlElements.DIV);
+      writer.writeClassAttribute(Classes.create(tree, "level"));
+//      final Style levelStyle = new Style();
+//      levelStyle.setLeft(width.multiply(level));
+//      levelStyle.setWidth(width);
+//      writer.writeStyleAttribute(levelStyle);
+      // at the start of each div there is an empty and disabled select tag to show empty area.
+      // this is not needed for the 1st level.
+      if (level > 0) {
+        writer.startElement(HtmlElements.SELECT);
+        writer.writeAttribute(HtmlAttributes.DISABLED, true);
+        writer.writeAttribute(HtmlAttributes.SIZE, size);
+        writer.writeClassAttribute(Classes.create(tree, "select"));
+        writer.endElement(HtmlElements.SELECT);
+      }
+
+      for(final Integer rowIndex : thisLevel) {
+        encodeSelectBox(facesContext, tree, writer, rowIndex, nextLevel, size);
+      }
+
+      thisLevel.clear();
+      final List<Integer> swap = thisLevel;
+      thisLevel = nextLevel;
+      nextLevel = swap;
+
+      writer.endElement(HtmlElements.DIV);
+    }
+
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+
+    tree.setRowIndex(-1);
+  }
+
+  private void encodeSelectBox(
+      final FacesContext facesContext, final AbstractUITreeListbox tree, final TobagoResponseWriter writer,
+      final int parentRowIndex, final List<Integer> foldersRowIndices, final int size)
+      throws IOException {
+
+    tree.setRowIndex(parentRowIndex);
+
+    final UITreeNode node = ComponentUtils.findDescendant(tree, UITreeNode.class);
+    final String parentId = node.getClientId(facesContext);
+
+    writer.startElement(HtmlElements.SELECT);
+    writer.writeClassAttribute(Classes.create(tree, "select"));
+    if (parentId != null) {
+      writer.writeAttribute(DataAttributes.TREE_PARENT, parentId, false);
+    }
+
+    writer.writeAttribute(HtmlAttributes.SIZE, size);
+//    writer.writeAttribute(HtmlAttributes.MULTIPLE, siblingMode);
+
+    final UITreeSelect select = ComponentUtils.findDescendant(tree, UITreeSelect.class);
+    final String labelValue;
+    if (select != null) {
+      labelValue = select.getLabel();
+    } else {
+      final UITreeLabel label = ComponentUtils.findDescendant(tree, UITreeLabel.class);
+      if (label != null) {
+        labelValue = label.getLabel();
+      } else {
+        labelValue = null;
+      }
+    }
+    if (labelValue != null) {
+      writer.startElement(HtmlElements.OPTGROUP);
+      writer.writeAttribute(HtmlAttributes.LABEL, labelValue, true);
+      writer.endElement(HtmlElements.OPTGROUP);
+    }
+
+    final List<Integer> rowIndices = tree.getRowIndicesOfChildren();
+
+    for (final Integer rowIndex : rowIndices) {
+      tree.setRowIndex(rowIndex);
+      if (!tree.isRowAvailable()) {
+        break;
+      }
+
+      for (final UIComponent child : tree.getChildren()) {
+        RenderUtils.encode(facesContext, child);
+      }
+
+      if (tree.isFolder()) {
+        foldersRowIndices.add(rowIndex);
+      }
+    }
+
+    writer.endElement(HtmlElements.SELECT);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeMenuRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeMenuRenderer.java
new file mode 100644
index 0000000..7935831
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeMenuRenderer.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+public class TreeMenuRenderer extends TreeRenderer {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeNodeRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeNodeRenderer.java
new file mode 100644
index 0000000..4700e91
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeNodeRenderer.java
@@ -0,0 +1,222 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITreeNode;
+import org.apache.myfaces.tobago.component.UITreeSelect;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.component.AbstractUITree;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeListbox;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeMenu;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeNodeBase;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.layout.Display;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.model.Selectable;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.Map;
+
+public class TreeNodeRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TreeNodeRenderer.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+
+    final UITreeNode node = (UITreeNode) component;
+
+    super.decode(facesContext, node);
+
+    if (ComponentUtils.isOutputOnly(node)) {
+      return;
+    }
+
+    final AbstractUIData data = ComponentUtils.findAncestor(node, AbstractUIData.class);
+    if (data instanceof AbstractUITreeListbox) {
+      final String clientId = data.getClientId(facesContext);
+      final String nodeStateId = node.nodeStateId(facesContext);
+      final Map<String, String> requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
+      final String id = node.getClientId(facesContext);
+      final boolean folder = node.isFolder();
+
+      // expand state
+      if (folder) {
+        final boolean expanded = Boolean.parseBoolean(requestParameterMap.get(id + "-expanded"));
+/* XXX check
+      if (node.isExpanded() != expanded) {
+        new TreeExpansionEvent(node, node.isExpanded(), expanded).queue();
+      }
+*/
+      }
+
+      // select
+      if (data.getSelectable() != Selectable.none) { // selection
+        final String selected = requestParameterMap.get(clientId + AbstractUITree.SELECT_STATE);
+        final String searchString = ";" + node.getClientId(facesContext) + ";";
+        final UITreeSelect treeSelect = ComponentUtils.findDescendant(node, UITreeSelect.class);
+        if (treeSelect != null) {
+          treeSelect.setSubmittedValue(selected.contains(searchString));
+        }
+      }
+
+      // marked
+      final String marked =
+          requestParameterMap.get(clientId + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_MARKED);
+      if (marked != null) {
+        final String searchString = clientId + UINamingContainer.getSeparatorChar(facesContext) + nodeStateId;
+        final boolean markedValue = marked.equals(searchString);
+/* XXX check
+      if (node.isMarked() != markedValue) {
+        new TreeMarkedEvent(node, node.isMarked(), markedValue).queue();
+      }
+*/
+      } else {
+        LOG.warn("This log message is help clarifying the occurrence of this else case.");
+      }
+    }
+  }
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUITreeNodeBase node = (AbstractUITreeNodeBase) component;
+    final AbstractUIData data = ComponentUtils.findAncestor(node, AbstractUIData.class);
+
+    final boolean dataRendersRowContainer = data.isRendersRowContainer();
+    final String clientId = node.getClientId(facesContext);
+    final String parentId = data.getRowParentClientId();
+    final boolean visible = data.isRowVisible();
+    final boolean folder = node.isFolder();
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    if (data instanceof AbstractUITreeListbox) {
+      writer.startElement(HtmlElements.OPTION);
+      // todo: define where to store the selection of a tree, node.getValue() seems not to be a god place.
+      //        writer.writeAttribute(HtmlAttributes.value, node.getValue().toString(), true); // XXX converter?
+      writer.writeAttribute(HtmlAttributes.VALUE, clientId, true);
+      writer.writeIdAttribute(clientId);
+      writer.writeAttribute(HtmlAttributes.SELECTED, folder);
+    } else {
+      writer.startElement(HtmlElements.DIV);
+
+      // div id
+      writer.writeIdAttribute(clientId);
+
+      Markup markup = Markup.NULL;
+      if (data instanceof AbstractUITree && data.getSelectedState().isSelected(node.getPath())) {
+        markup = markup.add(Markup.SELECTED);
+      }
+      if (folder) {
+        markup = markup.add(Markup.FOLDER);
+        if (data.getExpandedState().isExpanded(node.getPath())) {
+          markup = markup.add(Markup.EXPANDED);
+        }
+      }
+
+      writer.writeClassAttribute(Classes.create(node, markup));
+      HtmlRendererUtils.writeDataAttributes(facesContext, writer, node);
+      if (parentId != null) {
+        writer.writeAttribute(DataAttributes.TREE_PARENT, parentId, false);
+      }
+
+      Style style = node.getStyle();
+      if (style == null) {
+        style = new Style();
+      }
+      // In the case of a sheet, we need not hiding the node, because the whole TR will be hidden.
+      if (!dataRendersRowContainer && !visible) {
+        style.setDisplay(Display.none);
+      }
+      if(style.getLeft() == null) {
+        style.setMarginLeft(leftOffset(data, node.getLevel(), data.isShowRoot()));
+      }
+
+      writer.writeStyleAttribute(style);
+    }
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final AbstractUITreeNodeBase node = (AbstractUITreeNodeBase) component;
+    final AbstractUIData data = ComponentUtils.findAncestor(node, AbstractUIData.class);
+    final int level = node.getLevel();
+    final boolean folder = node.isFolder();
+    final boolean expanded = folder && data.getExpandedState().isExpanded(node.getPath()) || level == 0;
+    final boolean isMenu = data instanceof AbstractUITreeMenu;
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    if (data instanceof AbstractUITreeListbox) {
+      if (folder) {
+        writer.writeText(" \u2192"); // this is an right arrow →
+      }
+      writer.endElement(HtmlElements.OPTION);
+    } else {
+      if (isMenu && folder) {
+        encodeIcon(facesContext, writer, expanded, node);
+      }
+      writer.endElement(HtmlElements.DIV);
+    }
+  }
+
+  private void encodeIcon(
+      final FacesContext facesContext, final TobagoResponseWriter writer, final boolean expanded,
+      final AbstractUITreeNodeBase node)
+      throws IOException {
+//    LOG.warn("todo: font-awesome icons");
+/* XXX
+    final String srcOpen = ResourceManagerUtils.getImage(facesContext, "image/treeMenuOpen");
+    final String srcClose = ResourceManagerUtils.getImage(facesContext, "image/treeMenuClose");
+    final String src = expanded ? srcOpen : srcClose;
+    writer.startElement(HtmlElements.IMG);
+    writer.writeClassAttribute(Classes.create(node, "toggle"));
+    writer.writeAttribute(HtmlAttributes.SRC, src, false);
+    writer.writeAttribute(DataAttributes.SRC_OPEN, srcOpen, false);
+    writer.writeAttribute(DataAttributes.SRC_CLOSED, srcClose, false);
+    writer.writeAttribute(HtmlAttributes.ALT, "", false);
+    writer.endElement(HtmlElements.IMG);
+*/
+  }
+
+  protected Measure leftOffset(AbstractUIData data, int level, boolean showRoot) {
+    if (data instanceof AbstractUITreeMenu) {
+      final int factor = showRoot ? level : level - 1;
+      return Measure.valueOf(factor * 25); // XXX should be defined in CSS
+    } else {
+      return Measure.ZERO;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeRenderer.java
new file mode 100644
index 0000000..4bb5465
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeRenderer.java
@@ -0,0 +1,159 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITreeNode;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.component.AbstractUITree;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.Selectable;
+import org.apache.myfaces.tobago.model.SelectedState;
+import org.apache.myfaces.tobago.model.TreePath;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class TreeRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TreeRenderer.class);
+
+  protected static final String SCROLL_POSITION = ComponentUtils.SUB_SEPARATOR + "scrollPosition";
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    final AbstractUITree tree = (AbstractUITree) component;
+    final String value = facesContext.getExternalContext().getRequestParameterMap().get(
+        tree.getClientId(facesContext) + SCROLL_POSITION);
+    if (value != null) {
+      tree.getState().getScrollPosition().update(value);
+    }
+    RenderUtils.decodedStateOfTreeData(facesContext, tree);
+  }
+
+  @Override
+  public boolean getRendersChildren() {
+    return true;
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext context, final UIComponent component) throws IOException {
+    // will be rendered in encodeEnd()
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUITree tree = (AbstractUITree) component;
+
+    final String clientId = tree.getClientId(facesContext);
+    final UIComponent root = ComponentUtils.findDescendant(tree, UITreeNode.class);
+    if (root == null) {
+      LOG.error("Can't find the tree root. This may occur while updating a tree from Tobago 1.0 to 1.5. "
+          + "Please refer the documentation to see how to use tree tags.");
+      return;
+    }
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(Classes.create(tree), tree.getCustomClass());
+    writer.writeStyleAttribute(tree.getStyle());
+    writer.writeIdAttribute(clientId);
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, tree);
+    writer.writeAttribute(DataAttributes.SCROLL_PANEL, Boolean.TRUE.toString(), false);
+
+    final Selectable selectable = tree.getSelectable();
+    if (selectable.isSupportedByTree()) {
+      writer.writeAttribute(DataAttributes.SELECTABLE, selectable.name(), false);
+    }
+
+    final SelectedState selectedState = tree.getSelectedState();
+    final StringBuilder selectedValue = new StringBuilder(",");
+
+    final ExpandedState expandedState = tree.getExpandedState();
+    final StringBuilder expandedValue = new StringBuilder(",");
+
+    final int last = tree.isRowsUnlimited() ? Integer.MAX_VALUE : tree.getFirst() + tree.getRows();
+    for (int rowIndex = tree.getFirst(); rowIndex < last; rowIndex++) {
+      tree.setRowIndex(rowIndex);
+      if (!tree.isRowAvailable()) {
+        break;
+      }
+
+      final TreePath path = tree.getPath();
+
+      if (selectedState.isSelected(path)) {
+        selectedValue.append(rowIndex);
+        selectedValue.append(",");
+      }
+
+      if (tree.isFolder() && expandedState.isExpanded(path)) {
+        expandedValue.append(rowIndex);
+        expandedValue.append(",");
+      }
+
+      for (final UIComponent child : tree.getChildren()) {
+        RenderUtils.encode(facesContext, child);
+      }
+    }
+    tree.setRowIndex(-1);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    final String selectedId = clientId + ComponentUtils.SUB_SEPARATOR + AbstractUITree.SUFFIX_SELECTED;
+    writer.writeNameAttribute(selectedId);
+    writer.writeIdAttribute(selectedId);
+    writer.writeClassAttribute(Classes.create(tree, AbstractUITree.SUFFIX_SELECTED));
+    writer.writeAttribute(HtmlAttributes.VALUE, selectedValue.toString(), false);
+    writer.endElement(HtmlElements.INPUT);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    final String expandedId = clientId + ComponentUtils.SUB_SEPARATOR + AbstractUIData.SUFFIX_EXPANDED;
+    writer.writeNameAttribute(expandedId);
+    writer.writeIdAttribute(expandedId);
+    writer.writeClassAttribute(Classes.create(tree, AbstractUIData.SUFFIX_EXPANDED));
+    writer.writeAttribute(HtmlAttributes.VALUE, expandedValue.toString(), false);
+    writer.endElement(HtmlElements.INPUT);
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeIdAttribute(clientId + SCROLL_POSITION);
+    writer.writeNameAttribute(clientId + SCROLL_POSITION);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeAttribute(HtmlAttributes.VALUE, tree.getState().getScrollPosition().encode(), false);
+    writer.writeAttribute(DataAttributes.SCROLL_POSITION, Boolean.TRUE.toString(), true);
+    writer.endElement(HtmlElements.INPUT);
+
+    writer.endElement(HtmlElements.DIV);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeSelectRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeSelectRenderer.java
new file mode 100644
index 0000000..b84a886
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/TreeSelectRenderer.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.UITreeSelect;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeListbox;
+import org.apache.myfaces.tobago.internal.component.AbstractUITreeNodeBase;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.model.Selectable;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UINamingContainer;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class TreeSelectRenderer extends RendererBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TreeSelectRenderer.class);
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+
+    final UITreeSelect select = (UITreeSelect) component;
+    final AbstractUITreeNodeBase node = ComponentUtils.findAncestor(select, AbstractUITreeNodeBase.class);
+    final AbstractUIData data = ComponentUtils.findAncestor(node, AbstractUIData.class);
+
+    if (ComponentUtils.isOutputOnly(select)) {
+      return;
+    }
+
+    final String clientId = select.getClientId(facesContext);
+    final String name;
+    if (data.getSelectable().isSingle()) {
+      name = getClientIdWithoutRowIndex(data, clientId);
+    } else {
+      name = clientId;
+    }
+
+    final String parameter = facesContext.getExternalContext().getRequestParameterMap().get(name);
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("parameter = '" + parameter + "'");
+    }
+
+    final boolean selected = clientId.equals(parameter);
+    if (!select.isValueStoredInState()) {
+      select.setSubmittedValue(selected ? "true" : "false");
+    }
+  }
+
+  @Override
+  public void encodeBegin(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final UITreeSelect select = (UITreeSelect) component;
+    final AbstractUITreeNodeBase node = ComponentUtils.findAncestor(select, AbstractUITreeNodeBase.class);
+    final AbstractUIData data = ComponentUtils.findAncestor(node, AbstractUIData.class);
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    if (data instanceof AbstractUITreeListbox) {
+      writer.write(StringUtils.defaultString(select.getLabel()));
+      return;
+    }
+
+    final String id = select.getClientId(facesContext);
+    final String currentValue = getCurrentValue(facesContext, select);
+    final boolean checked;
+    if (select.isValueStoredInState()) {
+      checked = data.getSelectedState().isSelected(node.getPath());
+    } else {
+      checked = "true".equals(currentValue);
+    }
+
+    final boolean folder = data.isFolder();
+    final Selectable selectable = data.getSelectable();
+
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(Classes.create(select));
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, select);
+
+    if (select.isShowCheckbox()
+        && selectable != Selectable.none
+        && (!selectable.isLeafOnly() || !folder)) {
+      writer.startElement(HtmlElements.INPUT);
+      writer.writeClassAttribute(BootstrapClass.FORM_CHECK_INLINE);
+      if (selectable.isSingle()) {
+        writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.RADIO);
+        writer.writeNameAttribute(getClientIdWithoutRowIndex(data, id));
+      } else {
+        writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.CHECKBOX);
+        writer.writeNameAttribute(id);
+      }
+      writer.writeAttribute(HtmlAttributes.VALUE, id, false);
+      writer.writeIdAttribute(id);
+      writer.writeAttribute(HtmlAttributes.CHECKED, checked);
+
+      writer.writeCommandMapAttribute(JsonUtils.encode(RenderUtils.getBehaviorCommands(facesContext, select)));
+
+      writer.endElement(HtmlElements.INPUT);
+    }
+
+    // label
+    final String label = select.getLabel();
+    if (StringUtils.isNotEmpty(label)) {
+      writer.startElement(HtmlElements.LABEL);
+      writer.writeClassAttribute(Classes.create(select, "label"));
+      final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, select);
+      if (title != null) {
+        writer.writeAttribute(HtmlAttributes.TITLE, title, true);
+      }
+      writer.writeAttribute(HtmlAttributes.FOR, id, false);
+      writer.writeText(label);
+      writer.endElement(HtmlElements.LABEL);
+    }
+
+    writer.endElement(HtmlElements.SPAN);
+  }
+
+  private String getClientIdWithoutRowIndex(final AbstractUIData data, final String id) {
+    final char separatorChar = UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance());
+    return id.substring(0, id.indexOf("" + separatorChar + data.getRowIndex() + separatorChar));
+  }
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/VerbatimRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/VerbatimRenderer.java
new file mode 100644
index 0000000..0273805
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/renderkit/renderer/VerbatimRenderer.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.renderkit.renderer;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+
+public class VerbatimRenderer extends RendererBase {
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+    final String value = RenderUtils.currentValue(component);
+    if (value == null) {
+      return;
+    }
+
+    if (ComponentUtils.getBooleanAttribute(component, Attributes.escape)) {
+      writer.writeText(value, null);
+    } else {
+      writer.write(value);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/AttributeTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/AttributeTagDeclaration.java
new file mode 100644
index 0000000..25f2034
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/AttributeTagDeclaration.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+
+import javax.el.ValueExpression;
+
+/**
+ * Add an attribute on the UIComponent
+ * associated with the closest parent UIComponent custom action.
+ */
+@Tag(name = "attribute")
+@SimpleTag(
+    faceletHandler = "org.apache.myfaces.tobago.facelets.AttributeHandler")
+public interface AttributeTagDeclaration {
+
+  /**
+   * The name of the attribute in the parent component.
+   */
+  @TagAttribute(required = true, name = "name", type = "java.lang.String")
+  void setName(final ValueExpression name);
+
+  /**
+   * The value of the attribute in the parent component.
+   */
+  @TagAttribute(required = true, name = "value", type = "java.lang.String")
+  void setValue(final ValueExpression value);
+  /**
+   * Warning: The mode is only available when using Facelets.
+   * Allowed values are "action", "actionListener", "actionFromValue", "isNotSet", "isSet", "valueIfSet".
+   * <br>
+   * "action" (method binding) evaluate the expression to find the method binding which is referenced with the template.
+   * <br>
+   * "actionListener" same as "action" but for the method signature of ActionListeners.
+   * <br>
+   * "isSet" (boolean) checks, if the expression is set from the composition caller.
+   * <br>
+   * "isNotSet" (boolean) negation of "isSet"
+   * <br>
+   * "actionFromValue" Evaluates the ValueBinding to get an outcome set directly (no action method)
+   * <br>
+   * "valueIfSet" set the attribute only if the value is set.
+   */
+  @TagAttribute(name = "mode")
+  void setMode(final ValueExpression mode);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/BarTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/BarTagDeclaration.java
new file mode 100644
index 0000000..ea41790
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/BarTagDeclaration.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Defines a container for navigation elements, branding, ...
+ */
+@Tag(name = "bar")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIBar",
+    uiComponentBaseClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.BAR,
+facets = {
+    @Facet(
+        name = Facets.BRAND,
+        description = "Contains an element which will get a 'navbar-brand' style, e.g. use <tc:link> ")})
+public interface BarTagDeclaration
+    extends HasIdBindingAndRendered, HasTip, IsVisual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/BoxTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/BoxTagDeclaration.java
new file mode 100644
index 0000000..1650e37
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/BoxTagDeclaration.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasCollapsedMode;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsCollapsed;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Renders a panel with border and title.
+ */
+@Tag(name = "box")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIBox",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIBox",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.BOX,
+    facets = {
+        @Facet(name = Facets.BAR,
+            description = "Contains some code to be placed in the header at the bar position."),
+        @Facet(name = Facets.LABEL,
+            description = "Contains some code to be placed in the header at the label position."),
+        @Facet(name=Facets.LAYOUT, description = "Deprecated! Contains an layout manager. "
+            + "The layout manager tag should surround the content instead.")})
+
+public interface BoxTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, HasLabel, HasTip, IsCollapsed, HasCollapsedMode {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonTagDeclaration.java
new file mode 100644
index 0000000..4fbc1d5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonTagDeclaration.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAction;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasActionListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConfirmation;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasImage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLink;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTarget;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDefaultCommand;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabledBySecurity;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsImmediateCommand;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsOmit;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsTransition;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UICommand;
+
+/**
+ * Renders a button element.
+ */
+@Tag(name = "button")
+@BodyContentDescription(anyTagOf = "facestag")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIButton",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIButton",
+    uiComponentFacesClass = "javax.faces.component.UICommand",
+    interfaces = {
+        "org.apache.myfaces.tobago.component.SupportsAccessKey"
+    },
+    componentFamily = UICommand.COMPONENT_FAMILY,
+    rendererType = RendererTypes.BUTTON,
+    allowedChildComponenents = "NONE",
+    facets = {
+        @Facet(
+            name = Facets.CONFIRMATION,
+            description = "Contains a UIOutput instance with the confirmation message.",
+            allowedChildComponenents = "org.apache.myfaces.tobago.Out")
+    },
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            description = "Behavior of a click event.",
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface ButtonTagDeclaration
+    extends HasIdBindingAndRendered, HasAction, HasActionListener, IsImmediateCommand, HasConfirmation,
+    HasLink, IsTransition, HasTarget, IsDisabledBySecurity,
+    IsOmit, IsVisual, HasLabel, HasAccessKey, HasTip, HasImage,
+    IsDefaultCommand, HasTabIndex {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonsTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonsTagDeclaration.java
new file mode 100644
index 0000000..5d5f747
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ButtonsTagDeclaration.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Renders a group of buttons.
+ */
+@Tag(name = "buttons")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIButtons",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIButtons",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.BUTTONS)
+
+public interface ButtonsTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, HasTip {
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/CalendarTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/CalendarTagDeclaration.java
new file mode 100644
index 0000000..2646976
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/CalendarTagDeclaration.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * Renders a calendar.
+ */
+@Tag(name = "calendar")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UICalendar",
+    uiComponentBaseClass = "javax.faces.component.UIOutput",
+    uiComponentFacesClass = "javax.faces.component.UIOutput",
+    componentFamily = UIOutput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.CALENDAR)
+public interface CalendarTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual {
+
+  /**
+   * The current value of this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {"java.util.Calendar", "java.util.Date"},
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
+  void setValue(String value);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnNodeTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnNodeTagDeclaration.java
new file mode 100644
index 0000000..7208d19
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnNodeTagDeclaration.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIColumn;
+
+/**
+ * Creates a tree node inside of a sheet (also known as tree table).
+ * This component represents a single node inside a tree structure.
+ */
+@SuppressWarnings("ALL")
+@Tag(name = "columnNode")
+@BodyContentDescription(anyTagOf = "<tc:treeIndent>|<tc:treeIcon>|<tc:treeSelect>|<tc:treeLabel>|<tc:treeCommand>")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIColumnNode",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIColumnNode",
+    uiComponentFacesClass = "javax.faces.component.UIColumn",
+    componentFamily = UIColumn.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_NODE,
+    allowedChildComponenents = {
+        "org.apache.myfaces.tobago.TreeIndent",
+        "org.apache.myfaces.tobago.TreeIcon",
+        "org.apache.myfaces.tobago.TreeSelect",
+        "org.apache.myfaces.tobago.TreeLabel",
+        "org.apache.myfaces.tobago.TreeCommand"
+    })
+public interface ColumnNodeTagDeclaration
+    extends HasIdBindingAndRendered, HasTip, IsDisabled, IsVisual, HasLabel {
+
+  /**
+   * Flag indicating whether or not the width of this column in a sheet is resizable, by the user.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"boolean"}, defaultValue = "true")
+  void setResizable(String resizable);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnSelectorTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnSelectorTagDeclaration.java
new file mode 100644
index 0000000..c8a10fa
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnSelectorTagDeclaration.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIColumn;
+
+/**
+ * Renders a column with checkboxes to mark selected rows.
+ */
+@Tag(name = "columnSelector")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIColumnSelector",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIColumnSelector",
+    uiComponentFacesClass = "javax.faces.component.UIColumn",
+    componentFamily = UIColumn.COMPONENT_FAMILY,
+    rendererType = RendererTypes.COLUMN_SELECTOR,
+    allowedChildComponenents = "NONE")
+public interface ColumnSelectorTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, IsDisabled {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnTagDeclaration.java
new file mode 100644
index 0000000..f589eff
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ColumnTagDeclaration.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIColumn;
+
+/**
+ * Renders a UIComponent that represents a single column of data within a
+ * parent UISheet component.
+ */
+@Tag(name = "column")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIColumn",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIColumn",
+    uiComponentFacesClass = "javax.faces.component.UIColumn",
+    componentFamily = UIColumn.COMPONENT_FAMILY,
+    rendererType = RendererTypes.COLUMN)
+public interface ColumnTagDeclaration
+    extends HasIdBindingAndRendered, HasLabel, HasTip, IsVisual {
+  /**
+   * Alignment of this column.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setAlign(String align);
+
+  /**
+   * Flag indicating whether or not this column is sortable.
+   * To make a column sortable the data of the sheet must be one of
+   * <code>java.util.List</code> or <code>Object[]</code>.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"boolean"}, defaultValue = "false")
+  void setSortable(String sortable);
+
+  /**
+   * Flag indicating whether or not the width of this column in a sheet is resizable, by the user.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"boolean"}, defaultValue = "true")
+  void setResizable(String resizable);
+
+  /**
+   * The layout token for this column.
+   * Allowd layout tokens ('*', '&lt;x>*', '&lt;x>px' or '&lt;x>%').
+   * Where '*' is equivalent to '1*'.
+   */
+/* TBD
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setWidth(String width);
+*/
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ConverterTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ConverterTagDeclaration.java
new file mode 100644
index 0000000..e434e7b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ConverterTagDeclaration.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+
+import javax.el.ValueExpression;
+
+/**
+ * Register an Converter instance on the UIComponent
+ * associated with the closest parent UIComponent.
+ */
+@Tag(name = "converter")
+@SimpleTag(
+    faceletHandler = "org.apache.myfaces.tobago.facelets.ConverterHandler")
+public interface ConverterTagDeclaration {
+
+  /**
+   * The converterId of a registered converter.
+   */
+  @TagAttribute(name = "converterId", type = "java.lang.String")
+  void setConverterId(final ValueExpression converterId);
+
+  /**
+   * The value binding expression to a converter.
+   */
+  @TagAttribute(name = "binding", type = "javax.faces.convert.Converter")
+  void setBinding(final ValueExpression binding);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/DataAttributeTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/DataAttributeTagDeclaration.java
new file mode 100644
index 0000000..c70fb23
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/DataAttributeTagDeclaration.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Preliminary;
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+
+import javax.el.ValueExpression;
+
+/**
+ * Add an data attribute on the UIComponent
+ * associated with the closest parent UIComponent custom action.
+ * Data attributes will be passed through the renderers into the DOM of the user agent and
+ * can be used by scripts.
+ */
+@Preliminary
+@Tag(name = "dataAttribute")
+@SimpleTag(
+    faceletHandler = "org.apache.myfaces.tobago.facelets.DataAttributeHandler")
+public interface DataAttributeTagDeclaration {
+
+  /**
+   * The name of the attribute in the parent component.
+   */
+  @TagAttribute(required = true, name = "name", type = "java.lang.String")
+  void setName(final ValueExpression name);
+
+  /**
+   * The value of the attribute in the parent component.
+   */
+  @TagAttribute(required = true, name = "value", type = "java.lang.String")
+  void setValue(final ValueExpression value);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/DateTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/DateTagDeclaration.java
new file mode 100644
index 0000000..a8d3ef4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/DateTagDeclaration.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasPlaceholder;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequired;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIInput;
+
+/**
+ * Renders a date input field.
+ * <p>
+ * For a time input field set you'll need to set the &lt;f:convertDateTime type="time"&gt; inside the &lt;tc:date&gt;.
+ * <p>
+ * If there is no converter given, a default instance of {@link javax.faces.convert.DateTimeConverter} will be used.
+ */
+@Tag(name = "date")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIDate",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIDate",
+    uiComponentFacesClass = "javax.faces.component.UIInput",
+    componentFamily = UIInput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.DATE,
+    allowedChildComponenents = "NONE",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface DateTagDeclaration
+    extends HasAccessKey, HasValidator, HasValue, HasValueChangeListener, HasTabIndex, IsFocus, IsVisual,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessage, HasIdBindingAndRendered, IsReadonly,
+    IsDisabled, HasConverter, HasLabel, HasLabelLayout,
+    HasTip, IsRequired, HasPlaceholder {
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/EventTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/EventTagDeclaration.java
new file mode 100644
index 0000000..7d003cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/EventTagDeclaration.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAction;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasActionListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConfirmation;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLink;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTarget;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabledBySecurity;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsImmediateCommand;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsOmit;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsTransition;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UICommand;
+
+/**
+ * Add an event behavior to the component.
+ */
+@Tag(name = "event")
+@UIComponentTag(uiComponent = "org.apache.myfaces.tobago.component.UIEvent",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIEvent",
+    uiComponentFacesClass = "javax.faces.component.UICommand",
+    componentFamily = UICommand.COMPONENT_FAMILY,
+    rendererType = RendererTypes.EVENT,
+    faceletHandler = "org.apache.myfaces.tobago.facelets.EventHandler")
+public interface EventTagDeclaration
+    extends HasIdBindingAndRendered, HasAction, HasActionListener, IsImmediateCommand, HasConfirmation,
+    HasLink, IsTransition, HasTarget, IsDisabledBySecurity, IsOmit {
+
+  /**
+   * The name of the event.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.component.ClientBehaviors")
+  void setEvent(final ValueExpression event);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FigureTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FigureTagDeclaration.java
new file mode 100644
index 0000000..ad1960b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FigureTagDeclaration.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Use figure to show e. g. images or videos inside.
+ */
+@Tag(name = "figure")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIFigure",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIFigure",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.FIGURE,
+    interfaces = "org.apache.myfaces.tobago.component.Visual",
+    facets = {
+        @Facet(
+            name = Facets.LABEL,
+            description = "Contains some code to be placed in the header at the label position.")})
+public interface FigureTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, HasTip, HasLabel {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileTagDeclaration.java
new file mode 100644
index 0000000..7cef08c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FileTagDeclaration.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsMultiple;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequired;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIInput;
+
+/**
+ * <p>
+ * Renders a file input field.
+ * </p>
+ * <p>
+ * For content constraints please use <a href="validateFileItem.html">tc:validateFileItem</a>.
+ * </p>
+ */
+@Tag(name = "file")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIFile",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIFile",
+    uiComponentFacesClass = "javax.faces.component.UIInput",
+    componentFamily = UIInput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.FILE,
+    allowedChildComponenents = "NONE",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface FileTagDeclaration
+    extends HasValidator, HasValidatorMessage, HasRequiredMessage, HasConverterMessage,
+    HasValueChangeListener, HasIdBindingAndRendered, IsDisabled, IsFocus, IsMultiple,
+    HasLabel, HasLabelLayout, HasAccessKey, HasTip, IsReadonly, IsRequired, HasTabIndex, IsVisual {
+
+  /**
+   * Value binding expression pointing to a
+   * {@link javax.servlet.http.Part} property to store the
+   * uploaded file.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(
+      type = { "javax.servlet.http.Part", "javax.servlet.http.Part[]" },
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
+  void setValue(String value);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlexLayoutTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlexLayoutTagDeclaration.java
new file mode 100644
index 0000000..ff909c0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlexLayoutTagDeclaration.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFlexLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasColumnLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRowLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.layout.AlignItems;
+import org.apache.myfaces.tobago.layout.JustifyContent;
+
+/**
+ * Renders a flex layout (CSS3 feature).
+ *
+ * @since 3.0.0
+ */
+@Tag(name = "flexLayout")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIFlexLayout",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIFlexLayout",
+    componentFamily = AbstractUIFlexLayout.COMPONENT_FAMILY,
+    rendererType = RendererTypes.FLEX_LAYOUT,
+    allowedChildComponenents = "NONE")
+public interface FlexLayoutTagDeclaration
+    extends HasIdBindingAndRendered, HasColumnLayout, HasRowLayout, IsVisual {
+
+  /**
+   * This value defines CSS align-items value of the flex layout.
+   *
+   * @since 3.0.0
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.AlignItems",
+      allowedValues = {
+          AlignItems.FLEX_START, AlignItems.FLEX_END, AlignItems.BASELINE, AlignItems.CENTER, AlignItems.STRETCH
+      })
+  void setAlignItems(String alignItems);
+
+  /**
+   * This value defines CSS justify-content value of the flex layout.
+   *
+   * @since 3.0.0
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.JustifyContent",
+      allowedValues = {
+          JustifyContent.FLEX_START, JustifyContent.FLEX_END, JustifyContent.CENTER, JustifyContent.SPACE_BETWEEN,
+          JustifyContent.SPACE_AROUND
+      })
+  void setJustifyContent(String justifyContent);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlowLayoutTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlowLayoutTagDeclaration.java
new file mode 100644
index 0000000..90d6e52
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FlowLayoutTagDeclaration.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFlowLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.layout.TextAlign;
+
+/**
+ * Renders a FlowLayout that positions the content components in there natural order.
+ */
+@Tag(name = "flowLayout")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIFlowLayout",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIFlowLayout",
+    componentFamily = AbstractUIFlowLayout.COMPONENT_FAMILY,
+    rendererType = RendererTypes.FLOW_LAYOUT,
+    allowedChildComponenents = "NONE")
+public interface FlowLayoutTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual {
+
+  /**
+   * The alignment of the elements inside of the container, possible values are:
+   * {@link TextAlign#left},
+   * {@link TextAlign#right},
+   * {@link TextAlign#center} and
+   * {@link TextAlign#justify}.
+   *
+   * @since 3.0.0
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {"org.apache.myfaces.tobago.layout.TextAlign"},
+      allowedValues = {
+          TextAlign.LEFT, TextAlign.RIGHT, TextAlign.CENTER, TextAlign.JUSTIFY
+      })
+  void setTextAlign(String textAlign);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FooterTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FooterTagDeclaration.java
new file mode 100644
index 0000000..db4d755
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FooterTagDeclaration.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFixed;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Defines a footer of its parent (like page, box, ...)
+ * @since 3.0.0
+ */
+@Tag(name = "footer")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIFooter",
+    uiComponentBaseClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.FOOTER,
+    allowedChildComponenents = "ALL")
+public interface FooterTagDeclaration
+    extends HasIdBindingAndRendered, HasTip, IsFixed, IsVisual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FormTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FormTagDeclaration.java
new file mode 100644
index 0000000..236b372
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/FormTagDeclaration.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsInline;
+
+import javax.faces.component.UIForm;
+
+/**
+ * If an action is preformed, everything within the next parent form belongs to the submit-area.
+ * An action could be a button which is pressed.
+ * tc:page is a form.
+ * Everything in the submit-area is written into the model, even other forms.
+ */
+@Tag(name = "form")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIForm",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIForm",
+    uiComponentFacesClass = "javax.faces.component.UIForm",
+    componentFamily = UIForm.COMPONENT_FAMILY,
+    rendererType = RendererTypes.FORM,
+    allowedChildComponenents = "ALL")
+public interface FormTagDeclaration extends HasBinding, HasId, IsInline {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/GridLayoutTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/GridLayoutTagDeclaration.java
new file mode 100644
index 0000000..50ffec3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/GridLayoutTagDeclaration.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.component.AbstractUIGridLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasColumnLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRowLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSpacing;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+/**
+ * <p>
+ * WARNING: This component is preliminary and may be changed without a major release.
+ * </p>
+ *
+ * Renders a GridLayout.
+ * <pre>
+ * columns/rows ::= LAYOUT
+ * LAYOUT       ::= TOKEN [";" TOKEN]+
+ * TOKEN        ::= AUTO | PIXEL | PROPORTIONAL
+ * AUTO         ::= "auto" | "fixed"
+ * PIXEL        ::= NUMBER "px"
+ * PROPORTIONAL ::= [NUMBER] "*"
+ * </pre>
+ * <table border="1">
+ * <caption>GridLayout</caption>
+ * <tr>
+ * <th>Parent</th>
+ * <th>Child</th>
+ * <th>Okay?</th>
+ * <th>Remarks</th>
+ * </tr>
+ * <tr>
+ * <td>AUTO</td>
+ * <td>any combination of AUTO or PIXEL but no PROPORTIONAL</td>
+ * <td>okay</td>
+ * <td>-</td>
+ * </tr>
+ * <tr>
+ * <td>AUTO</td>
+ * <td>any combination with at least one PROPORTIONAL</td>
+ * <td>wrong</td>
+ * <td>Layout manager cannot compute the auto value.</td>
+ * </tr>
+ * <tr>
+ * <td>PIXEL</td>
+ * <td>any combination of AUTO or PIXEL but no PROPORTIONAL</td>
+ * <td>potentially wrong</td>
+ * <td>The values depend on each other, the programmer has to keep consistency manually.</td>
+ * </tr>
+ * <tr>
+ * <td>PIXEL</td>
+ * <td>any combination with at least one PROPORTIONAL</td>
+ * <td>okay</td>
+ * <td>-</td>
+ * </tr>
+ * <tr>
+ * <td>PROPORTIONAL</td>
+ * <td>any combination of AUTO or PIXEL but no PROPORTIONAL</td>
+ * <td>potentially wrong</td>
+ * <td>No automatic matching:<ul><li>too little space: scroll bar</li>
+ * <li>too much space: elements will be spread.</li></ul></td>
+ * </tr>
+ * <tr>
+ * <td>PROPORTIONAL</td>
+ * <td>any combination with at least one PROPORTIONAL</td>
+ * <td>okay</td>
+ * <td>-</td>
+ * </tr>
+ * </table>
+ */
+@Tag(name = "gridLayout")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIGridLayout",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIGridLayout",
+    componentFamily = AbstractUIGridLayout.COMPONENT_FAMILY,
+    rendererType = RendererTypes.GRID_LAYOUT,
+    allowedChildComponenents = "NONE")
+public interface GridLayoutTagDeclaration extends HasId, HasSpacing,
+    HasColumnLayout, HasRowLayout, HasBinding, IsVisual {
+
+  /**
+   * This attribute advises the layout manager, to not use space that comes from non rendered components.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean")
+  void setRigid(String rigid);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/HeaderTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/HeaderTagDeclaration.java
new file mode 100644
index 0000000..d1bfa32
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/HeaderTagDeclaration.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFixed;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Defines a header of its parent (like page, box, ...)
+ * @since 3.0.0
+ */
+@Tag(name = "header")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIHeader",
+    uiComponentBaseClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.HEADER,
+    allowedChildComponenents = "ALL")
+public interface HeaderTagDeclaration
+    extends HasIdBindingAndRendered, HasTip, IsFixed, IsVisual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/HiddenTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/HiddenTagDeclaration.java
new file mode 100644
index 0000000..2e47193
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/HiddenTagDeclaration.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+
+import javax.faces.component.UIInput;
+
+/**
+ * Renders a hidden input element.
+ */
+@Tag(name = "hidden")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIHidden",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIHidden",
+    uiComponentFacesClass = "javax.faces.component.UIInput",
+    componentFamily = UIInput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.HIDDEN,
+    allowedChildComponenents = "NONE",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true)
+    })
+public interface HiddenTagDeclaration extends HasIdBindingAndRendered, HasValue, HasConverter, HasValidator,
+    IsReadonly, IsDisabled {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ImageTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ImageTagDeclaration.java
new file mode 100644
index 0000000..3fb16ec
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ImageTagDeclaration.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAlt;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIGraphic;
+
+/**
+ * Renders an image.
+ */
+@Tag(name = "image")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIImage",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIImage",
+    uiComponentFacesClass = "javax.faces.component.UIGraphic",
+    componentFamily = UIGraphic.COMPONENT_FAMILY,
+    rendererType = RendererTypes.IMAGE,
+    allowedChildComponenents = "NONE")
+public interface ImageTagDeclaration
+    extends HasIdBindingAndRendered, HasTip, IsDisabled, IsVisual, HasAlt {
+
+  /**
+   * Absolute url to an image or image name to lookup in tobago resource path.
+   * In the second case, there is no need to set the extension (like .gif or .png).
+   * If you leave it out, you can use different extension in different themes.
+   */
+  @TagAttribute(required = true)
+  @UIComponentTagAttribute()
+  void setValue(String value);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/InTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/InTagDeclaration.java
new file mode 100644
index 0000000..782d4ba
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/InTagDeclaration.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAutocomplete;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasPlaceholder;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsPassword;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequired;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIInput;
+
+/**
+ * Renders a text input field.
+ */
+@Tag(name = "in")
+@BodyContentDescription(anyTagOf = "facestag")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIIn",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIIn",
+    uiComponentFacesClass = "javax.faces.component.UIInput",
+    componentFamily = UIInput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.IN,
+    allowedChildComponenents = {
+        "org.apache.myfaces.tobago.Suggest"
+    },
+    facets = {
+    @Facet(name = Facets.BEFORE,
+        description =
+            "This facet can contain a part for input groups."),
+    @Facet(name = Facets.AFTER,
+        description =
+            "This facet can contain a part for input groups.")
+        },
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface InTagDeclaration
+    extends HasIdBindingAndRendered, HasConverter, IsReadonly, IsDisabled, IsRequired, HasTip, IsPassword,
+    HasAccessKey, HasValidator, HasValue, HasValueChangeListener, HasTabIndex, IsFocus, IsVisual,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessage, HasLabel, HasLabelLayout,
+    HasAutocomplete, HasPlaceholder {
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LabelTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LabelTagDeclaration.java
new file mode 100644
index 0000000..fe9bfd8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LabelTagDeclaration.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasFor;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * Renders a label component.
+ */
+@Tag(name = "label")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UILabel",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUILabel",
+    uiComponentFacesClass = "javax.faces.component.UIOutput",
+    interfaces = "org.apache.myfaces.tobago.component.SupportsAccessKey",
+    componentFamily = UIOutput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.LABEL,
+    allowedChildComponenents = "NONE")
+public interface LabelTagDeclaration extends HasIdBindingAndRendered,
+    HasAccessKey, HasFor, HasTip, IsVisual {
+
+  /**
+   * Text value to display as label. Overwritten by 'labelWithAccessKey'
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setValue(String value);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinkTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinkTagDeclaration.java
new file mode 100644
index 0000000..605e424
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinkTagDeclaration.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAction;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasActionListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConfirmation;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasImage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLink;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTarget;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabledBySecurity;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsImmediateCommand;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsOmit;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsTransition;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UICommand;
+
+/**
+ * Renders a link element.
+ */
+@Tag(name = "link")
+@BodyContentDescription(anyTagOf = "facestag")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UILink",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUILink",
+    uiComponentFacesClass = "javax.faces.component.UICommand",
+    interfaces = "org.apache.myfaces.tobago.component.SupportsAccessKey",
+    componentFamily = UICommand.COMPONENT_FAMILY,
+    rendererType = RendererTypes.LINK,
+    allowedChildComponenents = "NONE",
+    facets = {
+        @Facet(
+            name = Facets.CONFIRMATION,
+            description = "Contains a UIOutput instance with the confirmation message.",
+            allowedChildComponenents = "org.apache.myfaces.tobago.Out")},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            description = "Behavior of a click event.",
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface LinkTagDeclaration
+    extends HasIdBindingAndRendered, HasAction, HasActionListener, IsImmediateCommand, HasConfirmation,
+            HasLink, IsTransition, HasTarget, IsDisabledBySecurity,
+            IsOmit, HasImage, HasTabIndex, IsVisual, HasLabel, HasAccessKey, HasTip {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinksTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinksTagDeclaration.java
new file mode 100644
index 0000000..4561d91
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/LinksTagDeclaration.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Defines a navigation element, which contains a menu-like structure
+ */
+@Tag(name = "links")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UILinks",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUILinks",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.LINKS)
+public interface LinksTagDeclaration extends HasIdBindingAndRendered, IsVisual, HasTip {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/MessagesTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/MessagesTagDeclaration.java
new file mode 100644
index 0000000..c01e34b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/MessagesTagDeclaration.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasFor;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.layout.OrderBy;
+
+import javax.faces.component.UIMessages;
+
+/**
+ * Renders error/validation messages.
+ */
+@Tag(name = "messages")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIMessages",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIMessages",
+    uiComponentFacesClass = "javax.faces.component.UIMessages",
+    componentFamily = UIMessages.COMPONENT_FAMILY,
+    rendererType = RendererTypes.MESSAGES,
+    allowedChildComponenents = "NONE")
+
+public interface MessagesTagDeclaration
+    extends HasIdBindingAndRendered, HasFor, IsVisual {
+
+  /**
+   * Flag indicating that only messages that are not associated to any
+   * particular UIComponent should be displayed. That are messages without clientId.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setGlobalOnly(String globalOnly);
+
+  /**
+   * Flag indicating whether the detail should be included
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setShowDetail(String showDetail);
+
+  /**
+   * Flag indicating whether the summary should be included
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setShowSummary(String showSummary);
+
+   /**
+   * Sets the mininum severity to be shown. E. g. "warn" shows only "warn", "error" and "fatal".
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "javax.faces.application.FacesMessage$Severity", defaultValue = "info",
+      defaultCode = "javax.faces.application.FacesMessage.SEVERITY_INFO")
+  void setMinSeverity(String minSeverity);
+
+   /**
+   * Sets the maximum severity to be shown. E. g. "warn" shows only "warn" and "info".
+    * When setting this attribute you usually shoud take care, that you have a second message tag to show the
+    * higher severity levels.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "javax.faces.application.FacesMessage$Severity", defaultValue = "fatal",
+      defaultCode = "javax.faces.application.FacesMessage.SEVERITY_FATAL")
+  void setMaxSeverity(String maxSeverity);
+
+   /**
+   * Sets the maximum number of messages to show.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "2147483647")
+  void setMaxNumber(String maxNumber);
+
+   /**
+   * Sets the order of the messages.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.OrderBy",
+      allowedValues = {OrderBy.OCCURRENCE, OrderBy.SEVERITY},
+      defaultValue = OrderBy.OCCURRENCE,
+      defaultCode = "org.apache.myfaces.tobago.layout.OrderBy.occurrence")
+  void setOrderBy(String orderBy);
+
+  /**
+   * Has the user to confirm this message?
+   * This attributes handles the case, if the application wants to warn the user about a problem,
+   * and the user has to confirm the message before he/she can continue.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setConfirmation(String confirmation);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ObjectTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ObjectTagDeclaration.java
new file mode 100644
index 0000000..488fec6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ObjectTagDeclaration.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * Show external content inside of an application.
+ * This will typically renders an iframe tag.
+ */
+@Tag(name = "object")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIObject",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIObject",
+    uiComponentFacesClass = "javax.faces.component.UIOutput",
+    componentFamily = UIOutput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.OBJECT,
+    allowedChildComponenents = "NONE")
+public interface ObjectTagDeclaration extends HasIdBindingAndRendered, IsVisual {
+
+  /**
+   * URI to object source
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setSrc(String src);
+
+  /**
+   * Name of the element.
+   * If not set the id will be used as name. The id in JSF normally contains colons.
+   * This doesn't work in Internet Explorer 9 and lower when using window.open(src, target).
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setName(String name);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OperationTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OperationTagDeclaration.java
new file mode 100644
index 0000000..d8d53ab
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OperationTagDeclaration.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+
+/**
+ * An operation describes an Tobago command, which will usually executed on client side.
+ *
+ * ********************* &lt;br/&gt;
+ * WARNING &lt;br/&gt;
+ * ********************* &lt;br/&gt;
+ * This feature is preliminary and may be subject of change in later versions!  &lt;br/&gt;
+ */
+@Tag(name = "operation")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIOperation",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIOperation",
+    componentFamily = "org.apache.myfaces.tobago.Operation",
+    rendererType = RendererTypes.OPERATION,
+    allowedChildComponenents = "NONE")
+public interface OperationTagDeclaration {
+
+  /**
+   * Name of the operation to be executed.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute()
+  void setName(String name);
+
+  /**
+   * The id of the component the operation is related to.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute()
+  void setFor(String forAttribute);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OutTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OutTagDeclaration.java
new file mode 100644
index 0000000..90a063e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/OutTagDeclaration.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSanitize;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * Renders a text
+ */
+@Tag(name = "out")
+@BodyContentDescription(anyTagOf = "f:converter|f:convertNumber|f:convertDateTime|...")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIOut",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIOut",
+    uiComponentFacesClass = "javax.faces.component.UIOutput",
+    componentFamily = UIOutput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.OUT,
+    allowedChildComponenents = "NONE")
+
+public interface OutTagDeclaration
+    extends HasIdBindingAndRendered, HasConverter, HasTip, HasValue, IsVisual,
+    HasSanitize, HasLabel, HasLabelLayout {
+
+  /**
+   * Flag indicating that characters that are
+   * sensitive in HTML and XML markup must be escaped.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setEscape(String escape);
+
+  /**
+   * Indicates that the renderer should create an element in the output language
+   * (e. g. an span or div tag around the output text).
+   * Use true, if you enable the possibility to apply styles to the output.
+   * Use false, if you want to keep the code small (especially inside of sheets).
+   */
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setCreateSpan(String createSpan);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PageTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PageTagDeclaration.java
new file mode 100644
index 0000000..8b4883a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PageTagDeclaration.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIForm;
+
+/**
+ * <p>
+ * Renders a page element.
+ * </p>
+ * <p>
+ * The markup {@link org.apache.myfaces.tobago.context.Markup#SPREAD}
+ * means the page should spread over the hole available area.
+ * So the content will use the full height of the browser window.
+ * <b>Warning: This feature is preliminary and may change, if necessary, in minor releases!</b>
+ * </p>
+ */
+@Tag(name = "page")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIPage",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIPage",
+    uiComponentFacesClass = "javax.faces.component.UIForm",
+    componentFamily = UIForm.COMPONENT_FAMILY,
+    rendererType = RendererTypes.PAGE,
+    facets =
+        { @Facet(name=Facets.LAYOUT, description = "Deprecated! Contains an layout manager. "
+              + "The layout manager tag should surround the content instead.")},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.LOAD),
+        @Behavior(
+            name = ClientBehaviors.RESIZE)
+    })
+
+public interface PageTagDeclaration
+    extends HasLabel, HasId, HasBinding, IsVisual {
+
+  /**
+   * Contains the id of the component which should have the focus after
+   * loading the page.
+   * Set to empty string for disabling setting of focus.
+   * Default (null) enables the "auto focus" feature.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setFocusId(String focusId);
+
+  /**
+   * Absolute URL to an image or image name to lookup in tobago resource path
+   * representing the application. In HTML it is used as a favicon.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setApplicationIcon(String icon);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PanelTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PanelTagDeclaration.java
new file mode 100644
index 0000000..3ef1c14
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PanelTagDeclaration.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasCollapsedMode;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsCollapsed;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Intended for use in situations when only one UIComponent child can be
+ * nested, such as in the case of facets.
+ */
+@Tag(name = "panel")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIPanel",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIPanel",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.PANEL,
+    interfaces = "org.apache.myfaces.tobago.component.Visual",
+    facets = {
+        @Facet(name = Facets.RELOAD, description = "Contains an instance of UIReload",
+            allowedChildComponenents = "org.apache.myfaces.tobago.Reload"),
+        @Facet(name = Facets.LAYOUT, description = "Deprecated. Contains an layout manager. "
+            + "The layout manager tag should surround the content instead.")},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.MOUSEOVER),
+        @Behavior(
+            name = ClientBehaviors.MOUSEOUT)
+    })
+public interface PanelTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, IsCollapsed, HasCollapsedMode, HasTip {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PopupTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PopupTagDeclaration.java
new file mode 100644
index 0000000..d026e3f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/PopupTagDeclaration.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.component.AbstractUIPopup;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.model.CollapseMode;
+
+/**
+ * Renders a popup panel.
+ */
+@Tag(name = "popup")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIPopup",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIPopup",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = AbstractUIPopup.COMPONENT_FAMILY,
+    rendererType = RendererTypes.POPUP
+)
+public interface PopupTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, HasTip {
+
+  /**
+   * Indicating the collapsed state of this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setCollapsed(String collapsed);
+
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.CollapseMode",
+      defaultValue = CollapseMode.ABSENT,
+      defaultCode = "org.apache.myfaces.tobago.model.CollapseMode.absent")
+  void setCollapsedMode(String collapsed);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ProgressTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ProgressTagDeclaration.java
new file mode 100644
index 0000000..8966767
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ProgressTagDeclaration.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * Renders a progress bar.
+ */
+@Tag(name = "progress")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIProgress",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIProgress",
+    uiComponentFacesClass = "javax.faces.component.UIOutput",
+    componentFamily = UIOutput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.PROGRESS,
+    allowedChildComponenents = "NONE",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.COMPLETE,
+            isDefault = true)
+    }
+)
+
+public interface ProgressTagDeclaration extends HasIdBindingAndRendered, HasTip, IsVisual {
+
+  /**
+   * The current value of this component. May be a java.lang.Number or a javax.swing.BoundedRangeModel
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {"javax.swing.BoundedRangeModel", "java.lang.Double"},
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
+  void setValue(String value);
+
+  /**
+   * The maximum of the value of the progress.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {"java.lang.Double"})
+  void setMax(String max);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ReloadTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ReloadTagDeclaration.java
new file mode 100644
index 0000000..29dbfbf
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ReloadTagDeclaration.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+
+/**
+ * Update the parent component
+ *
+ * ********************* &lt;br/&gt;
+ * WARNING &lt;br/&gt;
+ * ********************* &lt;br/&gt;
+ * This feature is preliminary and may be subject of change in later versions!  &lt;br/&gt;
+ */
+@Tag(name = "reload")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIReload",
+    componentFamily = "org.apache.myfaces.tobago.Reload",
+    allowedChildComponenents = "NONE")
+public interface ReloadTagDeclaration extends HasIdBindingAndRendered {
+
+
+  /**
+   * Time in milliseconds after which the parent component is automatically reloaded.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "5000")
+  void setFrequency(String frequency);
+
+  /**
+   * Is update required.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setUpdate(String update);
+
+  /**
+   * Flag indicating that
+   * the update check should be performed
+   * immediately (that is, during Apply Request Values phase) rather than
+   * waiting until Render Response phase.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setImmediate(String immediate);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ResetInputActionListenerTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ResetInputActionListenerTagDeclaration.java
new file mode 100644
index 0000000..afb56e1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ResetInputActionListenerTagDeclaration.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.component.Attributes;
+
+/**
+ * A ResetInputActionListener is a declarative way to allow an action source to reset all EditableValueHolder
+ * of a page or in a sub-form or part of the component tree.
+ */
+@Tag(name = "resetInputActionListener")
+@SimpleTag(
+    faceletHandler = "org.apache.myfaces.tobago.facelets.ResetInputActionListenerHandler")
+public interface ResetInputActionListenerTagDeclaration {
+
+  /**
+   * A list of ids of components. For each id, the surrounding (virtual) UIForm will be searched, and for each of
+   * them, all containing EditableValueHolder will be reset.
+   */
+  @TagAttribute(required = false, name = Attributes.EXECUTE, type = "java.lang.String")
+  void setExecute(final javax.el.ValueExpression execute);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/RowTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/RowTagDeclaration.java
new file mode 100644
index 0000000..bdfde17
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/RowTagDeclaration.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+/**
+ * This component creates a representative in a UISheet for each row.
+ * The tag must be a subtag of &lt;tc:sheet&gt;
+ */
+@Tag(name = "row")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIRow",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIRow",
+    uiComponentFacesClass = "javax.faces.component.UIColumn",
+    rendererType = RendererTypes.ROW,
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            description = "Behavior of a click event.",
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK)
+    })
+public interface RowTagDeclaration extends HasIdBindingAndRendered, IsVisual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ScriptTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ScriptTagDeclaration.java
new file mode 100644
index 0000000..dda0452
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ScriptTagDeclaration.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+
+/**
+ * This tag adds script files to include into the rendered page.
+ * <br>
+ * Some features are deprecated (because of CSP): This tag adds client side script to the rendered page.
+ */
+@Tag(name = "script")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIScript",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIScript",
+    componentFamily = "org.apache.myfaces.tobago.Script",
+    faceletHandler = "org.apache.myfaces.tobago.facelets.ScriptHandler",
+    rendererType = RendererTypes.SCRIPT,
+    allowedChildComponenents = "NONE")
+public interface ScriptTagDeclaration extends HasIdBindingAndRendered {
+
+  /**
+   * File name to include into the rendered page. The name must be full qualified, or relative.
+   * If using a complete path from root, you'll need to add the contextPath from the web application.
+   * This can be done with the EL #{request.contextPath}.
+   * @param file A JavaScript file.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute()
+  void setFile(String file);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SectionTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SectionTagDeclaration.java
new file mode 100644
index 0000000..0f88793
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SectionTagDeclaration.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasCollapsedMode;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasImage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsCollapsed;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+/**
+ * Renders a section or subsection.
+ */
+@Tag(name = "section")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISection",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISection",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = "org.apache.myfaces.tobago.Section",
+    rendererType = RendererTypes.SECTION,
+    facets = {
+        @Facet(name = Facets.LABEL,
+            description = "This facet contains a UILabel",
+            allowedChildComponenents = "org.apache.myfaces.tobago.Label")})
+
+public interface SectionTagDeclaration
+    extends HasIdBindingAndRendered, HasLabel, IsVisual, HasImage, IsCollapsed, HasCollapsedMode, HasTip {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutTagDeclaration.java
new file mode 100644
index 0000000..6108cb1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SegmentLayoutTagDeclaration.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.component.AbstractUISegmentLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+/**
+ * Renders a layout using a 12 columns grid.
+ * Find more information on how the grid works in the Twitter Bootstrap documentation.
+ *
+ * If no attribute is defined, extraSmall="12" will be used as default.
+ * @since 3.0.0
+ */
+@Tag(name = "segmentLayout")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISegmentLayout",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISegmentLayout",
+    componentFamily = AbstractUISegmentLayout.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SEGMENT_LAYOUT,
+    allowedChildComponenents = "NONE")
+public interface SegmentLayoutTagDeclaration extends HasIdBindingAndRendered, IsVisual {
+
+  /**
+   * The semicolon-separated definition of the columns for extra small devices. The sum must be 12.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.ColumnPartition")
+  void setExtraSmall(String extraSmall);
+
+  /**
+   * The semicolon-separated definition of the columns for small devices. The sum must be 12.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.ColumnPartition")
+  void setSmall(String small);
+
+  /**
+   * The semicolon-separated definition of the columns for medium devices. The sum must be 12.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.ColumnPartition")
+  void setMedium(String medium);
+
+  /**
+   * The semicolon-separated definition of the columns for large devices. The sum must be 12.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.ColumnPartition")
+  void setLarge(String large);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectBooleanCheckboxTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectBooleanCheckboxTagDeclaration.java
new file mode 100644
index 0000000..8aaf2d2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectBooleanCheckboxTagDeclaration.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasItemLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessageForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequiredForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectBoolean;
+
+/**
+ * Renders a checkbox.
+ */
+@Tag(name = "selectBooleanCheckbox")
+@BodyContentDescription(anyTagOf = "<f:facet>* ")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectBooleanCheckbox",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectBooleanCheckbox",
+    uiComponentFacesClass = "javax.faces.component.UISelectBoolean",
+    componentFamily = UISelectBoolean.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_BOOLEAN_CHECKBOX,
+    allowedChildComponenents = "NONE",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+
+public interface SelectBooleanCheckboxTagDeclaration extends HasValidator,
+    HasValueChangeListener, HasIdBindingAndRendered, HasValue, IsDisabled,
+    HasTip, IsReadonly, HasTabIndex, IsRequiredForSelect, HasConverter, IsFocus,
+    HasValidatorMessage, HasRequiredMessageForSelect, HasConverterMessage, IsVisual,
+    HasAccessKey, HasItemLabel, HasLabel, HasLabelLayout {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectItemTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectItemTagDeclaration.java
new file mode 100644
index 0000000..a741bdb
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectItemTagDeclaration.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasItemLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+/**
+ * Add a child UISelectItem component to the UIComponent
+ * associated with the closed parent UIComponent custom
+ * action.
+ */
+@Tag(name = "selectItem")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectItem",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectItem",
+    uiComponentFacesClass = "javax.faces.component.UISelectItem",
+    allowedChildComponenents = "NONE")
+public interface SelectItemTagDeclaration extends HasBinding, HasId, IsVisual, HasItemLabel {
+
+  /**
+   * Description of an item, might be rendered as a tool tip.
+   * @deprecated since 2.0.0, please use itemTip.
+   */
+  @Deprecated
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.lang.String"})
+  void setItemDescription(String itemDescription);
+
+  /**
+   * Flag indicating whether the option created
+   * by this component is disabled.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"boolean"}, defaultValue = "false")
+  void setItemDisabled(String itemDisabled);
+
+  /**
+   * Value to be returned to the server if this option is selected by the user.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setItemValue(String itemValue);
+
+  /**
+   * Value binding expression pointing at a SelectItem instance containing
+   * the information for this option.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "javax.faces.model.SelectItem",
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
+  void setValue(String value);
+
+  /**
+   * Image to be displayed to the user for this option.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setItemImage(String itemImage);
+
+  /**
+   * Text value to display as tooltip.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setTip(String tip);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectItemsTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectItemsTagDeclaration.java
new file mode 100644
index 0000000..e7938f2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectItemsTagDeclaration.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasItemLabel;
+
+/**
+ * Add a child UISelectItems component to the UIComponent
+ * associated with the closed parent UIComponent custom
+ * action.
+ */
+@Tag(name = "selectItems")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectItems",
+    uiComponentBaseClass = "javax.faces.component.UISelectItems",
+    uiComponentFacesClass = "javax.faces.component.UISelectItems",
+    isComponentAlreadyDefined = false,
+    allowedChildComponenents = "NONE")
+public interface SelectItemsTagDeclaration extends HasId, HasBinding, HasItemLabel {
+
+  /**
+   * Value binding expression pointing at a List or array of SelectItem instances containing
+   * the information for this option.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {"javax.faces.model.SelectItem[]", "java.lang.Object[]", "java.util.Collection"},
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
+  void setValue(String value);
+
+  /**
+   * Name of a variable under which the iterated data will be exposed.
+   * It may be referred to in EL of other attributes.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(expression = DynamicExpression.PROHIBITED)
+  void setVar(final String var);
+
+  /**
+   * Flag indicating whether the option created
+   * by this component is disabled.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"boolean"}, defaultValue = "false")
+  void setItemDisabled(String itemDisabled);
+
+  /**
+   * Value to be returned to the server if this option is selected by the user.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.lang.Object"})
+  void setItemValue(String itemValue);
+
+  /**
+   * Image to be displayed to the user for this option.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setItemImage(String itemImage);
+
+  /**
+   * Text value to display as tooltip.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setTip(String tip);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyCheckboxTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyCheckboxTagDeclaration.java
new file mode 100644
index 0000000..21deef5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyCheckboxTagDeclaration.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRenderRange;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessageForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsInline;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequiredForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectMany;
+
+/**
+ * Render a group of checkboxes.
+ */
+@Tag(name = "selectManyCheckbox")
+@BodyContentDescription(anyTagOf = "(<f:selectItems>|<f:selectItem>|<tc:selectItem>)+ <f:facet>* ")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectManyCheckbox",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectManyCheckbox",
+    uiComponentFacesClass = "javax.faces.component.UISelectMany",
+    componentFamily = UISelectMany.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_MANY_CHECKBOX,
+    allowedChildComponenents = {
+        "javax.faces.SelectItem",
+        "javax.faces.SelectItems"},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface SelectManyCheckboxTagDeclaration extends
+    IsDisabled, HasId, HasTip, IsInline, HasRenderRange, IsRendered, IsRequiredForSelect,
+    HasBinding, IsReadonly, HasConverter, HasLabelLayout,
+    HasLabel, HasValidator, HasValueChangeListener,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessageForSelect, HasTabIndex, IsFocus, IsVisual {
+
+  /**
+   * The value of the multi select.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.lang.Object[]", "java.util.List"})
+  void setValue(String value);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyListboxTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyListboxTagDeclaration.java
new file mode 100644
index 0000000..38e46d5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyListboxTagDeclaration.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessageForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSize;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequiredForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectMany;
+
+/**
+ * Render a multi selection option listbox.
+ */
+@Tag(name = "selectManyListbox")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectManyListbox",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectManyListbox",
+    uiComponentFacesClass = "javax.faces.component.UISelectMany",
+    componentFamily = UISelectMany.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_MANY_LISTBOX,
+    allowedChildComponenents = {"javax.faces.SelectItem", "javax.faces.SelectItems"},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+
+public interface SelectManyListboxTagDeclaration
+    extends HasId, IsDisabled, IsRendered, HasBinding, HasTip,
+    IsReadonly, HasConverter, IsRequiredForSelect, HasLabel, HasValidator, HasValueChangeListener, HasLabelLayout,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessageForSelect, HasTabIndex, IsFocus, IsVisual, HasSize {
+
+  /**
+   * The value of the multi select.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.lang.Object[]", "java.util.List"})
+  void setValue(String value);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyShuttleTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyShuttleTagDeclaration.java
new file mode 100644
index 0000000..838b8a7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectManyShuttleTagDeclaration.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessageForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSize;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequiredForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectMany;
+
+@Tag(name = "selectManyShuttle")
+@BodyContentDescription(anyTagOf = "(<f:selectItems>|<f:selectItem>|<tc:selectItem>)+ <f:facet>* ")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectManyShuttle",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectManyShuttle",
+    uiComponentFacesClass = "javax.faces.component.UISelectMany",
+    componentFamily = UISelectMany.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_MANY_SHUTTLE,
+    allowedChildComponenents = {
+        "javax.faces.SelectItem",
+        "javax.faces.SelectItems"},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface SelectManyShuttleTagDeclaration extends
+    IsDisabled, HasId, HasTip, IsRendered, IsRequiredForSelect, HasBinding, IsReadonly, HasConverter,
+    HasLabel, HasValidator, HasValueChangeListener, HasLabelLayout,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessageForSelect, HasTabIndex, IsFocus, IsVisual, HasSize {
+
+  /**
+   * The value of the multi select.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.lang.Object[]", "java.util.List"})
+  void setValue(String value);
+
+  /**
+   * A localized user presentable label for the left select box.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setUnselectedLabel(String label);
+
+
+  /**
+   * A localized user presentable label for the right select box.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setSelectedLabel(String label);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneChoiceTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneChoiceTagDeclaration.java
new file mode 100644
index 0000000..48a474a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneChoiceTagDeclaration.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectOne;
+
+/**
+ * Render a single selection dropdown list.
+ */
+@Tag(name = "selectOneChoice")
+@BodyContentDescription(anyTagOf = "(<f:selectItems>|<f:selectItem>|<tc:selectItem>)+ <f:facet>* ")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectOneChoice",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectOneChoice",
+    uiComponentFacesClass = "javax.faces.component.UISelectOne",
+    componentFamily = UISelectOne.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_ONE_CHOICE,
+    allowedChildComponenents = {
+        "javax.faces.SelectItem",
+        "javax.faces.SelectItems"
+        },
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface SelectOneChoiceTagDeclaration
+    extends HasValidator, HasValue, HasValueChangeListener, HasTabIndex, IsFocus, IsVisual,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessage, HasId, IsDisabled, IsReadonly, HasLabel,
+    IsRendered, HasConverter, HasBinding, HasTip, HasLabelLayout {
+
+  /**
+   * Flag indicating that selecting an Item representing a value is required.
+   * If an SelectItem was chosen which underling value is an empty string an
+   * ValidationError occurs and a Error Message is rendered.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setRequired(String required);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneListboxTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneListboxTagDeclaration.java
new file mode 100644
index 0000000..2a15496
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneListboxTagDeclaration.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSize;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectOne;
+
+/**
+ * Render a single selection option listbox.
+ */
+@Tag(name = "selectOneListbox")
+@BodyContentDescription(anyTagOf = "(<f:selectItems>|<f:selectItem>|<tc:selectItem>)+ <f:facet>* ")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectOneListbox",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectOneListbox",
+    uiComponentFacesClass = "javax.faces.component.UISelectOne",
+    componentFamily = UISelectOne.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_ONE_LISTBOX,
+    allowedChildComponenents = {
+        "javax.faces.SelectItem",
+        "javax.faces.SelectItems"
+        },
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface SelectOneListboxTagDeclaration
+    extends HasValidator, HasValue, HasValueChangeListener, HasTabIndex, IsFocus, IsVisual,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessage, HasId, IsDisabled, IsReadonly, HasLabel, IsRendered,
+    HasBinding, HasTip, HasConverter, HasLabelLayout, HasSize {
+
+  /**
+   * Flag indicating that selecting an Item representing a Value is Required.
+   * If an SelectItem was chosen which underling value is an empty string an
+   * ValidationError occurs and a Error Message is rendered.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setRequired(String required);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneRadioTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneRadioTagDeclaration.java
new file mode 100644
index 0000000..470ee45
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectOneRadioTagDeclaration.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRenderRange;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsInline;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectOne;
+
+/**
+ * Render a set of radio buttons.
+ */
+@Tag(name = "selectOneRadio")
+@BodyContentDescription(anyTagOf = "(<f:selectItems>|<f:selectItem>|<tc:selectItem>)+ <f:facet>* ")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectOneRadio",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISelectOneRadio",
+    uiComponentFacesClass = "javax.faces.component.UISelectOne",
+    componentFamily = UISelectOne.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_ONE_RADIO,
+    allowedChildComponenents = {
+        "javax.faces.SelectItem",
+        "javax.faces.SelectItems"
+        },
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface SelectOneRadioTagDeclaration
+    extends HasValidator, HasValue, HasValueChangeListener, HasTabIndex, IsFocus, IsVisual,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessage, IsDisabled, IsReadonly, HasId, HasTip, IsInline,
+    HasRenderRange, IsRendered, HasBinding, HasConverter, HasLabel, HasLabelLayout {
+
+  /**
+   * Flag indicating that selecting an Item representing a Value is Required.
+   * If an SelectItem was chosen which underling value is an empty string an
+   * ValidationError occurs and a Error Message is rendered.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setRequired(String required);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectReferenceTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectReferenceTagDeclaration.java
new file mode 100644
index 0000000..6af56ad
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SelectReferenceTagDeclaration.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * Renders a set of option related to and same type as the <strong>for</strong>
+ * component.
+ */
+@Tag(name = "selectReference")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISelectReference",
+    uiComponentBaseClass = "javax.faces.component.UIOutput",
+    uiComponentFacesClass = "javax.faces.component.UIOutput",
+    componentFamily = UIOutput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SELECT_REFERENCE,
+    allowedChildComponenents = "NONE")
+public interface SelectReferenceTagDeclaration extends HasIdBindingAndRendered {
+  /**
+   * Id of the component, this is related to.
+   */
+  @TagAttribute(required = true)
+  @UIComponentTagAttribute()
+  void setFor(String forComponent);
+
+  /**
+   * Range of items to render.
+   */
+  @TagAttribute(required = true)
+  @UIComponentTagAttribute()
+  void setRenderRange(String renderRange);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SeparatorTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SeparatorTagDeclaration.java
new file mode 100644
index 0000000..5cf1ee3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SeparatorTagDeclaration.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+/**
+ * Renders a separator.
+ */
+@Tag(name = "separator")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISeparator",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISeparator",
+    componentFamily = "org.apache.myfaces.tobago.Separator",
+    rendererType = RendererTypes.SEPARATOR,
+    allowedChildComponenents = "NONE",
+    facets = {
+        @Facet(name = Facets.LABEL,
+            description = "This facet contains a UILabel",
+            allowedChildComponenents = "org.apache.myfaces.tobago.Label")})
+
+public interface SeparatorTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, HasLabel {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetPageCommandTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetPageCommandTagDeclaration.java
new file mode 100644
index 0000000..4e431d2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetPageCommandTagDeclaration.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.RendererTypes;
+
+import javax.faces.component.UICommand;
+
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UICommand",
+    uiComponentFacesClass = "javax.faces.component.UICommand",
+    componentFamily = UICommand.COMPONENT_FAMILY,
+    generate = false,
+    rendererType = RendererTypes.SHEET_PAGE_COMMAND)
+public interface SheetPageCommandTagDeclaration extends LinkTagDeclaration {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java
new file mode 100644
index 0000000..da396e6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SheetTagDeclaration.java
@@ -0,0 +1,257 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasVar;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsShowRoot;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsShowRootJunction;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.layout.ShowPosition;
+import org.apache.myfaces.tobago.model.Selectable;
+
+import javax.faces.component.UIData;
+
+/**
+ * Render a sheet element.
+ */
+@Tag(name = "sheet")
+@BodyContentDescription(anyTagOf = "<tc:column>* <tc:columnSelector>? <tc:row>?")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISheet",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISheet",
+    interfaces = "org.apache.myfaces.tobago.event.SortActionSource2",
+    uiComponentFacesClass = "javax.faces.component.UIData",
+    componentFamily = UIData.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SHEET,
+    allowedChildComponenents = {
+        "javax.faces.Column",
+        "org.apache.myfaces.tobago.ColumnSelector"},
+    facets = {
+        @Facet(
+            name = Facets.RELOAD,
+            description = "Contains an instance of UIReload",
+            allowedChildComponenents = "org.apache.myfaces.tobago.Reload")},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.RELOAD, // XXX replace by click
+            isDefault = true)
+    })
+public interface SheetTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, IsShowRoot, IsShowRootJunction, HasVar {
+  /**
+   * LayoutConstraints for column layout.
+   * Semicolon separated list of layout tokens ('&lt;x&gt;*', '&lt;x&gt;px' or '&lt;x&gt;%') or "auto"
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setColumns(String columns);
+
+  /**
+   * Flag indicating the header should be rendered.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setShowHeader(String showHeader);
+
+  /**
+   * The number of rows to display, starting with the one identified by the
+   * "first" property.
+   * <br> The default has been changed from 100 to 0 because this is the default
+   * in the JSF standard (since Tobago 1.5).
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "int",
+      defaultValue = "0")
+  void setRows(String rows);
+
+  /**
+   * Zero-relative row number of the first row to be displayed.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "int",
+      defaultValue = "0")
+  void setFirst(String first);
+
+  /**
+   * The sheet's data.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.lang.Object[]", "java.util.List", "javax.servlet.jsp.jstl.sql.Result",
+      "java.sql.ResultSet", "java.lang.Object", "javax.faces.model.DataModel"},
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
+  void setValue(String value);
+
+  /**
+   * Flag indicating whether or not the paging panel should be display, if it is not needed for paging.<br>
+   * <ul>
+   * <li>showPagingAlways="false" which is the default means, that the paging footer should be displayed,
+   * only when it is needed.
+   * <ul>
+   * <li>When the rows="0" paging is not needed, so the footer will not be rendered,
+   * <li>when rows="N", N &gt; 0 and the size of the data value is &lt;= N paging is not needed
+   * and the footer will not be rendered,
+   * <li>in any other case the paging footer will be displayed.
+   * </ul>
+   * <li>showPagingAlways="true" means, that the paging footer should be displayed in any case.
+   * </ul>
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setShowPagingAlways(String showPagingAlways);
+
+  /**
+   * The count of rendered direct paging links in the sheet's footer.<br>
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "9")
+  void setDirectLinkCount(String directLinkCount);
+
+  /**
+   * Flag indicating whether or not a range of direct paging links should be
+   * rendered in the sheet's footer.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.ShowPosition",
+      defaultValue = ShowPosition.CENTER,
+      allowedValues = {
+          ShowPosition.LEFT, ShowPosition.CENTER, ShowPosition.RIGHT, ShowPosition.NONE
+      },
+      defaultCode = "org.apache.myfaces.tobago.layout.ShowPosition.center")
+  void setShowDirectLinks(String showDirectLinks);
+
+  /**
+   * Flag indicating whether and where the range pages should
+   * rendered in the sheet's footer. Rendering this range also offers the
+   * capability to enter the index displayed page directly.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.ShowPosition",
+      defaultValue = ShowPosition.RIGHT,
+      allowedValues = {
+          ShowPosition.LEFT, ShowPosition.CENTER, ShowPosition.RIGHT, ShowPosition.NONE
+      },
+      defaultCode = "org.apache.myfaces.tobago.layout.ShowPosition.right")
+  void setShowPageRange(String showPageRange);
+
+  /**
+   * Flag indicating whether or not the range of displayed rows should
+   * rendered in the sheet's footer. Rendering this range also offers the
+   * capability to enter the index of the start row directly.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.ShowPosition",
+      defaultValue = ShowPosition.LEFT,
+      allowedValues = {
+          ShowPosition.LEFT, ShowPosition.CENTER, ShowPosition.RIGHT, ShowPosition.NONE
+      },
+      defaultCode = "org.apache.myfaces.tobago.layout.ShowPosition.left")
+  void setShowRowRange(String showRowRange);
+
+  /**
+   * Indicating the selection mode of the sheet.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.Selectable",
+      defaultValue = Selectable.MULTI,
+      allowedValues = {
+          Selectable.NONE, Selectable.SINGLE, Selectable.SINGLE_OR_NONE, Selectable.MULTI
+      },
+      defaultCode = "org.apache.myfaces.tobago.model.Selectable.multi")
+  void setSelectable(String selectable);
+
+  /**
+   * Sheet state saving object.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.SheetState",
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED,
+      generate = false)
+  void setState(String state);
+
+  /**
+   * Method binding representing a stateChangeListener method that will be
+   * notified when the state was changed by the user.
+   * The expression must evaluate to a public method that takes a
+   * SheetStateChangeEvent parameter, with a return type of void.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {},
+      expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
+      methodSignature = "javax.faces.event.ActionEvent")
+  void setStateChangeListener(String stateChangeListener);
+
+  /**
+   * Method binding representing an actionListener method that will be
+   * invoked when sorting was requested by the user.
+   * Use this if your application needs special handling for sorting columns.
+   * If this is not set and the sortable attribute column is set to true the sheet
+   * implementation will use a default sort method.
+   * The expression must evaluate to a public method which takes an
+   * ActionEvent as parameter and with a return type of void.
+   * The method will receive a {@link org.apache.myfaces.tobago.event.SortActionEvent}.
+   * The method should sort according to the sortColumnId and direction getting from
+   * the sheet's {@link org.apache.myfaces.tobago.model.SheetState} object.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {},
+      expression = DynamicExpression.METHOD_BINDING_REQUIRED,
+      methodSignature = "javax.faces.event.ActionEvent")
+  void setSortActionListener(String sortActionListener);
+
+
+  /**
+   * Flag indicating if paging arrows are shown near direct links
+   *
+   * @since 2.0.0
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setShowDirectLinksArrows(String showDirectLinksArrows);
+
+  /**
+   * Flag indicating if paging arrows are shown near page range
+   *
+   * @since 2.0.0
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setShowPageRangeArrows(String showPageRangeArrows);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SpanTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SpanTagDeclaration.java
new file mode 100644
index 0000000..18fe92d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SpanTagDeclaration.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+
+import javax.el.ValueExpression;
+
+/**
+ * Add a column span or row span to the parent UIComponent, useful for a grid layout.
+ */
+@Tag(name = "span")
+@SimpleTag(faceletHandler = "org.apache.myfaces.tobago.facelets.SpanHandler")
+public interface SpanTagDeclaration {
+
+  /**
+   * The number of horizontal cells this component should use.
+   */
+  @TagAttribute(type = "java.lang.Integer")
+  void setColumn(final ValueExpression column);
+
+  /**
+   * The number of vertical cells this component should use.
+   */
+  @TagAttribute(type = "java.lang.Integer")
+  void setRow(final ValueExpression row);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/StyleTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/StyleTagDeclaration.java
new file mode 100644
index 0000000..dff0d54
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/StyleTagDeclaration.java
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.layout.Display;
+import org.apache.myfaces.tobago.layout.Overflow;
+import org.apache.myfaces.tobago.layout.Position;
+import org.apache.myfaces.tobago.layout.TextAlign;
+
+/**
+ * <p>
+ * Add a style tag with the given file name to the header (using file attribute) or add
+ * some CSS styles to the parent component.
+ * </p>
+ */
+@Tag(name = "style")
+@BodyContentDescription(contentType = "css")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UIStyle",
+    componentFamily = "org.apache.myfaces.tobago.Style",
+    rendererType = RendererTypes.STYLE,
+    allowedChildComponenents = "NONE")
+public interface StyleTagDeclaration extends HasIdBindingAndRendered {
+
+  /**
+   * Name of the stylesheet file to add to page. The name must be full qualified, or relative.
+   * If using a complete path from root, you'll need to add the contextPath from the web application.
+   * This can be done with the EL #{request.contextPath}.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute()
+  void setFile(String file);
+
+  /**
+   * @param customClass A custom CSS class for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.renderkit.css.CustomClass")
+  void setCustomClass(String customClass);
+
+  /**
+   * @param width The width for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setWidth(String width);
+
+  /**
+   * @param height The height for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setHeight(String height);
+
+  /**
+   * @param minWidth The minimum width for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMinWidth(String minWidth);
+
+  /**
+   * @param minHeight The minimum height for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMinHeight(String minHeight);
+
+  /**
+   * @param maxWidth The maximum width for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMaxWidth(String maxWidth);
+
+  /**
+   * @param maxHeight The maximum height for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMaxHeight(String maxHeight);
+
+  /**
+   * @param left The left position value for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setLeft(String left);
+
+  /**
+   * @param right The left position value for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setRight(String right);
+
+  /**
+   * @param top The top position value for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setTop(String top);
+
+  /**
+   * @param bottom The top position value for this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setBottom(String bottom);
+
+  /**
+   * @param paddingLeft The left padding.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setPaddingLeft(String paddingLeft);
+
+  /**
+   * @param paddingRight The right padding.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setPaddingRight(String paddingRight);
+
+  /**
+   * @param paddingTop The top padding.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setPaddingTop(String paddingTop);
+
+  /**
+   * @param paddingBottom The bottom padding.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setPaddingBottom(String paddingBottom);
+
+  /**
+   * @param marginLeft The margin at the left of this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMarginLeft(String marginLeft);
+
+  /**
+   * @param marginRight The margin at the right of this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMarginRight(String marginRight);
+
+  /**
+   * @param marginTop The margin at the top of this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMarginTop(String marginTop);
+
+  /**
+   * @param marginBottom The margin at the bottom of this component.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setMarginBottom(String marginBottom);
+
+  /**
+   * @param overflowX Does the component need a horizontal scollbar.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.Overflow",
+      allowedValues = {Overflow.AUTO, Overflow.SCROLL, Overflow.HIDDEN})
+  void setOverflowX(String overflowX);
+
+  /**
+   * @param overflowY Does the component need a vertical scollbar.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.Overflow",
+      allowedValues = {Overflow.AUTO, Overflow.SCROLL, Overflow.HIDDEN})
+  void setOverflowY(String overflowY);
+
+  /**
+   * @param display Indicates the renderer to render the element as
+   *                {@link Display#block}, {@link Display#inline} or {@link Display#none}.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.Display",
+      allowedValues = {Display.BLOCK, Display.INLINE, Display.NONE})
+  void setDisplay(String display);
+
+  /**
+   * @param position Values for the position used with CSS.
+   * @since 3.0.0
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.Position",
+      allowedValues = {Position.ABSOLUTE, Position.RELATIVE, Position.FIXED})
+  void setPosition(String position);
+
+  /**
+   * The alignment of the elements inside of the container, possible values are:
+   * {@link TextAlign#left},
+   * {@link TextAlign#right},
+   * {@link TextAlign#center} and
+   * {@link TextAlign#justify}.
+   *
+   * @since 3.0.0
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {"org.apache.myfaces.tobago.layout.TextAlign"},
+      allowedValues = {
+          TextAlign.LEFT, TextAlign.RIGHT, TextAlign.CENTER, TextAlign.JUSTIFY
+      })
+  void setTextAlign(String textAlign);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SuggestTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SuggestTagDeclaration.java
new file mode 100644
index 0000000..4269103
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/SuggestTagDeclaration.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.model.SuggestFilter;
+
+import javax.faces.component.UIInput;
+
+/**
+ * Renders a list of suggested texts for a given input field.
+ *
+ * Basic features:
+ * <ul>
+ *   <li>provide a list directly while rendering (not AJAX needed) [todo]</li>
+ *   <li>update by typing (AJAX)</li>
+ *   <li>minimum number of typed characters (to avoid useless requests)</li>
+ *   <li>update delay (useful for optimization)</li>
+ *   <li>filter on client side (useful for optimization) [todo]</li>
+ * </ul>
+ *
+ * @since 2.0.0
+ */
+@Tag(name = "suggest")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISuggest",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISuggest",
+    componentFamily = UIInput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.SUGGEST,
+    allowedChildComponenents = {
+        "org.apache.myfaces.tobago.SelectItems",
+        "org.apache.myfaces.tobago.SelectItem"
+    }/* todo ,
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.SUGGEST,
+            isDefault = true)
+    }*/)
+public interface SuggestTagDeclaration extends HasIdBindingAndRendered {
+
+  /**
+   * MethodBinding which generates a list of suggested input values based on
+   * the currently entered text, which could be retrieved via getSubmittedValue() on the UIIn.
+   * The expression has to evaluate to a public method which has a javax.faces.component.UIInput parameter
+   * and returns a List&lt;String&gt;, a List&lt;org.apache.myfaces.tobago.model.AutoSuggestItem&gt;
+   * or a org.apache.myfaces.tobago.model.AutoSuggestItems.
+   *
+   * @deprecated Please use an <code>&lt;tc:selectItems&gt;</code> tag or a list of <code>&lt;tc:selectItem&gt;</code>
+   * tags (TODO: not implemented yet).
+   */
+  @Deprecated
+  @TagAttribute
+  @UIComponentTagAttribute(type = {},
+      expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
+      methodSignature = "javax.faces.component.UIInput",
+      methodReturnType = "java.lang.Object")
+  void setSuggestMethod(String suggestMethod);
+
+  /**
+   * Minimum number of characters to type before the list will be requested.
+   * If the value is 0, there will be send an initial list to the client.
+   * So, if you set <pre>update="false"</pre> this value should be 0.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "1")
+  void setMinimumCharacters(String minimumCharacters);
+
+  /**
+   * Time in milli seconds before the list will be requested (by AJAX).
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "200")
+  void setDelay(String delay);
+
+  /**
+   * The maximum number of item to display in the drop down list.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "10")
+  void setMaximumItems(String maximumItems);
+
+  /**
+   * The real size of the result list.
+   * Typically the result list will be cropped (in the backend) to save memory.
+   * This value can be set, to show the user there are more results for the given string.
+   * If the value is -1, no hint will be displayed.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "-1")
+  void setTotalCount(String totalCount);
+
+  /**
+   * TODO: not implemented yet
+   * <p>
+   * Additional client side filtering of the result list.
+   * This is useful when sending the full list initially to the client and
+   * setting <code>update=false</code>.
+   * </p>
+   * <p>
+   * Possible values are:
+   * </p>
+   * <dl>
+   *   <dt>all</dt>
+   *   <dd>no filtering</dd>
+   *   <dt>prefix</dt>
+   *   <dd>checks if the suggested string starts with the typed text</dd>
+   *   <dt>contains</dt>
+   *   <dd>checks if the typed text is inside of the suggested string</dd>
+   * </dl>
+   * <p>
+   * The filter will only applied on the client side and
+   * only if server updated (by AJAX) are turned off (<code>update=false</code>);
+   * </p>
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.SuggestFilter",
+      defaultValue = "SuggestFilter.ALL",
+      allowedValues = {
+          SuggestFilter.STRING_ALL,
+          SuggestFilter.STRING_PREFIX,
+          SuggestFilter.STRING_CONTAINS})
+  void setFilter(String filter);
+
+  /**
+   * TODO: not implemented yet
+   * <p>
+   * Should the list be updated while typing (via AJAX). This is the default behaviour.
+   * If you set this value to <code>false</code>, please set the <code>minimumCharacters="0"</code>.
+   * </p>
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setUpdate(String update);
+
+  /**
+   * The query is the string typed by the user.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(generate = false, isTransient = true)
+  void setQuery(String query);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabChangeListenerTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabChangeListenerTagDeclaration.java
new file mode 100644
index 0000000..f28fbe0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabChangeListenerTagDeclaration.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+
+import javax.el.ValueExpression;
+
+/**
+ * Register an TabChangedListener instance on the UIComponent
+ * associated with the closest parent UIComponent custom action.
+ */
+@Tag(name = "tabChangeListener")
+@SimpleTag(
+    faceletHandler = "org.apache.myfaces.tobago.facelets.TabChangeListenerHandler")
+public interface TabChangeListenerTagDeclaration {
+
+  /**
+   * Fully qualified Java class name of a TabChangeListener to be
+   * created and registered.
+   */
+  @TagAttribute(required = true, name = "type", type = "java.lang.String")
+  void setType(final ValueExpression type);
+
+  /**
+   * The value binding expression to a TabChangeListener.
+   */
+  @TagAttribute(name = "binding", type = "org.apache.myfaces.tobago.event.TabChangeListener")
+  void setBinding(final ValueExpression binding);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabGroupTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabGroupTagDeclaration.java
new file mode 100644
index 0000000..b2077ae
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabGroupTagDeclaration.java
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAction;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasActionListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsImmediateCommand;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.model.SwitchType;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Renders a tab group which contains tab panels.
+ */
+@Tag(name = "tabGroup")
+@BodyContentDescription(anyTagOf = "(<tc:tab>* ")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITabGroup",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITabGroup",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TAB_GROUP,
+    interfaces = "javax.faces.component.ActionSource2",
+    allowedChildComponenents = "org.apache.myfaces.tobago.Tab",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            isDefault = true)
+    })
+public interface TabGroupTagDeclaration
+    extends HasIdBindingAndRendered, IsImmediateCommand, HasAction, HasActionListener, IsVisual, HasTip {
+
+  /**
+   * Flag indicating that the tab navigation bar is rendered.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setShowNavigationBar(String showNavigationBar);
+
+  /**
+   * <p>
+   * Indicating how tab switching should be done.
+   * </p>
+   * <p>
+   * Possible values are:
+   * </p>
+   * <dl>
+   *   <dt>client</dt>
+   *   <dd>Tab switching is done on client, no server Request.</dd>
+   *   <dt>reloadPage</dt>
+   *   <dd>Tab switching is done by server request. Full page is reloaded.</dd>
+   *   <dt>reloadTab</dt>
+   *   <dd>Tab switching is done by server request. Only the Tab is reloaded.</dd>
+   * </dl>
+   * @param switchType Sets the switching type.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.model.SwitchType",
+      allowedValues = {SwitchType.CLIENT, SwitchType.RELOAD_PAGE, SwitchType.RELOAD_TAB},
+      defaultValue = SwitchType.CLIENT,
+      defaultCode = "org.apache.myfaces.tobago.model.SwitchType.client")
+  void setSwitchType(String switchType);
+
+  /**
+   *
+   * <strong>ValueBindingExpression</strong> pointing to a Integer to save the
+   * component's selected Tab.
+   *
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "0")
+  void setSelectedIndex(String selectedIndex);
+
+  /**
+   * For internal use. TBD: Check if this is needed any longer.
+   */
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "0")
+  void setRenderedIndex(String renderedIndex);
+
+  @TagAttribute  
+  @UIComponentTagAttribute(
+      type = {},
+      expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
+      methodSignature = "org.apache.myfaces.tobago.event.TabChangeEvent")
+  void setTabChangeListener(String listener);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabTagDeclaration.java
new file mode 100644
index 0000000..db2b778
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TabTagDeclaration.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasImage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIPanel;
+
+/**
+ * Renders a tab within a tab group.
+ */
+@Tag(name = "tab")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITab",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITab",
+    uiComponentFacesClass = "javax.faces.component.UIPanel",
+    interfaces = {
+        "javax.faces.component.NamingContainer",
+        "org.apache.myfaces.tobago.component.SupportsAccessKey"
+    },
+    componentFamily = UIPanel.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TAB,
+    facets = {
+        @Facet(name = Facets.BAR,
+            description = "Contains some code to be placed in the header at the bar position.")},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            isDefault = true)
+    })
+public interface TabTagDeclaration
+    extends HasIdBindingAndRendered, IsVisual, HasLabel, HasAccessKey, HasTip, IsDisabled, HasImage {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TextareaTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TextareaTagDeclaration.java
new file mode 100644
index 0000000..6ddab87
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TextareaTagDeclaration.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabelLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSanitize;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidator;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsFocus;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequired;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIInput;
+
+/**
+ * Renders a multi line text input control.
+ */
+@Tag(name = "textarea")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITextarea",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITextarea",
+    uiComponentFacesClass = "javax.faces.component.UIInput",
+    componentFamily = UIInput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TEXTAREA,
+    allowedChildComponenents = "NONE",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface TextareaTagDeclaration
+    extends HasIdBindingAndRendered, HasConverter, IsReadonly, IsDisabled, IsRequired, HasLabel, HasLabelLayout, HasTip,
+    HasAccessKey, HasValidator, HasValue, HasValueChangeListener, HasTabIndex, IsFocus, IsVisual,
+    HasValidatorMessage, HasConverterMessage, HasRequiredMessage, HasSanitize {
+
+  /**
+   * The row count for this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer")
+  void setRows(String rows);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeCommandTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeCommandTagDeclaration.java
new file mode 100644
index 0000000..523559e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeCommandTagDeclaration.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAccessKey;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAction;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasActionListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConfirmation;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLink;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTabIndex;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTarget;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabledBySecurity;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsImmediateCommand;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsOmit;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsTransition;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UICommand;
+
+/**
+ * Renders a command inside of a tree.
+ */
+@Tag(name = "treeCommand")
+@BodyContentDescription(anyTagOf = "facestag")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeCommand",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITreeCommand",
+    uiComponentFacesClass = "javax.faces.component.UICommand",
+    interfaces = {
+        "org.apache.myfaces.tobago.component.SupportsAccessKey"
+    },
+    componentFamily = UICommand.COMPONENT_FAMILY,
+    allowedChildComponenents = "NONE",
+    facets = {
+        @Facet(
+            name = Facets.CONFIRMATION,
+            description = "Contains a UIOutput instance with the confirmation message.",
+            allowedChildComponenents = "org.apache.myfaces.tobago.Out")},
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CLICK,
+            description = "Behavior of a click event.",
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK)
+    },
+    rendererType = RendererTypes.TREE_COMMAND)
+public interface TreeCommandTagDeclaration
+    extends HasIdBindingAndRendered, HasAction, HasActionListener, IsImmediateCommand, HasConfirmation,
+            HasLink, IsTransition, HasTarget, IsDisabledBySecurity,
+            IsOmit, HasLabel, HasAccessKey, HasTip, HasTabIndex, IsVisual {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeIconTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeIconTagDeclaration.java
new file mode 100644
index 0000000..e57d6a2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeIconTagDeclaration.java
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasAlt;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIGraphic;
+
+/**
+ * Renders an image beside a tree node.
+ */
+@Tag(name = "treeIcon")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeIcon",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUIImage",
+    uiComponentFacesClass = "javax.faces.component.UIGraphic",
+    componentFamily = UIGraphic.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_ICON,
+    allowedChildComponenents = "NONE")
+public interface TreeIconTagDeclaration extends HasIdBindingAndRendered, HasTip, IsDisabled, IsVisual, HasAlt {
+
+  /**
+   * Name of the icon.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setValue(String value);
+
+  /**
+   * Name of the folder icon, if not set "value" will be used.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setClosed(String closed);
+
+  /**
+   * Name of the open folder icon, if not set "closed" will be used.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setOpen(String open);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeIndentTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeIndentTagDeclaration.java
new file mode 100644
index 0000000..48ae4d3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeIndentTagDeclaration.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIGraphic;
+
+/**
+ * Renders an indent beside a tree node.
+ */
+@Tag(name = "treeIndent")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeIndent",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITreeIndent",
+    uiComponentFacesClass = "javax.faces.component.UIGraphic",
+    componentFamily = UIGraphic.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_INDENT,
+    allowedChildComponenents = "NONE")
+public interface TreeIndentTagDeclaration extends HasIdBindingAndRendered, HasTip, IsVisual {
+
+  /**
+   * Show the lines and icons which are defining the tree structure.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setShowJunctions(String showJunctions);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeLabelTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeLabelTagDeclaration.java
new file mode 100644
index 0000000..7caed9f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeLabelTagDeclaration.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIOutput;
+
+/**
+ * Renders a label inside of a tree.
+ */
+@Tag(name = "treeLabel")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeLabel",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUILabel",
+    uiComponentFacesClass = "javax.faces.component.UIOutput",
+    componentFamily = UIOutput.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_LABEL,
+    allowedChildComponenents = "NONE"
+)
+public interface TreeLabelTagDeclaration
+    extends HasIdBindingAndRendered, HasTip, IsVisual {
+
+  /**
+   * Text value to display as label.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setValue(String value);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java
new file mode 100644
index 0000000..b458ee8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeListboxTagDeclaration.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSize;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasVar;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequired;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.model.Selectable;
+
+import javax.faces.component.UIData;
+
+/**
+ * A tree data structure displayed as a set of list boxes.
+ */
+@Tag(name = "treeListbox")
+@BodyContentDescription(anyTagOf = "<tc:treeNode>|<tc:treeData>")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeListbox",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITreeListbox",
+    uiComponentFacesClass = "javax.faces.component.UIData",
+    componentFamily = UIData.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_LISTBOX,
+    allowedChildComponenents = {
+        "org.apache.myfaces.tobago.TreeNode",
+        "org.apache.myfaces.tobago.TreeData"
+    })
+public interface TreeListboxTagDeclaration
+    extends HasIdBindingAndRendered, HasValue, HasVar, IsVisual, IsRequired, HasSize {
+
+  /**
+   * Flag indicating whether or not this component should be render selectable items.
+   * Possible values are:
+   * <ul>
+   * <li><strong>single</strong> : a single section tree is rendered</li>
+   * <li><strong>multiLeafOnly</strong> : a multi section tree is rendered,
+   * only Leaf's are selectable</li>
+   * <li><strong>singleLeafOnly</strong> : a single section tree is rendered,
+   * only Leaf's are selectable</li>
+   * </ul>
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.Selectable",
+      defaultValue = Selectable.SINGLE,
+      allowedValues = {Selectable.SINGLE, Selectable.MULTI_LEAF_ONLY, Selectable.SINGLE_LEAF_ONLY},
+      defaultCode = "org.apache.myfaces.tobago.model.Selectable.single")
+  void setSelectable(String selectable);
+
+  /**
+   * <strong>ValueBindingExpression</strong> pointing to a object to save the
+   * component's state.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.TreeState",
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED,
+      generate = false)
+  void setState(String state);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeMenuTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeMenuTagDeclaration.java
new file mode 100644
index 0000000..ca56453
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeMenuTagDeclaration.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasVar;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsShowRoot;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIData;
+
+/**
+ * A tree which will be displayed like a flat menu.
+ * This menu is often used for navigation on the left side of an application.
+ */
+@Tag(name = "treeMenu")
+@BodyContentDescription(anyTagOf = "<tc:treeData>")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeMenu",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITreeMenu",
+    uiComponentFacesClass = "javax.faces.component.UIData",
+    componentFamily = UIData.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_MENU,
+    allowedChildComponenents = {
+        "org.apache.myfaces.tobago.TreeNode",
+        "org.apache.myfaces.tobago.TreeData"
+        })
+public interface TreeMenuTagDeclaration
+    extends HasIdBindingAndRendered, HasValue, HasVar, IsVisual,
+    IsShowRoot {
+
+  /**
+   *
+   * <strong>ValueBindingExpression</strong> pointing to a object to save the
+   * component's state.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.TreeState",
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED,
+      generate = false)
+  void setState(String state);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeNodeTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeNodeTagDeclaration.java
new file mode 100644
index 0000000..da09ba3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeNodeTagDeclaration.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIColumn;
+
+/**
+ * Creates a tree node. This component represents a single node inside a tree structure.
+ */
+@SuppressWarnings("ALL")
+@Tag(name = "treeNode")
+@BodyContentDescription(anyTagOf = "<tc:treeIndent>|<tc:treeIcon>|<tc:treeSelect>|<tc:treeLabel>|<tc:treeCommand>")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeNode",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITreeNode",
+    uiComponentFacesClass = "javax.faces.component.UIColumn",
+    componentFamily = UIColumn.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_NODE,
+    allowedChildComponenents = {
+        "org.apache.myfaces.tobago.TreeNode",
+        "org.apache.myfaces.tobago.TreeData"
+    })
+public interface TreeNodeTagDeclaration
+    extends HasIdBindingAndRendered, HasTip, IsDisabled, IsVisual {
+
+  @Deprecated
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", generate = false, defaultValue = "false")
+  void setSelected(String selected);
+
+  /**
+   * Method binding representing a expansionListener method that ....
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {},
+      generate = false,
+      expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
+      methodSignature = "org.apache.myfaces.tobago.event.TreeExpansionEvent")
+  void setTreeExpansionListener(String treeExpansionListener);
+
+/* TBD
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.layout.Measure")
+  void setWidth(String width);
+*/
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeSelectTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeSelectTagDeclaration.java
new file mode 100644
index 0000000..5a54b61
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeSelectTagDeclaration.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverter;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasConverterMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasLabel;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasRequiredMessageForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasTip;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValidatorMessage;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsRequiredForSelect;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UISelectBoolean;
+
+/**
+ * Makes a tree node selectable.
+ */
+@Tag(name = "treeSelect")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITreeSelect",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITreeSelect",
+    uiComponentFacesClass = "javax.faces.component.UISelectBoolean",
+    componentFamily = UISelectBoolean.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE_SELECT,
+    allowedChildComponenents = "NONE",
+    behaviors = {
+        @Behavior(
+            name = ClientBehaviors.CHANGE,
+            isDefault = true),
+        @Behavior(
+            name = ClientBehaviors.CLICK),
+        @Behavior(
+            name = ClientBehaviors.DBLCLICK),
+        @Behavior(
+            name = ClientBehaviors.FOCUS),
+        @Behavior(
+            name = ClientBehaviors.BLUR)
+    })
+public interface TreeSelectTagDeclaration
+    extends HasIdBindingAndRendered, HasLabel, HasTip, IsVisual, HasValue, HasValueChangeListener,
+    IsDisabled, IsRequiredForSelect, HasConverter,
+    HasValidatorMessage, HasRequiredMessageForSelect, HasConverterMessage {
+
+  /**
+   * Show a checkbox to visualize the selection state.
+   * This is useful to hide the checkbox, e. g. dependent of the type of the node.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setShowCheckbox(String showCheckbox);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeTagDeclaration.java
new file mode 100644
index 0000000..344f068
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/TreeTagDeclaration.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.BodyContentDescription;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasVar;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsShowRoot;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsShowRootJunction;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.model.Selectable;
+
+import javax.faces.component.UIData;
+
+/**
+ * A tree with classical look. 
+ * Usually used with icons and junction lines to open folder, etc.
+ */
+@Tag(name = "tree")
+@BodyContentDescription(anyTagOf = "<tc:treeData>")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UITree",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUITree",
+    uiComponentFacesClass = "javax.faces.component.UIData",
+    componentFamily = UIData.COMPONENT_FAMILY,
+    rendererType = RendererTypes.TREE,
+    allowedChildComponenents = {
+        "org.apache.myfaces.tobago.TreeNode",
+        "org.apache.myfaces.tobago.TreeData"
+        })
+public interface TreeTagDeclaration
+    extends HasIdBindingAndRendered, HasValue, HasVar, IsVisual,
+    IsShowRoot, IsShowRootJunction {
+
+  /**
+   * Flag indicating whether or not this component should be render selectable items.
+   * Possible values are:
+   * <ul>
+   * <li><strong>none</strong> : not selectable</li>
+   * <li><strong>multi</strong> : a multi section tree is rendered</li>
+   * <li><strong>single</strong> : a single section tree is rendered</li>
+   * <li><strong>multiLeafOnly</strong> : a multi section tree is rendered,
+   * only leaf's are selectable</li>
+   * <li><strong>singleLeafOnly</strong> : a single section tree is rendered,
+   * only leaf's are selectable</li>
+   * </ul>
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.Selectable",
+      defaultValue = Selectable.MULTI,
+      allowedValues = {
+          Selectable.NONE,
+          Selectable.MULTI,
+          Selectable.SINGLE,
+          Selectable.MULTI_LEAF_ONLY,
+          Selectable.SINGLE_LEAF_ONLY},
+      defaultCode = "org.apache.myfaces.tobago.model.Selectable.multi")
+  void setSelectable(String selectable);
+
+  /**
+   * <strong>ValueBindingExpression</strong> pointing to a object to save the
+   * component's state.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.model.TreeState",
+      expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED,
+      generate = false)
+  void setState(String state);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ValidateFileItemTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ValidateFileItemTagDeclaration.java
new file mode 100644
index 0000000..e2982cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ValidateFileItemTagDeclaration.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.ValidatorTag;
+import org.apache.myfaces.tobago.validator.FileItemValidator;
+
+import javax.el.ValueExpression;
+
+/**
+ * Register an {@link FileItemValidator} instance on the UIComponent
+ * associated with the closest parent UIComponent custom action.
+ */
+@Tag(name = "validateFileItem")
+@ValidatorTag(
+    validatorId = FileItemValidator.VALIDATOR_ID,
+    faceletHandler = "org.apache.myfaces.tobago.facelets.TobagoValidateHandler")
+public interface ValidateFileItemTagDeclaration {
+
+  @TagAttribute(name = "maxSize", type = "java.lang.Integer")
+  void setMaxSize(final ValueExpression maxSize);
+
+  @TagAttribute(name = "contentType", type = "java.lang.String")
+  void setContentType(final ValueExpression contentType);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ValidateSubmittedValueLengthTagDeclaration.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ValidateSubmittedValueLengthTagDeclaration.java
new file mode 100644
index 0000000..4e51c42
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/ValidateSubmittedValueLengthTagDeclaration.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.component;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.ValidatorTag;
+import org.apache.myfaces.tobago.validator.SubmittedValueLengthValidator;
+
+import javax.el.ValueExpression;
+
+/**
+ * Register an {@link SubmittedValueLengthValidator} instance on the UIComponent
+ * associated with the closest parent UIComponent custom action.
+ * The standard LengthValidator validate the length on the converted value.toString()
+ * not on the submitted value. Sometime you need to check the length of the submitted value.
+ */
+@Tag(name = "validateSubmittedValueLength")
+@ValidatorTag(validatorId = SubmittedValueLengthValidator.VALIDATOR_ID)
+public interface ValidateSubmittedValueLengthTagDeclaration {
+
+  @TagAttribute(name = "minimum", type = "java.lang.Integer")
+  void setMinimum(final ValueExpression minimum);
+
+  @TagAttribute(name = "maximum", type = "java.lang.Integer")
+  void setMaximum(final ValueExpression maximum);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/package-info.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/package-info.java
new file mode 100644
index 0000000..a8d1c7d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/component/package-info.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * <b>Tobago Framework Component Tag Library 3.0.x -
+ * (C) Copyright 2005-2017 The Apache Software Foundation</b>
+ */
+@org.apache.myfaces.tobago.apt.annotation.Taglib(
+    shortName = "tc",
+    uri = "http://myfaces.apache.org/tobago/component",
+    listener = {
+        "org.apache.myfaces.tobago.webapp.TobagoServletContextListener",
+        "org.apache.myfaces.tobago.webapp.SecretSessionListener"},
+    name = "tobago",
+    displayName = "Tobago Components 3.0.x")
+
+package org.apache.myfaces.tobago.internal.taglib.component;
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAccessKey.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAccessKey.java
new file mode 100644
index 0000000..d8be2af
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAccessKey.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasAccessKey {
+
+  /**
+   * The access key of this control.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.lang.Character"})
+  void setAccessKey(String key);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAction.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAction.java
new file mode 100644
index 0000000..715eb90
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAction.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasAction {
+  /**
+   * Action to invoke when clicked.
+   * This must be a MethodExpression or a String representing the application action to invoke when
+   * this component is activated by the user.
+   * The MethodBinding must evaluate to a public method that takes no parameters,
+   * and returns a String (the logical outcome) which is passed to the
+   * NavigationHandler for this application.
+   * The string is directly passed to the navigation handler.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {},
+      expression = DynamicExpression.METHOD_EXPRESSION,
+      methodReturnType = "java.lang.Object")
+  void setAction(String action);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasActionListener.java
new file mode 100644
index 0000000..06ec1b2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasActionListener.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasActionListener {
+  /**
+   * MethodExpression representing an action listener method that will be
+   * notified when this component is activated by the user.
+   * The expression must evaluate to a public method that takes an ActionEvent
+   * parameter, with a return type of void.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {},
+      expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
+      methodSignature = "javax.faces.event.ActionEvent")
+  void setActionListener(String actionListener);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAlt.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAlt.java
new file mode 100644
index 0000000..88d8d3f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAlt.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasAlt {
+  /**
+   * Alternate textual description of the image rendered by this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setAlt(String alt);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAutocomplete.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAutocomplete.java
new file mode 100644
index 0000000..5dfb561
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasAutocomplete.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasAutocomplete {
+
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setAutocomplete(String action);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasBinding.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasBinding.java
new file mode 100644
index 0000000..b7d37d3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasBinding.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasBinding {
+  /**
+   * The value binding expression linking this component to a property in a backing bean.
+   * For Facelets, the component is the outer UIPanel, not the input control.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "javax.faces.component.UIComponent")
+  void setBinding(String binding);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasCollapsedMode.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasCollapsedMode.java
new file mode 100644
index 0000000..66495f1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasCollapsedMode.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.model.CollapseMode;
+
+public interface HasCollapsedMode {
+
+  /**
+   * Enum indicating the mode of the collapsed state of this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+          type = "org.apache.myfaces.tobago.model.CollapseMode",
+          defaultValue = CollapseMode.NONE,
+          defaultCode = "org.apache.myfaces.tobago.model.CollapseMode.none")
+  void setCollapsedMode(String collapsed);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasColumnLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasColumnLayout.java
new file mode 100644
index 0000000..346d987
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasColumnLayout.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasColumnLayout {
+  /**
+   * This value defines the layout constraints for column layout.
+   * It is a semicolon separated list of layout tokens '[&lt;n&gt;]*', '&lt;n&gt;px' or 'auto'.
+   * Where &lt;n&gt; is a non negative integer and the square brackets means optional.
+   * Example: '2*;*;100px;auto'.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(defaultValue = "1*")
+  void setColumns(String columns);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConfirmation.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConfirmation.java
new file mode 100644
index 0000000..739b4b0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConfirmation.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasConfirmation {
+  /**
+   * Text to use as confirmation message.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setConfirmation(String confirmation);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConverter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConverter.java
new file mode 100644
index 0000000..a68239a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConverter.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasConverter {
+  /**
+   * An expression that specifies the Converter for this component.
+   * If the value binding expression is a String,
+   * the String is used as an ID to look up a Converter.
+   * If the value binding expression is a Converter,
+   * uses that instance as the converter.
+   * The value can either be a static value (ID case only)
+   * or an EL expression.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "javax.faces.convert.Converter",
+      expression = DynamicExpression.VALUE_EXPRESSION)
+  void setConverter(String converter);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConverterMessage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConverterMessage.java
new file mode 100644
index 0000000..41e51ed
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasConverterMessage.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+
+public interface HasConverterMessage {
+
+  /**
+   * An expression that specifies the converter message
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setConverterMessage(String converterMessage);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasFieldId.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasFieldId.java
new file mode 100644
index 0000000..32ea162
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasFieldId.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasFieldId {
+  /**
+   * The component identifier for the input field component inside of the container.
+   * This value must be unique within the closest parent component that is a naming container.
+   */
+  @TagAttribute(rtexprvalue = true)
+  @UIComponentTagAttribute
+  void setFieldId(String fieldId);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasFor.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasFor.java
new file mode 100644
index 0000000..d5f0705
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasFor.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasFor {
+  /**
+   * Id of the component, this is related to.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(expression = DynamicExpression.PROHIBITED)
+  void setFor(String forComponent);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasId.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasId.java
new file mode 100644
index 0000000..958eaa0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasId.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasId {
+  /**
+   * The component identifier for this component.
+   * This value must be unique within the closest parent component that is a naming container.
+   */
+  @TagAttribute(rtexprvalue = true)
+  @UIComponentTagAttribute(type = "java.lang.String")
+  void setId(String id);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasIdBindingAndRendered.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasIdBindingAndRendered.java
new file mode 100644
index 0000000..61f9de5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasIdBindingAndRendered.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+public interface HasIdBindingAndRendered extends HasId, HasBinding, IsRendered {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasImage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasImage.java
new file mode 100644
index 0000000..26cc18a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasImage.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasImage {
+  /**
+   * Url to an image to display.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setImage(String image);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasItemLabel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasItemLabel.java
new file mode 100644
index 0000000..ec82bae
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasItemLabel.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasItemLabel {
+  /**
+   * Label to be displayed to the user for this option.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setItemLabel(String itemLabel);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabel.java
new file mode 100644
index 0000000..702902e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabel.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasLabel {
+  /**
+   * A localized user presentable label for this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setLabel(String label);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabelLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabelLayout.java
new file mode 100644
index 0000000..f17856b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabelLayout.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasLabelLayout {
+
+  /**
+   * Defines the position of the label relative to the field.
+   * The default is flexLeft, if the label is set, or none, if the label isn't set.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.component.LabelLayout",
+      defaultCode = "getLabel() != null "
+          + "? org.apache.myfaces.tobago.component.LabelLayout.flexLeft "
+          + ": org.apache.myfaces.tobago.component.LabelLayout.none")
+  void setLabelLayout(String markup);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabelWidth.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabelWidth.java
new file mode 100644
index 0000000..6d7f2b2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLabelWidth.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasLabelWidth {
+  /**
+   * The width for the label component. Default: 'auto'.
+   * This value is used in the gridLayouts columns attribute.
+   * See gridLayout tag for valid values.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setLabelWidth(String width);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLink.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLink.java
new file mode 100644
index 0000000..3c49935
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasLink.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasLink {
+  /**
+   * Link to an arbitrary URL, either an internal link or an external link.
+
+   * <dl>
+   *   <dt>internal absolute link</dt>
+   *   <dd>Starts with a slash '/' character. The context path will be added.
+   *       A session id will be added, if needed.</dd>
+   *   <dt>external link</dt>
+   *   <dd>Starts with protocol followed by a colon ':' character.
+   *       The link will not be modified.</dd>
+   *   <dt>internal relative link</dt>
+   *   <dd>Any other strings. A session id will be added, if needed.</dd>
+   * </dl>
+   *
+   * @param link The external or internal link.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setLink(String link);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java
new file mode 100644
index 0000000..ee896cf
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasPlaceholder.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasPlaceholder {
+
+  /**
+   * <p>
+   * Displays a short text in the input field, that describes the meaning of this field.
+   * This is part of HTML 5, the theme should emulate the behaviour, when the browser doesn't support it.
+   * </p>
+   * <p>
+   * The text will not be displayed, when the input field is readonly or disabled.
+   * </p>
+   * @param placeholder The text to display
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setPlaceholder(String placeholder);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRenderRange.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRenderRange.java
new file mode 100644
index 0000000..ff074db
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRenderRange.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasRenderRange {
+  /**
+   * Range of items to render.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setRenderRange(String renderRange);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRequiredMessage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRequiredMessage.java
new file mode 100644
index 0000000..dd7992b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRequiredMessage.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+
+public interface HasRequiredMessage {
+  /**
+   * An expression that specifies the required message
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setRequiredMessage(String requiredMessage);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRequiredMessageForSelect.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRequiredMessageForSelect.java
new file mode 100644
index 0000000..933857a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRequiredMessageForSelect.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+
+public interface HasRequiredMessageForSelect {
+  /**
+   * An expression that specifies the required message
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setRequiredMessage(String requiredMessage);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRowLayout.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRowLayout.java
new file mode 100644
index 0000000..4e400b4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasRowLayout.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasRowLayout {
+  /**
+   * This value defines the layout constraints for row layout.
+   * It is a semicolon separated list of layout tokens '[&lt;n&gt;]*', '&lt;n&gt;px' or 'auto'.
+   * Where &lt;n&gt; is a non negative integer and the square brackets means optional.
+   * Example: '2*;*;100px;auto'.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(defaultValue = "1*")
+  void setRows(String rows);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSanitize.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSanitize.java
new file mode 100644
index 0000000..b9ecbc9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSanitize.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.sanitizer.SanitizeMode;
+
+public interface HasSanitize {
+  /**
+   * Should HTML content sanitized?
+   * The effect of sanitizing depends on the configuration.
+   * The value "auto" means, that sanitizing take place for
+   * <ul>
+   *   <li>tc:out when escape="false" or</li>
+   *   <li>tc:textarea when attribute data-html-editor is set,</li>
+   * </ul>
+   * because that are the critical parts.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.sanitizer.SanitizeMode",
+      defaultValue = SanitizeMode.AUTO,
+      allowedValues = {SanitizeMode.AUTO, SanitizeMode.NEVER},
+      defaultCode = "org.apache.myfaces.tobago.sanitizer.SanitizeMode.auto")
+  void setSanitize(String sanitize);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSize.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSize.java
new file mode 100644
index 0000000..276d26d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSize.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasSize {
+
+  /**
+   * The number of the shown rows in the element. E. g. the size attribute of the select element in HTML.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer")
+  void setSize(String size);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSpacing.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSpacing.java
new file mode 100644
index 0000000..7455a01
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasSpacing.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasSpacing {
+
+  /**
+   * Spacing between the columns in the actual layout.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.Measure",
+      defaultCode = "Measure.ZERO")
+  void setColumnSpacing(String columnSpacing);
+
+  /**
+   * Spacing between the rows in the actual layout.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.Measure",
+      defaultCode = "Measure.ZERO")
+  void setRowSpacing(String rowSpacing);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasState.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasState.java
new file mode 100644
index 0000000..e094ec8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasState.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasState {
+  /**
+   * <strong>ValueBindingExpression</strong> pointing to a object to save the
+   * component's state.
+   */
+  // TODO is Object right?
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "java.lang.Object", expression = DynamicExpression.VALUE_EXPRESSION_REQUIRED)
+  void setState(String state);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasStateBinding.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasStateBinding.java
new file mode 100644
index 0000000..48f594f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasStateBinding.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+
+public interface HasStateBinding {
+
+  @TagAttribute
+  void setStateBinding(String stateBinding);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTabChangeListenerType.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTabChangeListenerType.java
new file mode 100644
index 0000000..7494a0d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTabChangeListenerType.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasTabChangeListenerType {
+  /**
+   * Fully qualified Java class name of a TabChangeListener to be
+   * created and registered.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {"java.util.List", "java.util.Map", "java.lang.Object[]"})
+  void setType(String type);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTabIndex.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTabIndex.java
new file mode 100644
index 0000000..dddf8d6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTabIndex.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasTabIndex {
+
+  /**
+   * Controls the navigation of the focus through the
+   * input controls on a page with the Tab-Key.
+   * The navigation starts from the element with
+   * the lowest tabIndex value to the element with the highest value.
+   * Elements that have identical tabIndex values should be navigated
+   * in the order they appear in the character stream
+   * Elements that are disabled or with a negative tabIndex
+   * do not participate in the tabbing order.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Integer")
+  void setTabIndex(String tabIndex);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTarget.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTarget.java
new file mode 100644
index 0000000..15e21dc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTarget.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasTarget {
+  /**
+   * Name of a frame where the resource retrieved via this hyperlink is to be
+   * displayed.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setTarget(String target);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTip.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTip.java
new file mode 100644
index 0000000..ae951d1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasTip.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasTip {
+  /**
+   * Text value to display as tooltip.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute()
+  void setTip(String tip);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValidator.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValidator.java
new file mode 100644
index 0000000..0ebea59
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValidator.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasValidator {
+  /**
+   * A method binding EL expression,
+   * accepting FacesContext, UIComponent,
+   * and Object parameters, and returning void, that validates
+   * the component's local value.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = {},
+      expression = DynamicExpression.METHOD_EXPRESSION,
+      methodSignature = { "javax.faces.context.FacesContext", "javax.faces.component.UIComponent", "java.lang.Object" })
+  void setValidator(String validator);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValidatorMessage.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValidatorMessage.java
new file mode 100644
index 0000000..05c5ad5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValidatorMessage.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasValidatorMessage {
+
+  /**
+   * An expression that specifies the validator message
+   */
+  @TagAttribute
+  @UIComponentTagAttribute
+  void setValidatorMessage(String validatorMessage);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValue.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValue.java
new file mode 100644
index 0000000..592af47
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValue.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasValue {
+
+  /**
+   * The current value of this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.Object")
+  void setValue(String value);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValueChangeListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValueChangeListener.java
new file mode 100644
index 0000000..b48b22a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasValueChangeListener.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasValueChangeListener {
+  /**
+   * MethodExpression representing a value change listener method
+   * that will be notified when a new value has been set for this input component.
+   * The expression must evaluate to a public method that takes a ValueChangeEvent
+   * parameter, with a return type of void.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = {},
+      expression = DynamicExpression.METHOD_EXPRESSION_REQUIRED,
+      methodSignature = "javax.faces.event.ValueChangeEvent")
+  void setValueChangeListener(String valueChangeListener);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasVar.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasVar.java
new file mode 100644
index 0000000..49cd3d9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/HasVar.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface HasVar {
+
+  /**
+   * Name of a request-scope attribute under which the model data for the row
+   * selected by the current value of the "rowIndex" property
+   * (i.e. also the current value of the "rowData" property) will be exposed.
+   */
+  @TagAttribute(required = true)
+  @UIComponentTagAttribute(
+      expression = DynamicExpression.PROHIBITED)
+  void setVar(String var);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsCollapsed.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsCollapsed.java
new file mode 100644
index 0000000..9812fe9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsCollapsed.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsCollapsed {
+
+  /**
+   * Indicating the collapsed state of this component.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setCollapsed(String collapsed);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDefaultCommand.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDefaultCommand.java
new file mode 100644
index 0000000..1f8fc90
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDefaultCommand.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsDefaultCommand {
+  /**
+   * If true the command is executed as default -- for example if the
+   * user presses the enter key inside a related input field.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setDefaultCommand(String defaultCommand);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDisabled.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDisabled.java
new file mode 100644
index 0000000..30e8382
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDisabled.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsDisabled {
+  /**
+   * Flag indicating that this element is disabled.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setDisabled(String disabled);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDisabledBySecurity.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDisabledBySecurity.java
new file mode 100644
index 0000000..f20e378
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDisabledBySecurity.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsDisabledBySecurity {
+  /**
+   * Flag indicating that this element is disabled. If configured so in the tobago-config.xml the action will be
+   * checked for the annotations {@link javax.annotation.security.RolesAllowed},
+   * {@link javax.annotation.security.PermitAll} or {@link javax.annotation.security.DenyAll}.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", generate = false)
+  void setDisabled(String disabled);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDraggable.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDraggable.java
new file mode 100644
index 0000000..3172b89
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsDraggable.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+/**
+ * Warning: This class is stil in progress.
+ */
+public interface IsDraggable {
+
+  /**
+   * Draggable components are the source components of the drag-and-drop feature.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setDraggable(String draggable);
+
+  /**
+   * Indicate draggable of this component.
+   * Possible value is 'none'. But this can be overridden in the theme.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "java.lang.String[]")
+  void setDragNames(String draggable);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsFixed.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsFixed.java
new file mode 100644
index 0000000..43638d1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsFixed.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsFixed {
+  /**
+   * Flag indicating that this element is fixed on its position, e. g. it will not scroll with the
+   * neighbour elements.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setFixed(String fixed);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsFocus.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsFocus.java
new file mode 100644
index 0000000..6147bea
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsFocus.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsFocus {
+  /**
+   * Flag indicating this component should receive the focus.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setFocus(String focus);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsImmediateCommand.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsImmediateCommand.java
new file mode 100644
index 0000000..6cb282f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsImmediateCommand.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsImmediateCommand {
+
+  /**
+   * Flag indicating that, if this component is activated by the user,
+   * notifications should be delivered to interested listeners and actions
+   * immediately (that is, during Apply Request Values phase) rather than
+   * waiting until Invoke Application phase.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setImmediate(String immediate);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsInline.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsInline.java
new file mode 100644
index 0000000..94b471a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsInline.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsInline {
+  /**
+   * Flag indicating this component should rendered as an inline element.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setInline(String inline);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsMultiple.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsMultiple.java
new file mode 100644
index 0000000..3c4c1ce
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsMultiple.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsMultiple {
+
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setMultiple(String multiple);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsOmit.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsOmit.java
new file mode 100644
index 0000000..a97141c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsOmit.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsOmit {
+  /**
+   * Flag indicating that the action of this element, will not be executed from client side
+   * (e. g. when the user clicks a button.
+   * When setting this value to true, the action will not be executed by the Tobago, but it can executed
+   * by JavaScript.
+   * This attribute is useful, when you want to add JavaScript event handlers to commands manually.
+   * In this case you usually don't want a submit with a full reload of the page.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setOmit(String omit);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsPassword.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsPassword.java
new file mode 100644
index 0000000..20c234c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsPassword.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsPassword {
+
+  /**
+   * Flag indicating whether or not this component should be rendered as
+   * password field , so you will not see the typed charakters.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setPassword(String password);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsReadonly.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsReadonly.java
new file mode 100644
index 0000000..59bdb5d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsReadonly.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsReadonly {
+  /**
+   * Flag indicating that this component will prohibit changes by the user.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setReadonly(String readonly);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRendered.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRendered.java
new file mode 100644
index 0000000..0a80135
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRendered.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsRendered {
+  /**
+   * Flag indicating whether or not this component should be rendered
+   * (during Render Response Phase), or processed on any subsequent form submit.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(
+      type = "boolean",
+      defaultValue = "true")
+  void setRendered(String rendered);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRequired.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRequired.java
new file mode 100644
index 0000000..85c1413
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRequired.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsRequired {
+  /**
+   * Flag indicating that a value is required.
+   * If the value is an empty string a
+   * ValidationError occurs and a Error Message is rendered.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setRequired(String required);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRequiredForSelect.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRequiredForSelect.java
new file mode 100644
index 0000000..9aac147
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsRequiredForSelect.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsRequiredForSelect {
+  /**
+   * Flag indicating that a value is required.
+   * If the value is an empty string a
+   * ValidationError occurs and a Error Message is rendered.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setRequired(String required);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsShowRoot.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsShowRoot.java
new file mode 100644
index 0000000..d254e2a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsShowRoot.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsShowRoot {
+
+  /**
+   * Only applicable in the case that the data model is a tree.
+   * This flag indicates that the root node should be displayed.
+   * Often in tree structures the root node is special and should not be displayed.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setShowRoot(String showRoot);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsShowRootJunction.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsShowRootJunction.java
new file mode 100644
index 0000000..46d23b0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsShowRootJunction.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsShowRootJunction {
+
+  /**
+   * Only applicable in the case that the data model is a tree.
+   * This flag indicates that the root node should be displayed with an open-close-switch.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "false")
+  void setShowRootJunction(String showRootJunction);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsTransition.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsTransition.java
new file mode 100644
index 0000000..9998545
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsTransition.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsTransition {
+  /**
+   * Specify, if the command calls an JSF-Action.
+   * Useful to switch off the Double-Submit-Check and Waiting-Behavior.
+   *
+   * @param transition Indicates the transition.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean", defaultValue = "true")
+  void setTransition(String transition);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsVisual.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsVisual.java
new file mode 100644
index 0000000..d3333c0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/taglib/declaration/IsVisual.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.declaration;
+
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+
+public interface IsVisual {
+
+  /**
+   * For internal use. Used for rendering, if there is a child tag &lt;tc:style&gt;
+   */
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.renderkit.css.Style")
+  void setStyle(String style);
+
+  /**
+   * Sets a CSS class in its parent, if the parent supports it.
+   *
+   * Which this feature it is possible to put a CSS class name into a component with the &lt;tc:style&gt; tag. Example:
+   *
+   * <pre>
+   * &lt;tc:in&gt;
+   *   &lt;tc:style customClass="my-emphasized"/&gt;
+   * &lt;/tc:in&gt;
+   * </pre>
+   *
+   * One capability is, to used external CSS libs.
+   * <br>
+   * This feature should not be used imprudent.
+   * Because it might be unstable against changes in the renderered HTML code.
+   */
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.renderkit.css.CustomClass")
+  void setCustomClass(String customClass);
+
+  /**
+   * Indicate markup of this component.
+   * The allowed markups can be defined or overridden in the theme.
+   * The value 'none' should not be used any longer. Just leave the attribute empty, or use a NULL pointer.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "org.apache.myfaces.tobago.context.Markup")
+  void setMarkup(String markup);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/AccessKeyLogger.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/AccessKeyLogger.java
new file mode 100644
index 0000000..215b539
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/AccessKeyLogger.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class is for debugging the access keys.
+ */
+public final class AccessKeyLogger extends HashMap<Character, List<String>> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AccessKeyLogger.class);
+
+  private static final char[] KEYS = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+      'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+      'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'};
+
+  private AccessKeyLogger() {
+  }
+
+  private static AccessKeyLogger getInstance(final FacesContext facesContext) {
+    final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
+    AccessKeyLogger keyMap = (AccessKeyLogger) requestMap.get(AccessKeyLogger.class.getName());
+    if (keyMap == null) {
+      keyMap = new AccessKeyLogger();
+      requestMap.put(AccessKeyLogger.class.getName(), keyMap);
+    }
+    return keyMap;
+  }
+
+  public static void addAccessKey(final FacesContext facesContext, final Character key, String clientId) {
+    if (LOG.isDebugEnabled()) {
+      final AccessKeyLogger instance = getInstance(facesContext);
+      List<String> clientIds;
+      if (instance.containsKey(key)) {
+        clientIds = instance.get(key);
+      } else {
+        clientIds = new ArrayList<String>();
+        instance.put(key, clientIds);
+      }
+      clientIds.add(clientId);
+      // should only be called, when debug is enabled
+      LOG.debug("Using accessKey='{}' for clientId='{}'", key, clientId);
+    }
+  }
+
+  public static void logStatus(final FacesContext facesContext) {
+    if (LOG.isDebugEnabled()) {
+      final StringBuilder builder = new StringBuilder();
+      final AccessKeyLogger instance = AccessKeyLogger.getInstance(facesContext);
+      builder.append("Used access keys:");
+      for (Map.Entry<Character, List<String>> entry : instance.entrySet()) {
+        builder.append("\n'");
+        builder.append(entry.getKey());
+        builder.append("' -> ");
+        builder.append(entry.getValue());
+      }
+      builder.append("\nFree access keys: ");
+      for (final char key : KEYS) {
+        builder.append(instance.containsKey(Character.valueOf(key)) ? '.' : key);
+      }
+      LOG.debug(builder.toString());
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ArrayUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ArrayUtils.java
new file mode 100644
index 0000000..1c1a049
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ArrayUtils.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+public class ArrayUtils {
+
+  public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+  public static boolean contains(final String[] array, final String markup) {
+    for (final String anArray : array) {
+      if (markup.equals(anArray)) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/AuthorizationHelper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/AuthorizationHelper.java
new file mode 100644
index 0000000..26282f4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/AuthorizationHelper.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.security.DenyAll;
+import javax.annotation.security.PermitAll;
+import javax.annotation.security.RolesAllowed;
+import javax.enterprise.inject.spi.Bean;
+import javax.enterprise.inject.spi.BeanManager;
+import javax.faces.bean.ManagedBean;
+import javax.faces.context.FacesContext;
+import javax.naming.InitialContext;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/* The JSF annotations are, because it has to be runnable without CDI */
+@ManagedBean
+@javax.faces.bean.ApplicationScoped
+public class AuthorizationHelper {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AuthorizationHelper.class);
+
+  public static final String AUTHORIZATION_HELPER = "authorizationHelper";
+
+  private static final Pattern PATTERN = Pattern.compile("#\\{(\\w+(?:\\.\\w+)*)\\.(\\w+)(?:\\(.*\\))?\\}");
+
+  private static final Annotation NULL_VALUE = new Annotation() {
+    @Override
+    public Class<? extends Annotation> annotationType() {
+      return null;
+    }
+
+    @Override
+    public String toString() {
+      return "(NULL)";
+    }
+  };
+
+  private final Map<String, Object> cache = new ConcurrentHashMap<String, Object>();
+
+  private BeanManager beanManager;
+
+  public AuthorizationHelper() {
+
+    // XXX this is easier with CDI 1.1
+    // beanManager = CDI.context().getBeanManager();
+
+    try {
+      final InitialContext context = new InitialContext();
+      beanManager = (BeanManager) context.lookup("java:comp/BeanManager");
+    } catch (Exception exception) {
+      LOG.warn("Can't obtain 'java:comp/BeanManager'", exception);
+    }
+
+    if (beanManager == null) {
+      // this works with Jetty 9
+      beanManager = (BeanManager)
+          FacesContext.getCurrentInstance().getExternalContext().getApplicationMap().get(BeanManager.class.getName());
+    }
+
+    LOG.info("Using bean manager: '{}'", beanManager);
+  }
+
+  public static AuthorizationHelper getInstance(final FacesContext facesContext) {
+    return (AuthorizationHelper)
+        facesContext.getELContext().getELResolver().getValue(facesContext.getELContext(), null, AUTHORIZATION_HELPER);
+  }
+
+  public boolean isAuthorized(final FacesContext facesContext, final String expression) {
+
+    final Annotation securityAnnotation = getSecurityAnnotation(facesContext, expression);
+    if (securityAnnotation == null) {
+      return true;
+    }
+
+    if (securityAnnotation instanceof DenyAll) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("DenyAll");
+      }
+      return false;
+    }
+    if (securityAnnotation instanceof RolesAllowed) {
+      final String[] roles = ((RolesAllowed) securityAnnotation).value();
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("RolesAllowed " + Arrays.asList(((RolesAllowed) securityAnnotation).value()));
+      }
+      for (final String role : roles) {
+        final boolean authorised = facesContext.getExternalContext().isUserInRole(role);
+        if (authorised) {
+          return true;
+        }
+      }
+      return false;
+    }
+    if (securityAnnotation instanceof PermitAll) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("PermitAll");
+      }
+      return true;
+    }
+    return true;
+  }
+
+  private Annotation getSecurityAnnotation(final FacesContext facesContext, String expression) {
+    if (cache.containsKey(expression)) {
+      final Object obj = cache.get(expression);
+      if (obj instanceof Annotation) {
+        return (Annotation) obj;
+      }
+      return null;
+    } else {
+      Annotation securityAnnotation = null;
+      final Matcher matcher = PATTERN.matcher(expression);
+      if (matcher.matches()) {
+        final String beanString = matcher.group(1);
+        final String methodString = matcher.group(2);
+
+        Object bean = null;
+
+        if (beanManager != null) { // CDI case
+          for (Bean<?> entry : beanManager.getBeans(beanString)) {
+            if (bean == null) {
+              bean = entry;
+            } else {
+              LOG.warn("Bean name ambiguous: '{}'", beanString);
+            }
+          }
+
+        } else { // JSF case
+          bean = facesContext.getELContext().getELResolver().getValue(facesContext.getELContext(), null, beanString);
+        }
+
+        if (bean != null) {
+          // try first from method
+          final List<Method> methods = findMethods(bean, methodString);
+          switch (methods.size()) {
+            case 0:
+              LOG.error("No Method '" + methodString + "' in class " + bean.getClass());
+              break;
+            case 1:
+              securityAnnotation = getSecurityAnnotations(methods.get(0));
+              break;
+            default:
+              LOG.warn("Method name ambiguous '" + methodString + "' in class " + bean.getClass()
+                  + ". Found " + methods.size() + " but only 1 is supported, yet.");
+          }
+          // if not set, try from class
+          if (securityAnnotation == null) {
+            securityAnnotation = getSecurityAnnotations(bean.getClass());
+          }
+        }
+      }
+      if (securityAnnotation == null) {
+        securityAnnotation = NULL_VALUE;
+      }
+
+      cache.put(expression, securityAnnotation);
+      if (LOG.isInfoEnabled()) {
+        LOG.info("Security annotation '{}' saved for expression '{}'", securityAnnotation, expression);
+      }
+
+      return securityAnnotation;
+    }
+  }
+
+  private Annotation getSecurityAnnotations(final AnnotatedElement annotatedElement) {
+    Annotation annotation = annotatedElement.getAnnotation(RolesAllowed.class);
+    if (annotation != null) {
+      return annotation;
+    }
+    annotation = annotatedElement.getAnnotation(DenyAll.class);
+    if (annotation != null) {
+      return annotation;
+    }
+    annotation = annotatedElement.getAnnotation(PermitAll.class);
+    if (annotation != null) {
+      return annotation;
+    }
+    return null;
+  }
+
+  private List<Method> findMethods(Object bean, String name) {
+    final Class clazz;
+    if (bean instanceof Bean) {
+      clazz = ((Bean) bean).getBeanClass();
+    } else {
+      clazz = bean.getClass();
+    }
+
+    final Method[] methods = clazz.getMethods();
+    final List<Method> result = new ArrayList<Method>();
+    for (Method method : methods) {
+      if (method.getName().equals(name)) {
+        result.add(method);
+      }
+    }
+    return result;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ContentType.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ContentType.java
new file mode 100644
index 0000000..648817a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ContentType.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+public class ContentType {
+  private String primaryType;
+  private String subType;
+
+  public ContentType(final String contentType) {
+    parse(contentType);
+  }
+
+  private void parse(final String contentType) {
+    // TODO parse Parameter
+    final String[] values = StringUtils.split(contentType, "/");
+    if (values.length == 2) {
+      primaryType = values[0];
+      subType = values[1];
+    } else {
+      throw new IllegalArgumentException("ContentType '" + contentType + "' not recognized.");
+    }
+  }
+
+  public String getPrimaryType() {
+    return primaryType;
+  }
+
+  public String getSubType() {
+    return subType;
+  }
+
+  public boolean match(final ContentType contentType) {
+    return primaryType.equalsIgnoreCase(contentType.getPrimaryType())
+        && ("*".equals(subType) || subType.equalsIgnoreCase(contentType.getSubType()));
+  }
+
+  public String toString() {
+    return primaryType + "/" + subType;
+  }
+
+  public static ContentType valueOf(final String s) {
+    return new ContentType(s);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/CookieUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/CookieUtils.java
new file mode 100644
index 0000000..b37dcf1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/CookieUtils.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class CookieUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CookieUtils.class);
+
+  private static final String THEME_PARAMETER = "tobago.theme";
+
+  private static final int ONE_YEAR_IN_SECONDS = 365 * 24 * 60 * 60;
+
+  private CookieUtils() {
+  }
+
+  public static String getThemeNameFromCookie(HttpServletRequest request) {
+    String themeName = null;
+    final Cookie[] cookies = request.getCookies();
+    if (cookies != null) {
+      for (Cookie cookie : cookies) {
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("cookie name  ='{}'", cookie.getName());
+          LOG.debug("cookie value ='{}'", cookie.getValue());
+          LOG.debug("cookie path  ='{}'", cookie.getPath());
+        }
+        if (THEME_PARAMETER.equals(cookie.getName())) {
+          themeName = cookie.getValue();
+          if (LOG.isDebugEnabled()) {
+            LOG.debug("theme from cookie {}='{}'", THEME_PARAMETER, themeName);
+          }
+          break;
+        }
+      }
+    }
+    return themeName;
+  }
+
+  public static void setThemeNameToCookie(
+      HttpServletRequest request, HttpServletResponse response, String themeName) {
+
+    String path = request.getContextPath();
+    path = StringUtils.isBlank(path) ? "/" : path;
+    boolean found = false;
+    final Cookie[] cookies = request.getCookies();
+    if (cookies != null) {
+      for (Cookie cookie : cookies) {
+        if (THEME_PARAMETER.equals(cookie.getName())) {
+          if (found) {
+            if (LOG.isDebugEnabled()) {
+              LOG.debug("Found more than one cookie {}, try to remove them...", THEME_PARAMETER);
+            }
+            cookie.setMaxAge(0);
+          } else {
+            found = true;
+            if (StringUtils.notEquals(cookie.getValue(), themeName)) {
+              if (LOG.isDebugEnabled()) {
+                LOG.debug("update theme {} -> {}", cookie.getValue(), themeName);
+              }
+              cookie.setValue(themeName);
+            }
+            if (StringUtils.notEquals(cookie.getPath(), path)) {
+              if (LOG.isDebugEnabled()) {
+                LOG.debug("update path  {} -> {}", cookie.getPath(), path);
+              }
+              cookie.setPath(path);
+            }
+            cookie.setMaxAge(ONE_YEAR_IN_SECONDS);
+          }
+          response.addCookie(cookie);
+        }
+      }
+    }
+    if (!found) {
+      Cookie cookie = new Cookie(THEME_PARAMETER, themeName);
+      cookie.setPath(path);
+      cookie.setMaxAge(ONE_YEAR_IN_SECONDS);
+      response.addCookie(cookie);
+    }
+  }
+
+/*
+  public static void removeThemeNameCookie(
+      HttpServletRequest request, HttpServletResponse response) {
+
+    String path = request.getContextPath();
+    path = StringUtils.isBlank(path) ? "/" : path;
+    final Cookie[] cookies = request.getCookies();
+    for (Cookie cookie : cookies) {
+      if (THEME_PARAMETER.equals(cookie.getName())) {
+        cookie.setMaxAge(0);
+        response.addCookie(cookie);
+      }
+    }
+  }
+*/
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/DateFormatUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/DateFormatUtils.java
new file mode 100644
index 0000000..49f69fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/DateFormatUtils.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import javax.faces.convert.ConverterException;
+import javax.faces.convert.DateTimeConverter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Locale;
+
+/**
+ * This code is taken from myfaces core.
+ * TODO: Should be sharable (e.g. myfaces-commons).
+ */
+public final class DateFormatUtils {
+
+  private static final String TYPE_DATE = "date";
+  private static final String TYPE_TIME = "time";
+  private static final String TYPE_BOTH = "both";
+  private static final String STYLE_DEFAULT = "default";
+  private static final String STYLE_MEDIUM = "medium";
+  private static final String STYLE_SHORT = "short";
+  private static final String STYLE_LONG = "long";
+  private static final String STYLE_FULL = "full";
+
+  private DateFormatUtils() {
+  }
+
+  /**
+   * Find a pattern for the converter.
+   * Returns the pattern inside the converter, if any.
+   * Otherwise compute the pattern.
+   *
+   * @return the patter or null, if DateFormat.getDateInstance() returns no SimpleDateFormat.
+   */
+  public static String findPattern(final DateTimeConverter converter) {
+    String pattern = converter.getPattern();
+
+    if (pattern == null) {
+      final DateFormat dateFormat = getDateFormat(
+          converter.getType(), converter.getDateStyle(),
+          converter.getTimeStyle(), converter.getLocale());
+      if (dateFormat instanceof SimpleDateFormat) {
+        final SimpleDateFormat format = (SimpleDateFormat) dateFormat;
+        pattern = format.toPattern();
+      }
+    }
+
+    return pattern;
+  }
+
+  private static DateFormat getDateFormat(
+      final String type, final String dateStyle, final String timeStyle, final Locale locale) {
+    final DateFormat format;
+    if (type.equals(TYPE_DATE)) {
+      format = DateFormat.getDateInstance(calcStyle(dateStyle), locale);
+    } else if (type.equals(TYPE_TIME)) {
+      format = DateFormat.getTimeInstance(calcStyle(timeStyle), locale);
+    } else if (type.equals(TYPE_BOTH)) {
+      format = DateFormat.getDateTimeInstance(calcStyle(dateStyle),
+          calcStyle(timeStyle),
+          locale);
+    } else {
+      throw new ConverterException("invalid type '" + type + "'");
+    }
+
+    // format cannot be lenient (JSR-127)
+    format.setLenient(false);
+    return format;
+  }
+
+  private static int calcStyle(final String name) {
+    if (name.equals(STYLE_DEFAULT)) {
+      return DateFormat.DEFAULT;
+    }
+    if (name.equals(STYLE_MEDIUM)) {
+      return DateFormat.MEDIUM;
+    }
+    if (name.equals(STYLE_SHORT)) {
+      return DateFormat.SHORT;
+    }
+    if (name.equals(STYLE_LONG)) {
+      return DateFormat.LONG;
+    }
+    if (name.equals(STYLE_FULL)) {
+      return DateFormat.FULL;
+    }
+
+    throw new ConverterException("invalid style '" + name + "'");
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/Deprecation.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/Deprecation.java
new file mode 100644
index 0000000..f66f297
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/Deprecation.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public final class Deprecation {
+
+  // to prevent instantiation
+  private Deprecation() {
+  }
+
+  /**
+   * This Logger object should help to detect the usage of deprecated code.
+   * The main reason for this class is the lack of a "deprecated concept"
+   * for tag libraries. Thought the designer of a Tobago page cannot see
+   * in his IDE that a tag or attribute is deprecated.
+   * <p>
+   * The Tobago Java code will log into this Logger object, with
+   * <dl>
+   *   <dt><code>error</code></dt>
+   *   <dd>when the code is deprecated with a loss of function, or</dd>
+   *   <dt><code>warn</code></dt>
+   *   <dd>when the code is deprecated, but still works.</dd>
+   * </dl>
+   * <p>
+   * This Logger category can be switched off, in production environment without
+   * affecting the normal logging category.
+   */
+  public static final Logger LOG = LoggerFactory.getLogger(Deprecation.class);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/FacesContextUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/FacesContextUtils.java
new file mode 100644
index 0000000..b278d68
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/FacesContextUtils.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.commons.collections.list.SetUniqueList;
+import org.apache.commons.collections.set.ListOrderedSet;
+
+import javax.faces.context.FacesContext;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+@SuppressWarnings("unchecked")
+public final class FacesContextUtils {
+
+  private static final String TOBAGO_ENCTYPE = "org.apache.myfaces.tobago.enctype";
+  private static final String TOBAGO_SCRIPT_FILES = "org.apache.myfaces.tobago.scriptFiles";
+  private static final String TOBAGO_STYLE_FILES = "org.apache.myfaces.tobago.styleFiles";
+  private static final String TOBAGO_FOCUS_ID = "org.apache.myfaces.tobago.focusId";
+
+  private FacesContextUtils() {
+  }
+
+  public static void setFocusId(final FacesContext context, final String focusId) {
+    context.getAttributes().put(TOBAGO_FOCUS_ID, focusId);
+  }
+
+  public static String getFocusId(final FacesContext context) {
+    return (String) context.getAttributes().get(TOBAGO_FOCUS_ID);
+  }
+
+  public static String getEnctype(final FacesContext context) {
+    return (String) context.getAttributes().get(TOBAGO_ENCTYPE);
+  }
+
+  public static void setEnctype(final FacesContext context, final String enctype) {
+    context.getAttributes().put(TOBAGO_ENCTYPE, enctype);
+  }
+
+  public static List<String> getScriptFiles(final FacesContext context) {
+    final List<String> list = (List<String>) context.getAttributes().get(TOBAGO_SCRIPT_FILES);
+    if (list == null) {
+      return Collections.emptyList();
+    }
+    return list;
+  }
+  
+  public static void addScriptFile(final FacesContext context, final String file) {
+    List<String> list = (List<String>) context.getAttributes().get(TOBAGO_SCRIPT_FILES);
+    if (list == null) {
+      list = SetUniqueList.decorate(new ArrayList());
+      context.getAttributes().put(TOBAGO_SCRIPT_FILES, list);
+    }
+    list.add(file);
+  }
+
+  public static Set<String> getStyleFiles(final FacesContext context) {
+    final Set<String> set = (Set<String>) context.getAttributes().get(TOBAGO_STYLE_FILES);
+    if (set == null) {
+      return Collections.emptySet();
+    }
+    return set;
+  }
+
+  public static void addStyleFile(final FacesContext context, final String script) {
+    Set<String> set = (Set<String>) context.getAttributes().get(TOBAGO_STYLE_FILES);
+    if (set == null) {
+      set = new ListOrderedSet();
+      context.getAttributes().put(TOBAGO_STYLE_FILES, set);
+    }
+    set.add(script);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/FastStringWriter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/FastStringWriter.java
new file mode 100644
index 0000000..1c2494c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/FastStringWriter.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public class FastStringWriter extends Writer {
+
+  private StringBuilder stringBuilder;
+
+  public FastStringWriter() {
+    this(1024);
+  }
+
+  public FastStringWriter(final int initialSize) {
+    stringBuilder = new StringBuilder(initialSize);
+  }
+
+  @Override
+  public void write(final int c) {
+    stringBuilder.append((char) c);
+  }
+
+  @Override
+  public void write(final char[] cbuf, final int off, final int len) {
+    stringBuilder.append(cbuf, off, len);
+  }
+
+  @Override
+  public void write(final String str) {
+    stringBuilder.append(str);
+  }
+
+  @Override
+  public void write(final String str, final int off, final int len) {
+    stringBuilder.append(str.substring(off, off + len));
+  }
+
+  public String toString() {
+    return stringBuilder.toString();
+  }
+
+  @Override
+  public void flush() {
+    // do nothing
+  }
+
+  @Override
+  public void close() throws IOException {
+    // do nothing
+  }
+
+  public StringBuilder getBuilder() {
+    return stringBuilder;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlRendererUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlRendererUtils.java
new file mode 100644
index 0000000..7d070fb
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlRendererUtils.java
@@ -0,0 +1,272 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterWrapper;
+import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.FontAwesomeIconEncoder;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.model.SelectItem;
+import javax.faces.model.SelectItemGroup;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Locale;
+import java.util.Map;
+
+public final class HtmlRendererUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(HtmlRendererUtils.class);
+  private static final String ERROR_FOCUS_KEY = HtmlRendererUtils.class.getName() + ".ErrorFocusId";
+  private static final String FOCUS_KEY = HtmlRendererUtils.class.getName() + ".FocusId";
+  public static final String CHAR_NON_BEAKING_SPACE = "\u00a0";
+
+  private HtmlRendererUtils() {
+    // to prevent instantiation
+  }
+
+  public static void renderFocus(
+      final String clientId, final boolean focus, final boolean error, final FacesContext facesContext,
+      final TobagoResponseWriter writer) throws IOException {
+    final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
+    if (!requestMap.containsKey(FOCUS_KEY)
+        && (clientId.equals(FacesContextUtils.getFocusId(facesContext)) || focus || error)) {
+      requestMap.put(FOCUS_KEY, Boolean.TRUE);
+      writer.writeAttribute(HtmlAttributes.AUTOFOCUS, true);
+    }
+  }
+
+  public static String getRendererName(final FacesContext facesContext, final UIComponent component) {
+    final String rendererType = component.getRendererType();
+    return rendererType.substring(0, 1).toLowerCase(Locale.ENGLISH) + rendererType.substring(1);
+  }
+
+  public static void writeLabelWithAccessKey(final TobagoResponseWriter writer, final LabelWithAccessKey label)
+      throws IOException {
+    final int pos = label.getPos();
+    final String text = label.getLabel();
+    if (text != null) {
+      if (pos == -1) {
+        writer.writeText(text);
+      } else {
+        writer.writeText(text.substring(0, pos));
+        writer.startElement(HtmlElements.U);
+        writer.writeText(Character.toString(text.charAt(pos)));
+        writer.endElement(HtmlElements.U);
+        writer.writeText(text.substring(pos + 1));
+      }
+    }
+  }
+
+  public static void encodeIconWithLabel(TobagoResponseWriter writer, String image, String label) throws IOException {
+    if (image != null && image.startsWith("fa-")) { // XXX hack: should be integrated in the resource manager
+      writer.writeIcon(null, FontAwesomeIconEncoder.generateClass(image)); // todo: should not be static
+    }
+    if (label != null) {
+      writer.startElement(HtmlElements.SPAN);
+      writer.writeText(label);
+      writer.endElement(HtmlElements.SPAN);
+    }
+  }
+
+  public static void encodeIconWithLabel(
+       TobagoResponseWriter writer, FacesContext facesContext, String image, LabelWithAccessKey label, boolean disabled)
+      throws IOException {
+    if (image != null) {
+      if (image.startsWith("fa-")) {
+        writer.writeIcon(null, FontAwesomeIconEncoder.generateClass(image)); // todo: should not be static
+      } else {
+        writer.startElement(HtmlElements.IMG);
+        writer.writeAttribute(HtmlAttributes.SRC, image, true);
+        writer.writeAttribute(HtmlAttributes.ALT, "", false);
+        writer.endElement(HtmlElements.IMG);
+      }
+    }
+
+    if (label.getLabel() != null) {
+      writer.startElement(HtmlElements.SPAN);
+      HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
+      writer.endElement(HtmlElements.SPAN);
+    }
+  }
+
+  /**
+   * @deprecated since 3.0.0, use {@link org.apache.myfaces.tobago.renderkit.RendererBase#getResponseWriter}
+   */
+  public static TobagoResponseWriter getTobagoResponseWriter(final FacesContext facesContext) {
+
+    final ResponseWriter writer = facesContext.getResponseWriter();
+    if (writer instanceof TobagoResponseWriter) {
+      return (TobagoResponseWriter) writer;
+    } else {
+      return new TobagoResponseWriterWrapper(writer);
+    }
+  }
+
+  public static String getTitleFromTipAndMessages(final FacesContext facesContext, final UIComponent component) {
+    final String messages = ComponentUtils.getFacesMessageAsString(facesContext, component);
+    return HtmlRendererUtils.addTip(messages, ComponentUtils.getAttribute(component, Attributes.tip));
+  }
+
+  public static String addTip(String title, final Object tip) {
+    if (tip != null) {
+      if (title != null && title.length() > 0) {
+        title += " :: ";
+      } else {
+        title = "";
+      }
+      title += tip;
+    }
+    return title;
+  }
+
+  /**
+   * @deprecated Since Tobago 2.0.7
+   */
+  @Deprecated
+  public static void renderSelectItems(final UIInput component, final Iterable<SelectItem> items, final Object[] values,
+      final TobagoResponseWriter writer, final FacesContext facesContext) throws IOException {
+    renderSelectItems(component, items, values, null, null, writer, facesContext);
+  }
+
+  public static void renderSelectItems(final UIInput component, final Iterable<SelectItem> items, final Object[] values,
+      final String[] submittedValues, final TobagoResponseWriter writer, final FacesContext facesContext)
+      throws IOException {
+    renderSelectItems(component, items, values, submittedValues, null, writer, facesContext);
+  }
+
+  public static void renderSelectItems(final UIInput component, final Iterable<SelectItem> items, final Object value,
+      final String submittedValue, final TobagoResponseWriter writer, final FacesContext facesContext)
+      throws IOException {
+    renderSelectItems(component, items, value != null ? new Object[] {value}: null,
+        submittedValue != null ?  new String[] {submittedValue}: null, null, writer, facesContext);
+  }
+
+  public static void renderSelectItems(final UIInput component, final Iterable<SelectItem> items, final Object[] values,
+      final String[] submittedValues, final Boolean onlySelected, final TobagoResponseWriter writer,
+      final FacesContext facesContext) throws IOException {
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("component id = '{}'", component.getId());
+      LOG.debug("values = '{}'", Arrays.toString(values));
+      LOG.debug("submittedValues = '{}'", Arrays.toString(submittedValues));
+    }
+    for (final SelectItem item : items) {
+      if (item instanceof SelectItemGroup) {
+        writer.startElement(HtmlElements.OPTGROUP);
+        writer.writeAttribute(HtmlAttributes.LABEL, item.getLabel(), true);
+        if (item.isDisabled()) {
+          writer.writeAttribute(HtmlAttributes.DISABLED, true);
+        }
+        final SelectItem[] selectItems = ((SelectItemGroup) item).getSelectItems();
+        renderSelectItems(component, Arrays.asList(selectItems), values, submittedValues,
+            onlySelected, writer, facesContext);
+        writer.endElement(HtmlElements.OPTGROUP);
+      } else {
+
+        Object itemValue = item.getValue();
+        // when using selectItem tag with a literal value: use the converted value
+        if (itemValue instanceof String && values != null && values.length > 0 && !(values[0] instanceof String)) {
+          itemValue = ComponentUtils.getConvertedValue(facesContext, component, (String) itemValue);
+        }
+        final String formattedValue = ComponentUtils.getFormattedValue(facesContext, component, itemValue);
+        boolean contains;
+        if (submittedValues == null) {
+          contains = RenderUtils.contains(values, itemValue);
+        } else {
+          contains = RenderUtils.contains(submittedValues, formattedValue);
+        }
+        if (onlySelected != null) {
+          if (onlySelected) {
+            if (!contains) {
+              continue;
+            }
+          } else {
+            if (contains) {
+              continue;
+            }
+          }
+        }
+        writer.startElement(HtmlElements.OPTION);
+        writer.writeAttribute(HtmlAttributes.VALUE, formattedValue, true);
+        if (item instanceof org.apache.myfaces.tobago.model.SelectItem) {
+          final String image = ((org.apache.myfaces.tobago.model.SelectItem) item).getImage();
+          if (image != null) {
+            final Style style = new Style();
+            style.setBackgroundImage("url('" + image + "')");
+            writer.writeStyleAttribute(style);
+          }
+        }
+        Markup markup = item instanceof Visual ? ((Visual) item).getMarkup() : Markup.NULL;
+        if (onlySelected == null && contains) {
+          writer.writeAttribute(HtmlAttributes.SELECTED, true);
+          markup = Markup.SELECTED.add(markup);
+        }
+        if (item.isDisabled()) {
+          writer.writeAttribute(HtmlAttributes.DISABLED, true);
+          markup = Markup.DISABLED.add(markup);
+        }
+        writer.writeClassAttribute(Classes.create(component, "option", markup));
+
+        writer.writeText(item.getLabel());
+        writer.endElement(HtmlElements.OPTION);
+      }
+    }
+  }
+
+  public static void writeDataAttributes(
+      final FacesContext context, final TobagoResponseWriter writer, final UIComponent component)
+      throws IOException {
+
+    final Map<Object, Object> dataAttributes = ComponentUtils.getDataAttributes(component);
+    if (dataAttributes == null) {
+      return;
+    }
+
+    final ELContext elContext = context.getELContext();
+
+    for (final Map.Entry<Object, Object> entry : dataAttributes.entrySet()) {
+      final Object mapKey = entry.getKey();
+      final String name = mapKey instanceof ValueExpression
+          ? ((ValueExpression) mapKey).getValue(elContext).toString() : mapKey.toString();
+      final Object mapValue = entry.getValue();
+      final String value = mapValue instanceof ValueExpression
+          ? ((ValueExpression) mapValue).getValue(elContext).toString() : mapValue.toString();
+      writer.writeAttribute(DataAttributes.dynamic(name), value, true);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlWriterUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlWriterUtils.java
new file mode 100644
index 0000000..8fe8206
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HtmlWriterUtils.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public final class HtmlWriterUtils extends WriterUtils {
+
+  private static final char[][] CHARS_TO_ESCAPE;
+
+  static {
+    // init lookup table
+    CHARS_TO_ESCAPE = new char[0xA0][];
+
+    for (int i = 0; i < 0x20; i++) {
+      CHARS_TO_ESCAPE[i] = EMPTY; // Control characters
+    }
+
+    CHARS_TO_ESCAPE['\t'] = "&#x09;".toCharArray(); // Horizontal tabulator
+    CHARS_TO_ESCAPE['\n'] = "&#x0a;".toCharArray(); // Line feed
+    CHARS_TO_ESCAPE['\r'] = "&#x0d;".toCharArray(); // Carriage return
+
+    CHARS_TO_ESCAPE['\''] = "&#x27;".toCharArray();
+    CHARS_TO_ESCAPE['\"'] = "&quot;".toCharArray();
+    CHARS_TO_ESCAPE['&'] = "&amp;".toCharArray();
+    CHARS_TO_ESCAPE['<'] = "&lt;".toCharArray();
+    CHARS_TO_ESCAPE['>'] = "&gt;".toCharArray();
+    CHARS_TO_ESCAPE['/'] = "&#x2F;".toCharArray();
+
+    CHARS_TO_ESCAPE[0x7F] = EMPTY; // Delete
+
+    for (int i = 0x80; i < 0xA0; i++) {
+      CHARS_TO_ESCAPE[i] = EMPTY; // Control characters
+    }
+
+    // all "normal" character positions contains null
+  }
+
+  public HtmlWriterUtils(final Writer out, final String characterEncoding) {
+    super(out, characterEncoding);
+  }
+
+  @Override
+  protected void writeEncodedValue(final char[] text, final int start,
+      final int length, final boolean isAttribute) throws IOException {
+
+    int localIndex = -1;
+
+    final int end = start + length;
+    for (int i = start; i < end; i++) {
+      final char ch = text[i];
+      if (ch >= CHARS_TO_ESCAPE.length || CHARS_TO_ESCAPE[ch] != null) {
+        localIndex = i;
+        break;
+      }
+    }
+    final Writer out = getOut();
+
+    if (localIndex == -1) {
+      // no need to escape
+      out.write(text, start, length);
+    } else {
+      // write until localIndex and then encode the remainder
+      out.write(text, start, localIndex);
+
+      final ResponseWriterBuffer buffer = getBuffer();
+
+      for (int i = localIndex; i < end; i++) {
+        final char ch = text[i];
+
+        // Tilde or less...
+        if (ch < CHARS_TO_ESCAPE.length) {
+          if (isAttribute && ch == '&' && (i + 1 < end) && text[i + 1] == '{') {
+            // HTML 4.0, section B.7.1: ampersands followed by
+            // an open brace don't get escaped
+            buffer.addToBuffer('&');
+          } else if (CHARS_TO_ESCAPE[ch] != null) {
+            buffer.addToBuffer(CHARS_TO_ESCAPE[ch]);
+          } else {
+            buffer.addToBuffer(ch);
+          }
+        } else if (isUtf8()) {
+          buffer.addToBuffer(ch);
+        } else if (ch <= 0xff) {
+          // ISO-8859-1 entities: encode as needed
+          buffer.flushBuffer();
+
+          out.write('&');
+          final char[] chars = ISO8859_1_ENTITIES[ch - 0xA0];
+          out.write(chars, 0, chars.length);
+          out.write(';');
+        } else {
+          buffer.flushBuffer();
+
+          // Double-byte characters to encode.
+          // PENDING: when outputting to an encoding that
+          // supports double-byte characters (UTF-8, for example),
+          // we should not be encoding
+          writeDecRef(ch);
+        }
+      }
+
+      buffer.flushBuffer();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HttpPartWrapper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HttpPartWrapper.java
new file mode 100644
index 0000000..1736324
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/HttpPartWrapper.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import javax.faces.FacesException;
+import javax.faces.FacesWrapper;
+import javax.faces.component.StateHolder;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Collection;
+
+public class HttpPartWrapper implements Part, FacesWrapper<Part>, StateHolder {
+  private Part delegate;
+
+  public HttpPartWrapper() {
+  }
+
+  public HttpPartWrapper(Part delegate) {
+    this.delegate = delegate;
+  }
+
+  @Override
+  public void delete() throws IOException {
+    getWrapped().delete();
+  }
+
+  @Override
+  public String getContentType() {
+    return getWrapped().getContentType();
+  }
+
+  @Override
+  public String getHeader(String headerName) {
+    return getWrapped().getHeader(headerName);
+  }
+
+  @Override
+  public Collection<String> getHeaderNames() {
+    return getWrapped().getHeaderNames();
+  }
+
+  @Override
+  public Collection<String> getHeaders(String headerName) {
+    return getWrapped().getHeaders(headerName);
+  }
+
+  @Override
+  public InputStream getInputStream() throws IOException {
+    return getWrapped().getInputStream();
+  }
+
+  @Override
+  public String getName() {
+    return getWrapped().getName();
+  }
+
+  @Override
+  public long getSize() {
+    return getWrapped().getSize();
+  }
+
+  @Override
+  public void write(String fileName) throws IOException {
+    getWrapped().write(fileName);
+  }
+
+  public String getSubmittedFileName() {
+    Part wrapped = getWrapped();
+    try {
+      Method m = wrapped.getClass().getMethod("getSubmittedFileName");
+      return (String) m.invoke(wrapped);
+    } catch (NoSuchMethodException ex) {
+      throw new FacesException(ex);
+    } catch (SecurityException ex) {
+      throw new FacesException(ex);
+    } catch (IllegalAccessException ex) {
+      throw new FacesException(ex);
+    } catch (IllegalArgumentException ex) {
+      throw new FacesException(ex);
+    } catch (InvocationTargetException ex) {
+      throw new FacesException(ex);
+    }
+  }
+
+  @Override
+  public Object saveState(FacesContext context) {
+    return null;
+  }
+
+  @Override
+  public void restoreState(FacesContext context, Object state) {
+  }
+
+  @Override
+  public boolean isTransient() {
+    return true;
+  }
+
+  @Override
+  public void setTransient(boolean newTransientValue) {
+  }
+
+  @Override
+  public Part getWrapped() {
+    return delegate;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/IoUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/IoUtils.java
new file mode 100644
index 0000000..fad8f3b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/IoUtils.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+public final class IoUtils {
+
+  private IoUtils() {
+  }
+
+  public static void closeQuietly(final Closeable closeable) {
+    try {
+      if (closeable != null) {
+        closeable.close();
+      }
+    } catch (final IOException exception) {
+      // ignore
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JQueryUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JQueryUtils.java
new file mode 100644
index 0000000..78dc09d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JQueryUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+public class JQueryUtils {
+
+  public static String escapeIdForHtml(String id) {
+    return "#" + id.replaceAll("([:\\.\\[\\],])", "\\\\$1");
+  }
+
+  public static String escapeIdForJavaScript(String id) {
+    return "#" + id.replaceAll("([:\\.\\[\\],])", "\\\\\\\\$1");
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JavascriptWriterUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JavascriptWriterUtils.java
new file mode 100644
index 0000000..d50bb68
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JavascriptWriterUtils.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public final class JavascriptWriterUtils extends WriterUtils {
+
+  private static final char[][] CHARS_TO_ESCAPE;
+
+  static {
+    // init lookup table
+    CHARS_TO_ESCAPE = new char[0xA0][];
+
+    for (int i = 0; i < 0x20; i++) {
+      CHARS_TO_ESCAPE[i] = EMPTY; // Control characters
+    }
+
+    CHARS_TO_ESCAPE['\t'] = "\\n".toCharArray(); // Horizontal tabulator
+    CHARS_TO_ESCAPE['\n'] = "\\n".toCharArray(); // Line feed
+    CHARS_TO_ESCAPE['\r'] = "\\r".toCharArray(); // Carriage return
+
+    CHARS_TO_ESCAPE['"'] = "\\\"".toCharArray();
+    CHARS_TO_ESCAPE['\\'] = "\\\\".toCharArray();
+
+    CHARS_TO_ESCAPE[0x7F] = EMPTY; // Delete
+
+    for (int i = 0x80; i < 0xA0; i++) {
+      CHARS_TO_ESCAPE[i] = EMPTY; // Control characters
+    }
+
+    // all "normal" character positions contains null
+  }
+
+  public JavascriptWriterUtils(final Writer out, final String characterEncoding) {
+    super(out, characterEncoding);
+  }
+
+  @Override
+  protected void writeEncodedValue(final char[] text, final int start,
+      final int length, final boolean isAttribute) throws IOException {
+
+    int localIndex = -1;
+
+    final int end = start + length;
+    for (int i = start; i < end; i++) {
+      final char ch = text[i];
+      if (ch >= CHARS_TO_ESCAPE.length || CHARS_TO_ESCAPE[ch] != null) {
+        localIndex = i;
+        break;
+      }
+    }
+    final Writer out = getOut();
+
+    if (localIndex == -1) {
+      // no need to escape
+      out.write(text, start, length);
+    } else {
+      // write until localIndex and then encode the remainder
+      out.write(text, start, localIndex);
+
+      final ResponseWriterBuffer buffer = getBuffer();
+
+      for (int i = localIndex; i < end; i++) {
+        final char ch = text[i];
+
+        // Tilde or less...
+        if (ch < CHARS_TO_ESCAPE.length) {
+          if (isAttribute && ch == '&' && (i + 1 < end) && text[i + 1] == '{') {
+            // HTML 4.0, section B.7.1: ampersands followed by
+            // an open brace don't get escaped
+            buffer.addToBuffer('&');
+          } else if (CHARS_TO_ESCAPE[ch] != null) {
+            buffer.addToBuffer(CHARS_TO_ESCAPE[ch]);
+          } else {
+            buffer.addToBuffer(ch);
+          }
+        } else if (isUtf8()) {
+          buffer.addToBuffer(ch);
+        } else if (ch <= 0xff) {
+          // ISO-8859-1 entities: encode as needed
+          buffer.flushBuffer();
+
+          out.write('&');
+          final char[] chars = ISO8859_1_ENTITIES[ch - 0xA0];
+          out.write(chars, 0, chars.length);
+          out.write(';');
+        } else {
+          buffer.flushBuffer();
+
+          // Double-byte characters to encode.
+          // PENDING: when outputting to an encoding that
+          // supports double-byte characters (UTF-8, for example),
+          // we should not be encoding
+          writeDecRef(ch);
+        }
+      }
+
+      buffer.flushBuffer();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JndiUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JndiUtils.java
new file mode 100644
index 0000000..ed83473
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JndiUtils.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+
+public final class JndiUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(JndiUtils.class);
+
+  private JndiUtils() {
+  }
+
+  public static Object getJndiProperty(final Context ctx, final String... path) throws NamingException {
+    return getJndiProperty(ctx, null, path);
+  }
+
+  public static Object getJndiProperty(final Context ctx, final Object defaultValue, final String... path)
+      throws NamingException {
+    String name = "java:comp/env";
+    // avoid error messages from websphere
+    for (int i = 0; i < path.length; i++) {
+      final Binding b = getBinding(ctx, name, path[i]);
+      if (b == null) {
+        break;
+      }
+      if (i == path.length - 1) {
+        final Object obj = b.getObject();
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Value: " + obj);
+        }
+        return obj;
+      } else {
+        name = name + "/" + path[i];
+      }
+    }
+    return defaultValue;
+  }
+
+  private static Binding getBinding(final Context ctx, final String name, final String path)
+      throws NamingException {
+    final NamingEnumeration<Binding> ne = ctx.listBindings(name);
+    while (ne.hasMore()) {
+      final Binding b = ne.next();
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Property: " + b.getName());
+      }
+      if (path.equals(b.getName())) {
+        return b;
+      }
+    }
+    return null;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonUtils.java
new file mode 100644
index 0000000..eb4958e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonUtils.java
@@ -0,0 +1,297 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.internal.context.DateTimeI18n;
+import org.apache.myfaces.tobago.internal.renderkit.Collapse;
+import org.apache.myfaces.tobago.internal.renderkit.Command;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.layout.AutoLayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutToken;
+import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.apache.myfaces.tobago.layout.MeasureLayoutToken;
+import org.apache.myfaces.tobago.layout.RelativeLayoutToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+
+public class JsonUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(JsonUtils.class);
+
+  private JsonUtils() {
+  }
+
+  private static void encode(final StringBuilder builder, final String name, final String[] value) {
+    builder.append("\"");
+    builder.append(name);
+    builder.append("\":");
+    encode(builder, value);
+    builder.append(",");
+  }
+
+  public static void encode(StringBuilder builder, String[] value) {
+    builder.append("[");
+    boolean colon = false;
+    for (final String item : value) {
+      if (colon) {
+        builder.append(",");
+      }
+      builder.append("\"");
+      builder.append(item);
+      builder.append("\"");
+      colon = true;
+    }
+    builder.append("]");
+  }
+
+  public static void encode(StringBuilder builder, List<Integer> value) {
+    builder.append("[");
+    boolean colon = false;
+    for (final Integer item : value) {
+      if (colon) {
+        builder.append(",");
+      }
+      builder.append(item);
+      colon = true;
+    }
+    builder.append("]");
+  }
+
+  private static void encode(final StringBuilder builder, final String name, final Boolean value) {
+    builder.append("\"");
+    builder.append(name);
+    builder.append("\":");
+    builder.append(Boolean.toString(value));
+    builder.append(",");
+  }
+
+  private static void encode(final StringBuilder builder, final String name, final Integer value) {
+    builder.append("\"");
+    builder.append(name);
+    builder.append("\":");
+    builder.append(Integer.toString(value));
+    builder.append(",");
+  }
+
+  private static void encode(final StringBuilder builder, final String name, String value) {
+    value = value.replaceAll("\\\"", "\\\\\\\""); // todo: optimize
+    builder.append("\"");
+    builder.append(name);
+    builder.append("\":\"");
+    builder.append(value);
+    builder.append("\",");
+  }
+
+  public static String encode(final CommandMap commandMap) {
+
+    if (commandMap == null) {
+      return null;
+    }
+
+    final StringBuilder builder = new StringBuilder();
+    builder.append("{");
+    final int initialLength = builder.length();
+
+    final Command click = commandMap.getClick();
+    if (click != null) {
+      encode(builder, ClientBehaviors.click, click);
+    }
+
+    final Map<ClientBehaviors, Command> other = commandMap.getOther();
+    if (other != null) {
+      for(final Map.Entry<ClientBehaviors, Command> entry : other.entrySet()) {
+        encode(builder, entry.getKey(), entry.getValue());
+      }
+    }
+
+    if (builder.length() - initialLength > 0) {
+      assert builder.charAt(builder.length() - 1) == ',';
+      builder.deleteCharAt(builder.length() - 1);
+    }
+
+    builder.append("}");
+    return builder.toString();
+  }
+
+  private static void encode(final StringBuilder builder, final ClientBehaviors name, final Command command) {
+    builder.append("\"");
+    builder.append(name);
+    builder.append("\":{");
+    final int initialLength = builder.length();
+
+    final String action = command.getAction();
+    if (action != null) {
+      encode(builder, "action", action);
+    }
+    final Boolean transition = command.getTransition();
+    if (transition != null && !transition) { // true is the default, so encoding is needed.
+      encode(builder, "transition", transition);
+    }
+    final String target = command.getTarget();
+    if (target != null) {
+      encode(builder, "target", target);
+    }
+    final String execute = command.getExecute();
+    if (execute != null) {
+      encode(builder, "execute", execute);
+    }
+    final String render = command.getRender();
+    if (render != null) {
+      encode(builder, "render", render);
+    }
+    final Collapse collapse = command.getCollapse();
+    if (collapse != null) {
+      encode(builder, "collapse", collapse);
+    }
+    final String focus = command.getFocus();
+    if (focus != null) {
+      encode(builder, "focus", focus);
+    }
+    final String confirmation = command.getConfirmation();
+    if (confirmation != null) {
+      encode(builder, "confirmation", confirmation);
+    }
+    final Integer delay  = command.getDelay();
+    if (delay != null) {
+      encode(builder, "delay", delay);
+    }
+    final Boolean omit = command.getOmit();
+    if (omit != null && omit) { // false is the default, so encoding is needed.
+      encode(builder, "omit", true);
+    }
+
+    if (builder.length() - initialLength > 0) {
+      assert builder.charAt(builder.length() - 1) == ',';
+      builder.deleteCharAt(builder.length() - 1);
+    }
+
+    builder.append("},");
+  }
+
+  private static void encode(final StringBuilder builder, final String name, final Collapse collapse) {
+    builder.append("\"");
+    builder.append(name);
+    builder.append("\":{");
+    final int initialLength = builder.length();
+
+    final Collapse.Action action = collapse.getAction();
+    if (action != null) {
+      encode(builder, "transition", action.name());
+    }
+    final String forId = collapse.getFor();
+    if (forId != null) {
+      encode(builder, "forId", forId);
+    }
+    if (builder.length() - initialLength > 0) {
+      assert builder.charAt(builder.length() - 1) == ',';
+      builder.deleteCharAt(builder.length() - 1);
+    }
+
+    builder.append("},");
+  }
+
+  public static String encode(final DateTimeI18n dateTimeI18n) {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("{");
+    final int initialLength = builder.length();
+
+    encode(builder, "monthNames", dateTimeI18n.getMonthNames());
+    encode(builder, "monthNamesShort", dateTimeI18n.getMonthNamesShort());
+    encode(builder, "dayNames", dateTimeI18n.getDayNames());
+    encode(builder, "dayNamesShort", dateTimeI18n.getDayNamesShort());
+    encode(builder, "dayNamesMin", dateTimeI18n.getDayNamesMin());
+    encode(builder, "firstDay", dateTimeI18n.getFirstDay());
+
+    if (builder.length() - initialLength > 0) {
+      assert builder.charAt(builder.length() - 1) == ',';
+      builder.deleteCharAt(builder.length() - 1);
+    }
+    builder.append("}");
+    return builder.toString();
+  }
+
+  public static String encode(final String[] strings) {
+    if (strings == null) {
+      return null;
+    }
+    final StringBuilder builder = new StringBuilder();
+    encode(builder, strings);
+    return builder.toString();
+  }
+
+  public static String encode(final List<Integer> integers) {
+    if (integers == null) {
+      return null;
+    }
+    final StringBuilder builder = new StringBuilder();
+    encode(builder, integers);
+    return builder.toString();
+  }
+
+  public static void encode(final LayoutTokens bankHeads, final StringBuilder builder) {
+    builder.append("[");
+    for (final LayoutToken token : bankHeads.getTokens()) {
+      if (token instanceof RelativeLayoutToken) {
+        final int factor = ((RelativeLayoutToken) token).getFactor();
+        builder.append(factor);
+      } else if (token instanceof AutoLayoutToken) {
+        builder.append("\"auto\"");
+      } else if (token instanceof MeasureLayoutToken) {
+        builder.append("{\"measure\":\"");
+        builder.append(((MeasureLayoutToken) token).getMeasure());
+        builder.append("\"}");
+      } else {
+        LOG.warn("Not supported: " + token);
+      }
+      builder.append(',');
+    }
+    if (builder.charAt(builder.length() - 1) == ',') {
+      builder.deleteCharAt(builder.length() - 1);
+    }
+    builder.append("]");
+  }
+
+  public static List<Integer> decodeIntegerArray(String json) {
+    json = json.trim();
+    final List<Integer> result = new ArrayList<Integer>();
+    if (json.length() < 2 || json.charAt(0) != '[' || json.charAt(json.length() - 1) != ']') {
+      LOG.warn("Can't parse JSON array: no surrounding square brackets []: '{}'", json);
+    } else {
+      json = json.substring(1, json.length() - 1);
+      final StringTokenizer tokenizer = new StringTokenizer(json, ",");
+      while (tokenizer.hasMoreTokens()) {
+        final String token = tokenizer.nextToken().trim();
+        try {
+          result.add(Integer.parseInt(token));
+        } catch (NumberFormatException e) {
+          LOG.warn("Can't parse JSON array: not an integer token: '{}'", token);
+          // ignoring so far
+        }
+      }
+    }
+    return result;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonWriterUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonWriterUtils.java
new file mode 100644
index 0000000..f35b9f3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/JsonWriterUtils.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+
+public final class JsonWriterUtils extends WriterUtils {
+
+  private static final char[][] CHARS_TO_ESCAPE;
+
+  static {
+    // init lookup table
+    CHARS_TO_ESCAPE = new char[0xA0][];
+
+    for (int i = 0; i < 0x20; i++) {
+      CHARS_TO_ESCAPE[i] = EMPTY; // Control characters
+    }
+
+    CHARS_TO_ESCAPE['\t'] = "&#09;".toCharArray(); // Horizontal tabulator
+    CHARS_TO_ESCAPE['\n'] = "&#10;".toCharArray(); // Line feed
+    CHARS_TO_ESCAPE['\r'] = "&#13;".toCharArray(); // Carriage return
+
+    CHARS_TO_ESCAPE['\''] = "&#39;".toCharArray();
+    CHARS_TO_ESCAPE['"'] = "\\\"".toCharArray();
+    CHARS_TO_ESCAPE['&'] = "&amp;".toCharArray();
+    CHARS_TO_ESCAPE['<'] = "&lt;".toCharArray();
+    CHARS_TO_ESCAPE['>'] = "&gt;".toCharArray();
+    CHARS_TO_ESCAPE['\\'] = "\\\\".toCharArray();
+
+    CHARS_TO_ESCAPE[0x7F] = EMPTY; // Delete
+
+    for (int i = 0x80; i < 0xA0; i++) {
+      CHARS_TO_ESCAPE[i] = EMPTY; // Control characters
+    }
+
+    // all "normal" character positions contains null
+  }
+
+  public JsonWriterUtils(final Writer out, final String characterEncoding) {
+    super(out, characterEncoding);
+  }
+
+  @Override
+  protected void writeEncodedValue(final char[] text, final int start,
+      final int length, final boolean isAttribute) throws IOException {
+
+    int localIndex = -1;
+
+    final int end = start + length;
+    for (int i = start; i < end; i++) {
+      final char ch = text[i];
+      if (ch >= CHARS_TO_ESCAPE.length || CHARS_TO_ESCAPE[ch] != null) {
+        localIndex = i;
+        break;
+      }
+    }
+    final Writer out = getOut();
+
+    if (localIndex == -1) {
+      // no need to escape
+      out.write(text, start, length);
+    } else {
+      // write until localIndex and then encode the remainder
+      out.write(text, start, localIndex);
+
+      final ResponseWriterBuffer buffer = getBuffer();
+
+      for (int i = localIndex; i < end; i++) {
+        final char ch = text[i];
+
+        // Tilde or less...
+        if (ch < CHARS_TO_ESCAPE.length) {
+          if (isAttribute && ch == '&' && (i + 1 < end) && text[i + 1] == '{') {
+            // HTML 4.0, section B.7.1: ampersands followed by
+            // an open brace don't get escaped
+            buffer.addToBuffer('&');
+          } else if (CHARS_TO_ESCAPE[ch] != null) {
+            buffer.addToBuffer(CHARS_TO_ESCAPE[ch]);
+          } else {
+            buffer.addToBuffer(ch);
+          }
+        } else if (isUtf8()) {
+          buffer.addToBuffer(ch);
+        } else if (ch <= 0xff) {
+          // ISO-8859-1 entities: encode as needed
+          buffer.flushBuffer();
+
+          out.write('&');
+          final char[] chars = ISO8859_1_ENTITIES[ch - 0xA0];
+          out.write(chars, 0, chars.length);
+          out.write(';');
+        } else {
+          buffer.flushBuffer();
+
+          // Double-byte characters to encode.
+          // PENDING: when outputting to an encoding that
+          // supports double-byte characters (UTF-8, for example),
+          // we should not be encoding
+          writeDecRef(ch);
+        }
+      }
+
+      buffer.flushBuffer();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/MimeTypeUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/MimeTypeUtils.java
new file mode 100644
index 0000000..81423b5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/MimeTypeUtils.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+
+import javax.servlet.ServletContext;
+import java.util.Map;
+
+public final class MimeTypeUtils {
+
+  private static Map<String, String> additionalMimeTypes = null;
+
+  private MimeTypeUtils() {
+    // utils class
+  }
+
+  // todo: maybe support more extensions
+  public static String getMimeTypeForFile(final String file) {
+    int length = file.length();
+    if (file.charAt(length - 4) == '.') {
+      if (file.charAt(length - 1) == 'g') {
+        if (file.regionMatches(length - 3, "png", 0, 2)) {
+          return "image/png";
+        }
+        if (file.regionMatches(length - 3, "jpg", 0, 2)) {
+          return "image/jpeg";
+        }
+        if (file.endsWith("svg")) {
+          return "image/svg+xml";
+        }
+      } else {
+        if (file.endsWith("css")) {
+          return "text/css";
+        }
+        if (file.endsWith("gif")) {
+          return "image/gif";
+        }
+        if (file.endsWith("htm")) {
+          return "text/html";
+        }
+        if (file.endsWith("ico")) {
+          return "image/vnd.microsoft.icon";
+        }
+        if (file.endsWith("map")) {
+          return "application/json";
+        }
+        if (file.endsWith("ttf")) {
+          return "application/x-font-ttf";
+        }
+        if (file.endsWith("eot")) {
+          return "application/vnd.ms-fontobject";
+        }
+      }
+    } else if (file.charAt(length - 3) == '.') {
+      if (file.endsWith("js")) {
+        return "text/javascript";
+      }
+    } else if (file.charAt(length - 5) == '.') {
+      if (file.endsWith("woff")) {
+        return "application/font-woff";
+      }
+      if (file.endsWith("html")) {
+        return "text/html";
+      }
+    } else if (file.charAt(length - 6) == '.') {
+      if (file.endsWith("woff2")) {
+        return "application/font-woff2";
+      }
+    }
+
+    final int index = file.lastIndexOf('.');
+    if (index > -1) {
+      String extension = file.substring(index + 1);
+      return additionalMimeTypes.get(extension);
+    }
+
+    return null;
+  }
+
+  public static void init(ServletContext servletContext) {
+    if (additionalMimeTypes == null) {
+      final TobagoConfig tobagoConfig = TobagoConfig.getInstance(servletContext);
+      additionalMimeTypes = tobagoConfig.getMimeTypes();
+    } else {
+      throw new IllegalStateException(MimeTypeUtils.class.getSimpleName() + " is already initialized!");
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/NumberUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/NumberUtils.java
new file mode 100644
index 0000000..4294528
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/NumberUtils.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+public class NumberUtils {
+  public static boolean isDigits(final String str) {
+    if ((str == null) || (str.length() == 0)) {
+      return false;
+    }
+    for (int i = 0; i < str.length(); i++) {
+      if (!Character.isDigit(str.charAt(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ObjectUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ObjectUtils.java
new file mode 100644
index 0000000..2d38a7a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ObjectUtils.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+public class ObjectUtils {
+
+  private ObjectUtils() {
+    // utils class
+  }
+
+  @SuppressWarnings("ObjectEquality")
+  public static boolean equals(Object o1, Object o2) {
+    return o1 == o2 || o1 != null && o1.equals(o2);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/PartUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/PartUtils.java
new file mode 100644
index 0000000..04c90d8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/PartUtils.java
@@ -0,0 +1,331 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.commons.beanutils.PropertyUtils;
+
+import javax.servlet.http.Part;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+
+/**
+ * Only needed for Servlet 3.0. Not needed for Servlet 3.1 or higher.
+ *
+ * Basically taken from Apache Tomcat 8
+ */
+public final class PartUtils {
+
+  private PartUtils() {
+  }
+
+  /**
+   * This is a helper method, to get the original file name of the upload.
+   * If you have at least Servlet 3.1, you wouldn't need this function.
+   *
+   * @since Tobago 3.0.0
+   */
+  public static String getSubmittedFileName(Part part) {
+
+    try { // try to call the Servlet 3.1 function
+      return (String) PropertyUtils.getProperty(part, "submittedFileName");
+    } catch (Exception e) {
+      // ignore
+    }
+
+    String fileName = null;
+    String cd = part.getHeader("Content-Disposition");
+    if (cd != null) {
+      String cdl = cd.toLowerCase(Locale.ENGLISH);
+      if (cdl.startsWith("form-data") || cdl.startsWith("attachment")) {
+        ParameterParser paramParser = new ParameterParser();
+        paramParser.setLowerCaseNames(true);
+        // Parameter parser can handle null input
+        Map<String, String> params =
+            paramParser.parse(cd, ';');
+        if (params.containsKey("filename")) {
+          fileName = params.get("filename");
+          if (fileName != null) {
+            fileName = fileName.trim();
+            // XXX seems to be wrong in the code?
+            fileName = fileName.replaceAll("\\\\\\\"", "\""); // replaces \" with "
+          } else {
+            // Even if there is no value, the parameter is present,
+            // so we return an empty file name rather than no file
+            // name.
+            fileName = "";
+          }
+        }
+      }
+    }
+    return fileName;
+  }
+
+  private static class ParameterParser {
+
+    /**
+     * String to be parsed.
+     */
+    private char[] chars = null;
+
+    /**
+     * Current position in the string.
+     */
+    private int pos = 0;
+
+    /**
+     * Maximum position in the string.
+     */
+    private int len = 0;
+
+    /**
+     * Start of a token.
+     */
+    private int i1 = 0;
+
+    /**
+     * End of a token.
+     */
+    private int i2 = 0;
+
+    /**
+     * Whether names stored in the map should be converted to lower case.
+     */
+    private boolean lowerCaseNames = false;
+
+    /**
+     * Default ParameterParser constructor.
+     */
+    public ParameterParser() {
+      super();
+    }
+
+    /**
+     * Are there any characters left to parse?
+     *
+     * @return {@code true} if there are unparsed characters,
+     * {@code false} otherwise.
+     */
+    private boolean hasChar() {
+      return this.pos < this.len;
+    }
+
+    /**
+     * A helper method to process the parsed token. This method removes
+     * leading and trailing blanks as well as enclosing quotation marks,
+     * when necessary.
+     *
+     * @param quoted {@code true} if quotation marks are expected,
+     *               {@code false} otherwise.
+     * @return the token
+     */
+    private String getToken(boolean quoted) {
+      // Trim leading white spaces
+      while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) {
+        i1++;
+      }
+      // Trim trailing white spaces
+      while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) {
+        i2--;
+      }
+      // Strip away quotation marks if necessary
+      if (quoted
+          && ((i2 - i1) >= 2)
+          && (chars[i1] == '"')
+          && (chars[i2 - 1] == '"')) {
+        i1++;
+        i2--;
+      }
+      String result = null;
+      if (i2 > i1) {
+        result = new String(chars, i1, i2 - i1);
+      }
+      return result;
+    }
+
+    /**
+     * Tests if the given character is present in the array of characters.
+     *
+     * @param ch      the character to test for presense in the array of characters
+     * @param charray the array of characters to test against
+     * @return {@code true} if the character is present in the array of
+     * characters, {@code false} otherwise.
+     */
+    private boolean isOneOf(char ch, final char[] charray) {
+      boolean result = false;
+      for (char element : charray) {
+        if (ch == element) {
+          result = true;
+          break;
+        }
+      }
+      return result;
+    }
+
+    /**
+     * Parses out a token until any of the given terminators
+     * is encountered.
+     *
+     * @param terminators the array of terminating characters. Any of these
+     *                    characters when encountered signify the end of the token
+     * @return the token
+     */
+    private String parseToken(final char[] terminators) {
+      char ch;
+      i1 = pos;
+      i2 = pos;
+      while (hasChar()) {
+        ch = chars[pos];
+        if (isOneOf(ch, terminators)) {
+          break;
+        }
+        i2++;
+        pos++;
+      }
+      return getToken(false);
+    }
+
+    /**
+     * Parses out a token until any of the given terminators
+     * is encountered outside the quotation marks.
+     *
+     * @param terminators the array of terminating characters. Any of these
+     *                    characters when encountered outside the quotation marks signify the end
+     *                    of the token
+     * @return the token
+     */
+    private String parseQuotedToken(final char[] terminators) {
+      char ch;
+      i1 = pos;
+      i2 = pos;
+      boolean quoted = false;
+      boolean charEscaped = false;
+      while (hasChar()) {
+        ch = chars[pos];
+        if (!quoted && isOneOf(ch, terminators)) {
+          break;
+        }
+        if (!charEscaped && ch == '"') {
+          quoted = !quoted;
+        }
+        charEscaped = (!charEscaped && ch == '\\');
+        i2++;
+        pos++;
+
+      }
+      return getToken(true);
+    }
+
+    /**
+     * Sets the flag if parameter names are to be converted to lower case when
+     * name/value pairs are parsed.
+     *
+     * @param b {@code true} if parameter names are to be
+     *          converted to lower case when name/value pairs are parsed.
+     *          {@code false} otherwise.
+     */
+    public void setLowerCaseNames(boolean b) {
+      this.lowerCaseNames = b;
+    }
+
+    /**
+     * Extracts a map of name/value pairs from the given string. Names are
+     * expected to be unique.
+     *
+     * @param str       the string that contains a sequence of name/value pairs
+     * @param separator the name/value pairs separator
+     * @return a map of name/value pairs
+     */
+    public Map<String, String> parse(final String str, char separator) {
+      if (str == null) {
+        return new HashMap<String, String>();
+      }
+      return parse(str.toCharArray(), separator);
+    }
+
+    /**
+     * Extracts a map of name/value pairs from the given array of
+     * characters. Names are expected to be unique.
+     *
+     * @param charArray the array of characters that contains a sequence of
+     *                  name/value pairs
+     * @param separator the name/value pairs separator
+     * @return a map of name/value pairs
+     */
+    public Map<String, String> parse(final char[] charArray, char separator) {
+      if (charArray == null) {
+        return new HashMap<String, String>();
+      }
+      return parse(charArray, 0, charArray.length, separator);
+    }
+
+    /**
+     * Extracts a map of name/value pairs from the given array of
+     * characters. Names are expected to be unique.
+     *
+     * @param charArray the array of characters that contains a sequence of
+     *                  name/value pairs
+     * @param offset    - the initial offset.
+     * @param length    - the length.
+     * @param separator the name/value pairs separator
+     * @return a map of name/value pairs
+     */
+    public Map<String, String> parse(
+        final char[] charArray,
+        int offset,
+        int length,
+        char separator) {
+
+      if (charArray == null) {
+        return new HashMap<String, String>();
+      }
+      HashMap<String, String> params = new HashMap<String, String>();
+      this.chars = charArray;
+      this.pos = offset;
+      this.len = length;
+
+      String paramName;
+      String paramValue;
+      while (hasChar()) {
+        paramName = parseToken(new char[]{
+            '=', separator
+        });
+        paramValue = null;
+        if (hasChar() && (charArray[pos] == '=')) {
+          pos++; // skip '='
+          paramValue = parseQuotedToken(new char[]{
+              separator
+          });
+        }
+        if (hasChar() && (charArray[pos] == separator)) {
+          pos++; // skip separator
+        }
+        if ((paramName != null) && (paramName.length() > 0)) {
+          if (this.lowerCaseNames) {
+            paramName = paramName.toLowerCase(Locale.ENGLISH);
+          }
+
+          params.put(paramName, paramValue);
+        }
+      }
+      return params;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
new file mode 100644
index 0000000..d7e3a5e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/RenderUtils.java
@@ -0,0 +1,304 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommandBase;
+import org.apache.myfaces.tobago.internal.component.AbstractUIData;
+import org.apache.myfaces.tobago.internal.renderkit.Command;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.SelectedState;
+import org.apache.myfaces.tobago.model.TreePath;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIParameter;
+import javax.faces.component.ValueHolder;
+import javax.faces.component.behavior.ClientBehavior;
+import javax.faces.component.behavior.ClientBehaviorBase;
+import javax.faces.component.behavior.ClientBehaviorContext;
+import javax.faces.component.behavior.ClientBehaviorHolder;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.render.ClientBehaviorRenderer;
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.List;
+import java.util.Map;
+
+public final class RenderUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(RenderUtils.class);
+
+  private RenderUtils() {
+    // to prevent instantiation
+  }
+
+  public static boolean contains(final Object[] list, final Object value) {
+    if (list == null) {
+      return false;
+    }
+    for (final Object aList : list) {
+      if (aList != null && aList.equals(value)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static void encodeChildren(final FacesContext facesContext, final UIComponent panel) throws IOException {
+    for (final UIComponent child : panel.getChildren()) {
+      encode(facesContext, child);
+    }
+  }
+
+  public static void encode(final FacesContext facesContext, final UIComponent component) throws IOException {
+    encode(facesContext, component, null);
+  }
+
+  public static void encode(
+      final FacesContext facesContext, final UIComponent component,
+      final List<? extends Class<? extends UIComponent>> only)
+      throws IOException {
+
+    if (only != null && !matchFilter(component, only)) {
+      return;
+    }
+
+    if (component.isRendered()) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("rendering " + component.getRendererType() + " " + component);
+      }
+      component.encodeBegin(facesContext);
+      if (component.getRendersChildren()) {
+        component.encodeChildren(facesContext);
+      } else {
+        for (final UIComponent child : component.getChildren()) {
+          encode(facesContext, child, only);
+        }
+      }
+      component.encodeEnd(facesContext);
+    }
+  }
+
+  private static boolean matchFilter(
+      final UIComponent component, final List<? extends Class<? extends UIComponent>> only) {
+    for (final Class<? extends UIComponent> clazz : only) {
+      if (clazz.isAssignableFrom(component.getClass())) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static String currentValue(final UIComponent component) {
+    String currentValue = null;
+    if (component instanceof ValueHolder) {
+      Object value;
+      if (component instanceof EditableValueHolder) {
+        value = ((EditableValueHolder) component).getSubmittedValue();
+        if (value != null) {
+          return (String) value;
+        }
+      }
+
+      value = ((ValueHolder) component).getValue();
+      if (value != null) {
+        currentValue = ComponentUtils.getFormattedValue(FacesContext.getCurrentInstance(), component, value);
+      }
+    }
+    return currentValue;
+  }
+
+  public static void decodedStateOfTreeData(final FacesContext facesContext, final AbstractUIData data) {
+
+    if (!data.isTreeModel()) {
+      return;
+    }
+
+    // selected
+    final List<Integer> selectedIndices = decodeIndices(facesContext, data, AbstractUIData.SUFFIX_SELECTED);
+
+    // expanded
+    final List<Integer> expandedIndices = decodeIndices(facesContext, data, AbstractUIData.SUFFIX_EXPANDED);
+
+    final int last = data.isRowsUnlimited() ? Integer.MAX_VALUE : data.getFirst() + data.getRows();
+    for (int rowIndex = data.getFirst(); rowIndex < last; rowIndex++) {
+      data.setRowIndex(rowIndex);
+      if (!data.isRowAvailable()) {
+        break;
+      }
+
+      final TreePath path = data.getPath();
+
+      // selected
+      if (selectedIndices != null) {
+        final SelectedState selectedState = data.getSelectedState();
+        final boolean oldSelected = selectedState.isSelected(path);
+        final boolean newSelected = selectedIndices.contains(rowIndex);
+        if (newSelected != oldSelected) {
+          if (newSelected) {
+            selectedState.select(path);
+          } else {
+            selectedState.unselect(path);
+          }
+        }
+      }
+
+      // expanded
+      if (expandedIndices != null) {
+        final ExpandedState expandedState = data.getExpandedState();
+        final boolean oldExpanded = expandedState.isExpanded(path);
+        final boolean newExpanded = expandedIndices.contains(rowIndex);
+        if (newExpanded != oldExpanded) {
+          if (newExpanded) {
+            expandedState.expand(path);
+          } else {
+            expandedState.collapse(path);
+          }
+        }
+      }
+
+    }
+    data.setRowIndex(-1);
+  }
+
+  private static List<Integer> decodeIndices(
+      final FacesContext facesContext, final AbstractUIData data, final String suffix) {
+    String string = null;
+    final String key = data.getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + suffix;
+    try {
+      string = facesContext.getExternalContext().getRequestParameterMap().get(key);
+      if (string != null) {
+        return StringUtils.parseIntegerList(string);
+      }
+    } catch (final Exception e) {
+      // should not happen
+      LOG.warn("Can't parse " + suffix + ": '" + string + "' from parameter '" + key + "'", e);
+    }
+    return null;
+  }
+
+  public static String generateUrl(final FacesContext facesContext, final AbstractUICommandBase component) {
+
+    final ExternalContext externalContext = facesContext.getExternalContext();
+
+    String url = null;
+
+    if (component.getLink() != null) {
+
+      final String link = component.getLink();
+      if (link.startsWith("/")) { // internal absolute link
+        url = externalContext.encodeResourceURL(externalContext.getRequestContextPath() + link);
+      } else if (StringUtils.isUrl(link)) { // external link
+        url = link;
+      } else { // internal relative link
+        url = externalContext.encodeResourceURL(link);
+      }
+
+      final StringBuilder builder = new StringBuilder(url);
+      boolean firstParameter = !url.contains("?");
+      for (final UIComponent child : component.getChildren()) {
+        if (child instanceof UIParameter) {
+          final UIParameter parameter = (UIParameter) child;
+          if (firstParameter) {
+            builder.append("?");
+            firstParameter = false;
+          } else {
+            builder.append("&");
+          }
+          builder.append(parameter.getName());
+          builder.append("=");
+          final Object value = parameter.getValue();
+          if (value != null) {
+            final String characterEncoding = facesContext.getResponseWriter().getCharacterEncoding();
+            try {
+              builder.append(URLEncoder.encode(value.toString(), characterEncoding));
+            } catch (UnsupportedEncodingException e) {
+              LOG.error("", e);
+            }
+          }
+        }
+      }
+      url = builder.toString();
+    }
+
+    return url;
+  }
+
+  public static CommandMap getBehaviorCommands(final FacesContext facesContext, final ClientBehaviorHolder holder) {
+    CommandMap map = null;
+    final Map<String, List<ClientBehavior>> behaviors = holder.getClientBehaviors();
+    for (Map.Entry<String, List<ClientBehavior>> behaviorMap : behaviors.entrySet()) {
+      final String key = behaviorMap.getKey();
+      final ClientBehaviorContext context = ClientBehaviorContext.createClientBehaviorContext(
+          facesContext, (UIComponent) holder, key, ((UIComponent) holder).getClientId(facesContext), null);
+      for (ClientBehavior clientBehavior : behaviorMap.getValue()) {
+        if (clientBehavior instanceof ClientBehaviorBase) {
+          final String type = ((ClientBehaviorBase) clientBehavior).getRendererType();
+          final ClientBehaviorRenderer renderer = facesContext.getRenderKit().getClientBehaviorRenderer(type);
+          final String dummy = renderer.getScript(context, clientBehavior);
+          map = CommandMap.merge(map, CommandMap.restoreCommandMap(facesContext));
+        } else {
+          LOG.warn("Ignoring: '{}'", clientBehavior);
+        }
+      }
+    }
+
+    // if there is no explicit behavior (with f:ajax or tc:event), use the command properties as default.
+    // tbd: think about refactoring: put this into TobagoClientBehaviorRenderer
+    if ((map == null || map.isEmpty()) && holder instanceof AbstractUICommand) {
+      if (map == null) {
+        map = new CommandMap();
+      }
+      map.addCommand(ClientBehaviors.click, new Command(facesContext, (AbstractUICommand) holder));
+    }
+
+    return map;
+  }
+
+  public static void decodeClientBehaviors(final FacesContext facesContext, final UIComponent component) {
+    if (component instanceof ClientBehaviorHolder) {
+      final ClientBehaviorHolder clientBehaviorHolder = (ClientBehaviorHolder) component;
+      final Map<String, List<ClientBehavior>> clientBehaviors = clientBehaviorHolder.getClientBehaviors();
+      if (clientBehaviors != null && !clientBehaviors.isEmpty()) {
+        final Map<String, String> paramMap = facesContext.getExternalContext().getRequestParameterMap();
+        final String behaviorEventName = paramMap.get("javax.faces.behavior.event");
+        if (behaviorEventName != null) {
+          final List<ClientBehavior> clientBehaviorList = clientBehaviors.get(behaviorEventName);
+          if (clientBehaviorList != null && !clientBehaviorList.isEmpty()) {
+            final String clientId = paramMap.get("javax.faces.source");
+            if (component.getClientId(facesContext).equals(clientId)) {
+              for (ClientBehavior clientBehavior : clientBehaviorList) {
+                clientBehavior.decode(facesContext, component);
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java
new file mode 100644
index 0000000..4ce2cef
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseUtils.java
@@ -0,0 +1,145 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.context.TobagoContext;
+import org.apache.myfaces.tobago.context.UserAgent;
+import org.apache.myfaces.tobago.internal.config.ContentSecurityPolicy;
+import org.apache.myfaces.tobago.portlet.PortletUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.portlet.MimeResponse;
+import javax.servlet.http.HttpServletResponse;
+
+public final class ResponseUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ResponseUtils.class);
+
+  private ResponseUtils() {
+    // utils class
+  }
+
+  public static void ensureNoCacheHeader(final FacesContext facesContext) {
+    final Object response = facesContext.getExternalContext().getResponse();
+    if (response instanceof HttpServletResponse) {
+      ensureNoCacheHeader((HttpServletResponse) response);
+    } else if (PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse) {
+      ensureNoCacheHeader((MimeResponse) response);
+    }
+  }
+
+  public static void ensureNoCacheHeader(final HttpServletResponse response) {
+    response.setHeader("Cache-Control", "no-cache,no-store,max-age=0,must-revalidate");
+    response.setHeader("Pragma", "no-cache");
+    response.setDateHeader("Expires", 0);
+    response.setDateHeader("max-age", 0);
+  }
+
+  public static void ensureNoCacheHeader(final MimeResponse response) {
+    // TODO validate this
+    response.getCacheControl().setExpirationTime(0);
+  }
+
+  public static void ensureContentTypeHeader(final FacesContext facesContext, final String contentType) {
+    final Object response = facesContext.getExternalContext().getResponse();
+    if (response instanceof HttpServletResponse) {
+      ensureContentTypeHeader((HttpServletResponse) response, contentType);
+    } else if (PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse) {
+      ensureContentTypeHeader((MimeResponse) response, contentType);
+    }
+  }
+
+  public static void ensureContentTypeHeader(final HttpServletResponse response, final String contentType) {
+    if (!response.containsHeader("Content-Type")) {
+      response.setContentType(contentType);
+    } else {
+      final String responseContentType = response.getContentType();
+      if (!StringUtils.equalsIgnoreCaseAndWhitespace(responseContentType, contentType)) {
+        response.setContentType(contentType);
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Response already contains Header Content-Type '" + responseContentType
+              + "'. Overwriting with '" + contentType + "'");
+        }
+      }
+    }
+  }
+
+  public static void ensureContentTypeHeader(final MimeResponse response, final String contentType) {
+    final String responseContentType = response.getContentType();
+    if (!StringUtils.equalsIgnoreCaseAndWhitespace(responseContentType, contentType)) {
+      response.setContentType(contentType);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Response already contains Header Content-Type '" + responseContentType
+            + "'. Overwriting with '" + contentType + "'");
+      }
+    }
+  }
+
+  public static void ensureContentSecurityPolicyHeader(
+      final FacesContext facesContext, final ContentSecurityPolicy contentSecurityPolicy) {
+    final Object response = facesContext.getExternalContext().getResponse();
+    if (response instanceof HttpServletResponse) {
+      final HttpServletResponse servletResponse = (HttpServletResponse) response;
+      final UserAgent userAgent = TobagoContext.getInstance(facesContext).getUserAgent();
+      final String[] cspHeaders;
+      switch (contentSecurityPolicy.getMode()) {
+        case OFF:
+          cspHeaders = new String[0];
+          break;
+        case ON:
+          cspHeaders = userAgent.getCspHeaders();
+          break;
+        case REPORT_ONLY:
+          cspHeaders = userAgent.getCspReportOnlyHeaders();
+          break;
+        default:
+          throw new IllegalArgumentException("Undefined mode: " + contentSecurityPolicy.getMode());
+      }
+      final StringBuilder builder = new StringBuilder();
+      for (final String directive : contentSecurityPolicy.getDirectiveList()) {
+        builder.append(directive);
+        builder.append(";");
+      }
+      final String value = builder.toString();
+      for (final String cspHeader : cspHeaders) {
+        servletResponse.setHeader(cspHeader, value);
+      }
+    } else if (PortletUtils.isPortletApiAvailable() && response instanceof MimeResponse) {
+     // TODO Portlet
+      if (contentSecurityPolicy.getMode() != ContentSecurityPolicy.Mode.OFF) {
+        LOG.warn("CSP not implemented for Portlet!");
+      }
+    }
+  }
+
+  public static void ensureNosniffHeader(final FacesContext facesContext) {
+    final Object response = facesContext.getExternalContext().getResponse();
+    if (response instanceof HttpServletResponse) {
+      final HttpServletResponse servletResponse = (HttpServletResponse) response;
+      ensureNosniffHeader(servletResponse);
+    }
+  }
+
+  public static void ensureNosniffHeader(final HttpServletResponse servletResponse) {
+    servletResponse.setHeader("X-Content-Type-Options", "nosniff");
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseWriterBuffer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseWriterBuffer.java
new file mode 100644
index 0000000..449b56d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/ResponseWriterBuffer.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * Buffering scheme: we use a tremendously simple buffering
+ * scheme that greatly reduces the number of calls into the
+ * Writer/PrintWriter.  In practice this has produced significant
+ * measured performance gains (at least in JDK 1.3.1).  We only
+ * support adding single characters to the buffer, so anytime
+ * multiple characters need to be written out, the entire buffer
+ * gets flushed.  In practice, this is good enough, and keeps
+ * the core simple.
+ */
+public class ResponseWriterBuffer {
+
+  private static final int BUFFER_SIZE = 64;
+
+  private final char[] buff = new char[BUFFER_SIZE];
+
+  private int bufferIndex;
+
+  private final Writer writer;
+
+  public ResponseWriterBuffer(final Writer writer) {
+    this.writer = writer;
+  }
+
+  /**
+   * Add a character to the buffer, flushing the buffer if the buffer is
+   * full, and returning the new buffer index
+   */
+  public void addToBuffer(final char ch) throws IOException {
+    if (bufferIndex >= BUFFER_SIZE) {
+      writer.write(buff, 0, bufferIndex);
+      bufferIndex = 0;
+    }
+
+    buff[bufferIndex++] = ch;
+  }
+
+  public void addToBuffer(final char[] ch) throws IOException {
+    if (bufferIndex + ch.length >= BUFFER_SIZE) {
+      writer.write(buff, 0, bufferIndex);
+      bufferIndex = 0;
+    }
+
+    System.arraycopy(ch, 0, buff, bufferIndex, ch.length);
+    bufferIndex += ch.length;
+  }
+
+  /**
+   * Flush the contents of the buffer to the output stream
+   * and return the reset buffer index
+   */
+  public void flushBuffer() throws IOException {
+    if (bufferIndex > 0) {
+      writer.write(buff, 0, bufferIndex);
+    }
+    bufferIndex = 0;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/SelectItemUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/SelectItemUtils.java
new file mode 100644
index 0000000..6a46812
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/SelectItemUtils.java
@@ -0,0 +1,282 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UISelectItem;
+import javax.faces.component.UISelectItems;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.lang.reflect.Array;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+/**
+ * Based on code from MyFaces core.
+ */
+public class SelectItemUtils {
+
+  /**
+   * Creates a list of SelectItems to use for rendering.
+   */
+  public static Iterable<SelectItem> getItemIterator(final FacesContext facesContext, final UIComponent selector) {
+    if (selector.getChildCount() == 0) {
+      return Collections.emptyList();
+    } else {
+      return new Iterable<SelectItem>() {
+
+        private SelectItemsIterator iterator;
+
+        @Override
+        public Iterator<SelectItem> iterator() {
+          if (iterator == null) {
+            iterator = new SelectItemsIterator(facesContext, selector);
+          }
+          return iterator;
+        }
+      };
+    }
+  }
+
+  /**
+   * Creates a list of SelectItems to use for rendering.
+   * You should only use this method (which returns a list), when you need a list.
+   * Otherwise please use {@link #getItemIterator(javax.faces.context.FacesContext, javax.faces.component.UIComponent)}
+   */
+  public static List<SelectItem> getItemList(final FacesContext facesContext, final UIComponent selector) {
+    if (selector.getChildCount() == 0) {
+      return Collections.emptyList();
+    } else {
+      final Iterable<SelectItem> iterator = getItemIterator(facesContext, selector);
+      final List<SelectItem> result = new ArrayList<SelectItem>();
+      for (SelectItem selectItem : iterator) {
+        result.add(selectItem);
+      }
+      return result;
+    }
+  }
+
+  private static class SelectItemsIterator implements Iterator<SelectItem> {
+
+    private final FacesContext facesContext;
+    private final Iterator<UIComponent> children;
+    private Iterator<?> nestedItems;
+    private SelectItem nextItem;
+    private UISelectItems currentUISelectItems;
+
+    private SelectItemsIterator(final FacesContext facesContext, final UIComponent selector) {
+      this.children = selector.getChildren().iterator();
+      this.facesContext = facesContext;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public boolean hasNext() {
+      if (nextItem != null) {
+        return true;
+      }
+      if (nestedItems != null) {
+        if (nestedItems.hasNext()) {
+          return true;
+        }
+        nestedItems = null;
+      }
+
+      UIComponent child = null;
+      while (children.hasNext()) {
+        final UIComponent c = children.next();
+        // When there is other components nested that does
+        // not extends from UISelectItem or UISelectItems
+        // the behavior for this iterator is just skip this
+        // element(s) until an element that extends from these
+        // classes are found. If there is no more elements
+        // that conform this condition, just return false.
+        if (c instanceof UISelectItem || c instanceof UISelectItems) {
+          child = c;
+          break;
+        }
+      }
+      if (child == null) {
+        return false;
+      }
+
+      if (child instanceof UISelectItem) {
+        final UISelectItem uiSelectItem = (UISelectItem) child;
+        Object item = uiSelectItem.getValue();
+        if (item == null) {
+          // no value attribute --> create the SelectItem out of the other attributes
+          final Object itemValue = uiSelectItem.getItemValue();
+          String label = uiSelectItem.getItemLabel();
+          final String description = uiSelectItem.getItemDescription();
+          final boolean disabled = uiSelectItem.isItemDisabled();
+//          boolean escape = uiSelectItem.isItemEscaped();
+//          boolean noSelectionOption = uiSelectItem.isNoSelectionOption();
+          if (label == null) {
+            label = itemValue.toString();
+          }
+          String image = null;
+          Markup markup = null;
+          if (uiSelectItem instanceof org.apache.myfaces.tobago.component.UISelectItem) {
+            org.apache.myfaces.tobago.component.UISelectItem tobagoSelectItem
+                = (org.apache.myfaces.tobago.component.UISelectItem) uiSelectItem;
+            image = tobagoSelectItem.getItemImage();
+            markup = tobagoSelectItem.getMarkup();
+          }
+          item = new org.apache.myfaces.tobago.model.SelectItem(itemValue, label, description, disabled, image, markup);
+        } else if (!(item instanceof SelectItem)) {
+          ValueExpression expression = uiSelectItem.getValueExpression("value");
+          throw new IllegalArgumentException("ValueExpression '"
+              + (expression == null ? null : expression.getExpressionString()) + "' of UISelectItem : "
+              + child + " does not reference an Object of type SelectItem");
+        }
+        nextItem = (SelectItem) item;
+        return true;
+      } else { // UISelectItems
+        currentUISelectItems = ((UISelectItems) child);
+        final Object value = currentUISelectItems.getValue();
+
+        if (value instanceof SelectItem) {
+          nextItem = (SelectItem) value;
+          return true;
+        } else if (value != null && value.getClass().isArray()) {
+          // value is any kind of array (primitive or non-primitive)
+          // --> we have to use class Array to get the values
+          final int length = Array.getLength(value);
+          final Collection<Object> items = new ArrayList<Object>(length);
+          for (int i = 0; i < length; i++) {
+            items.add(Array.get(value, i));
+          }
+          nestedItems = items.iterator();
+          return hasNext();
+        } else if (value instanceof Iterable) {
+          // value is Iterable --> Collection, DataModel,...
+          nestedItems = ((Iterable<?>) value).iterator();
+          return hasNext();
+        } else if (value instanceof Map) {
+          final Map<Object, Object> map = ((Map<Object, Object>) value);
+          final Collection<SelectItem> items = new ArrayList<SelectItem>(map.size());
+          for (Map.Entry<Object, Object> entry : map.entrySet()) {
+            items.add(new org.apache.myfaces.tobago.model.SelectItem(entry.getValue(), entry.getKey().toString()));
+          }
+          nestedItems = items.iterator();
+          return hasNext();
+        }
+      }
+      return false;
+    }
+
+    @Override
+    public SelectItem next() {
+      if (!hasNext()) {
+        throw new NoSuchElementException();
+      }
+      if (nextItem != null) {
+        final SelectItem value = nextItem;
+        nextItem = null;
+        return value;
+      }
+      if (nestedItems != null) {
+        Object item = nestedItems.next();
+
+        if (!(item instanceof SelectItem)) {
+          // check new params of SelectItems (since 2.0): itemValue, itemLabel, itemDescription,...
+          // Note that according to the spec UISelectItems does not provide Getter and Setter
+          // methods for this values, so we have to use the attribute map
+          final Map<String, Object> attributeMap = currentUISelectItems.getAttributes();
+
+          // write the current item into the request map under the key listed in var, if available
+          boolean wroteRequestMapVarValue = false;
+          Object oldRequestMapVarValue = null;
+          final String var = ComponentUtils.getStringAttribute(currentUISelectItems, Attributes.var);
+          if (var != null && !"".equals(var)) {
+            // save the current value of the key listed in var from the request map
+            oldRequestMapVarValue = facesContext.getExternalContext().getRequestMap().put(var, item);
+            wroteRequestMapVarValue = true;
+          }
+
+          // check the itemValue attribute
+          Object itemValue = ComponentUtils.getAttribute(currentUISelectItems, Attributes.itemValue);
+          if (itemValue == null) {
+            // the itemValue attribute was not provided
+            // --> use the current item as the itemValue
+            itemValue = item;
+          }
+
+          // Spec: When iterating over the select items, toString()
+          // must be called on the string rendered attribute values
+          Object itemLabel = ComponentUtils.getAttribute(currentUISelectItems, Attributes.itemLabel);
+          if (itemLabel == null) {
+            itemLabel = itemValue.toString();
+          } else {
+            itemLabel = itemLabel.toString();
+          }
+          Object itemDescription = ComponentUtils.getAttribute(currentUISelectItems, Attributes.itemDescription);
+          if (itemDescription != null) {
+            itemDescription = itemDescription.toString();
+          }
+          final Boolean itemDisabled
+              = ComponentUtils.getBooleanAttribute(currentUISelectItems, Attributes.itemDisabled, false);
+          final String itemImage = ComponentUtils.getStringAttribute(currentUISelectItems, Attributes.itemImage);
+          final Markup markup;
+          if (currentUISelectItems instanceof Visual) {
+            markup = ((Visual) currentUISelectItems).getMarkup();
+          } else {
+            markup = Markup.NULL;
+          }
+// TBD: should this be possible?
+//        Boolean itemLabelEscaped = getBooleanAttribute(currentUISelectItems, ITEM_LABEL_ESCAPED_PROP, true);
+// TBD ?
+//        Object noSelectionValue = attributeMap.get(NO_SELECTION_VALUE_PROP);
+          item = new org.apache.myfaces.tobago.model.SelectItem(
+              itemValue, (String) itemLabel, (String) itemDescription, itemDisabled, itemImage, markup);
+
+          // remove the value with the key from var from the request map, if previously written
+          if (wroteRequestMapVarValue) {
+            // If there was a previous value stored with the key from var in the request map, restore it
+            if (oldRequestMapVarValue != null) {
+              facesContext.getExternalContext().getRequestMap().put(var, oldRequestMapVarValue);
+            } else {
+              facesContext.getExternalContext().getRequestMap().remove(var);
+            }
+          }
+        }
+        return (SelectItem) item;
+      }
+      throw new NoSuchElementException();
+    }
+
+    @Override
+    public void remove() {
+      throw new UnsupportedOperationException();
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/StringUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/StringUtils.java
new file mode 100644
index 0000000..b25ff61
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/StringUtils.java
@@ -0,0 +1,581 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.StringTokenizer;
+
+public final class StringUtils {
+
+  private StringUtils() {
+    // utils class
+  }
+
+  public static List<Integer> parseIntegerList(final String integerList) throws NumberFormatException {
+    return parseIntegerList(integerList, ", ");
+  }
+
+  public static List<Integer> parseIntegerList(final String integerList, final String delimiters)
+      throws NumberFormatException {
+    final List<Integer> list = new ArrayList<Integer>();
+
+    final StringTokenizer tokenizer = new StringTokenizer(integerList, delimiters);
+    while (tokenizer.hasMoreElements()) {
+      final String token = tokenizer.nextToken().trim();
+      if (token.length() > 0) {
+        list.add(new Integer(token));
+      }
+    }
+
+    return list;
+  }
+
+  public static <T> String joinWithSurroundingSeparator(final List<T> list) {
+    final StringBuilder buffer = new StringBuilder(",");
+    if (list != null) {
+      for (final T t : list) {
+        buffer.append(t);
+        buffer.append(",");
+      }
+    }
+    return buffer.toString();
+  }
+
+  public static int[] getIndices(final String list) {
+    final List<String> indexList = new ArrayList<String>();
+    final StringTokenizer st = new StringTokenizer(list, ",");
+    while (st.hasMoreTokens()) {
+      final String token = st.nextToken().trim();
+      final int idx = token.indexOf('-');
+      if (idx == -1) {
+        indexList.add(token);
+      } else {
+        final int start = Integer.parseInt(token.substring(0, idx).trim());
+        final int end = Integer.parseInt(token.substring(idx + 1).trim());
+        if (start < end) {
+          for (int i = start; i < end + 1; i++) {
+            indexList.add(Integer.toString(i));
+          }
+        } else {
+          for (int i = start; i > end - 1; i--) {
+            indexList.add(Integer.toString(i));
+          }
+        }
+      }
+    }
+
+    final int[] indices = new int[indexList.size()];
+    for (int i = 0; i < indices.length; i++) {
+      indices[i] = Integer.parseInt(indexList.get(i));
+    }
+    return indices;
+  }
+
+  public static String constantToLowerCamelCase(final String constant) {
+    final StringBuilder builder = new StringBuilder(constantToUpperCamelCase(constant));
+    if (builder.length() > 0) {
+      builder.setCharAt(0, Character.toLowerCase(builder.charAt(0)));
+    }
+    return builder.toString();
+  }
+
+  public static String constantToUpperCamelCase(final String constant) {
+    final StringBuilder builder = new StringBuilder(constant.length());
+    final char[] chars = constant.toCharArray();
+    for (int i = 0; i < chars.length; i++) {
+      if (i == 0) {
+        builder.append(chars[i]);
+      } else if (chars[i] == '_') {
+        builder.append(chars[++i]);
+      } else {
+        builder.append((((Character) chars[i]).toString().toLowerCase(Locale.ENGLISH)));
+      }
+    }
+    return builder.toString();
+  }
+
+  public static String firstToUpperCase(final String string) {
+    return string.substring(0, 1).toUpperCase(Locale.ENGLISH) + string.substring(1);
+  }
+
+  /**
+   * Is the same string, by ignoring differences that are only whitespaces.
+   * (null and "" are not equal)
+   */
+  @SuppressWarnings("StringEquality")
+  public static boolean equalsIgnoreCaseAndWhitespace(final String type1, final String type2) {
+
+    // StringEquality
+    if (type1 == type2) {
+      return true;
+    }
+
+    if (type1 == null || type2 == null) {
+      return false;
+    }
+
+    final char[] chars1 = type1.toCharArray();
+    final char[] chars2 = type2.toCharArray();
+    final int length1 = chars1.length;
+    final int length = chars2.length;
+
+    int i = 0;
+    int j = 0;
+
+    while (i < length1 && j < length) {
+      if (chars1[i] == chars2[j] || Character.toUpperCase(chars1[i]) == Character.toUpperCase(chars2[j])) {
+        i++;
+        j++;
+        // okay
+      } else if (Character.isWhitespace(chars1[i])) {
+        i++;
+        // okay, ignore space
+      } else if (Character.isWhitespace(chars2[j])) {
+        j++;
+        // try again
+      } else {
+        return false;
+      }
+    }
+
+    while (i < length1) {
+      if (Character.isWhitespace(chars1[i])) {
+        i++;
+        // okay, ignore space
+      } else {
+        return false;
+      }
+    }
+
+    while (j < length) {
+      if (Character.isWhitespace(chars2[j])) {
+        j++;
+        // okay, ignore space
+      } else {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean endsWith(final String string, final String suffix) {
+    if (string == null || suffix == null) {
+      return (string == null && suffix == null);
+    }
+    if (suffix.length() > string.length()) {
+      return false;
+    }
+    final int strOffset = string.length() - suffix.length();
+    return string.regionMatches(false, strOffset, suffix, 0, suffix.length());
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static String[] split(final String string, final char separator) {
+    // Performance tuned for 2.0 (JDK1.4)
+
+    if (string == null) {
+      return null;
+    }
+    final int len = string.length();
+    if (len == 0) {
+      return ArrayUtils.EMPTY_STRING_ARRAY;
+    }
+    final List<String> list = new ArrayList<String>();
+    int i = 0;
+    int start = 0;
+    boolean match = false;
+    while (i < len) {
+      if (string.charAt(i) == separator) {
+        if (match) {
+          list.add(string.substring(start, i));
+          match = false;
+        }
+        start = ++i;
+        continue;
+      }
+      match = true;
+      i++;
+    }
+    if (match) {
+      list.add(string.substring(start, i));
+    }
+    return list.toArray(new String[list.size()]);
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static String[] split(final String string, final String separator) {
+    final int max = -1;
+    // Performance tuned for 2.0 (JDK1.4)
+    // Direct code is quicker than StringTokenizer.
+    // Also, StringTokenizer uses isSpace() not isWhitespace()
+
+    if (string == null) {
+      return null;
+    }
+    final int len = string.length();
+    if (len == 0) {
+      return ArrayUtils.EMPTY_STRING_ARRAY;
+    }
+    final List<String> list = new ArrayList<String>();
+    int sizePlus1 = 1;
+    int i = 0;
+    int start = 0;
+    boolean match = false;
+    if (separator == null) {
+      // Null separator means use whitespace
+      while (i < len) {
+        if (Character.isWhitespace(string.charAt(i))) {
+          if (match) {
+            if (sizePlus1++ == max) {
+              i = len;
+            }
+            list.add(string.substring(start, i));
+            match = false;
+          }
+          start = ++i;
+          continue;
+        }
+        match = true;
+        i++;
+      }
+    } else if (separator.length() == 1) {
+      // Optimise 1 character case
+      final char sep = separator.charAt(0);
+      while (i < len) {
+        if (string.charAt(i) == sep) {
+          if (match) {
+            if (sizePlus1++ == max) {
+              i = len;
+            }
+            list.add(string.substring(start, i));
+            match = false;
+          }
+          start = ++i;
+          continue;
+        }
+        match = true;
+        i++;
+      }
+    } else {
+      // standard case
+      while (i < len) {
+        if (separator.indexOf(string.charAt(i)) >= 0) {
+          if (match) {
+            if (sizePlus1++ == max) {
+              i = len;
+            }
+            list.add(string.substring(start, i));
+            match = false;
+          }
+          start = ++i;
+          continue;
+        }
+        match = true;
+        i++;
+      }
+    }
+    if (match) {
+      list.add(string.substring(start, i));
+    }
+    return list.toArray(new String[list.size()]);
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean isAlpha(final String string) {
+    if (string == null) {
+      return false;
+    }
+    final int sz = string.length();
+    for (int i = 0; i < sz; i++) {
+      if (!Character.isLetter(string.charAt(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean isEmpty(final String value) {
+    return value == null || value.length() == 0;
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean isNotEmpty(final String value) {
+    return !isEmpty(value);
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean isBlank(final String string) {
+    if (string == null) {
+      return true;
+    }
+    final int strLen = string.length();
+    if (strLen == 0) {
+      return true;
+    }
+    for (int i = 0; i < strLen; i++) {
+      if ((!Character.isWhitespace(string.charAt(i)))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean isNotBlank(final String str) {
+    return !isBlank(str);
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static String replace(final String text, final String searchString, final String replacement) {
+    int max = -1;
+    if (isEmpty(text) || isEmpty(searchString) || replacement == null) {
+      return text;
+    }
+    int start = 0;
+    int end = text.indexOf(searchString, start);
+    if (end == -1) {
+      return text;
+    }
+    final int replLength = searchString.length();
+    int increase = replacement.length() - replLength;
+    increase = (increase < 0 ? 0 : increase);
+    increase *= (max < 0 ? 16 : (max > 64 ? 64 : max));
+    final StringBuilder buf = new StringBuilder(text.length() + increase);
+    while (end != -1) {
+      buf.append(text.substring(start, end)).append(replacement);
+      start = end + replLength;
+      if (--max == 0) {
+        break;
+      }
+      end = text.indexOf(searchString, start);
+    }
+    buf.append(text.substring(start));
+    return buf.toString();
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static String repeat(final String str, final int repeat) {
+    final int outputLength = str.length() * repeat;
+    final StringBuilder buf = new StringBuilder(outputLength);
+    for (int i = 0; i < repeat; i++) {
+      buf.append(str);
+    }
+    return buf.toString();
+  }
+
+  /**
+   * Returns a string of the same length to hide confidential passwords from log files etc.
+   */
+  public static String toConfidentialString(final String string, final boolean confidential) {
+    if (string == null) {
+      return "<null>";
+    } else if (confidential) {
+      return repeat("*", string.length()) + " (confidential)";
+    } else {
+      return string;
+    }
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static String uncapitalize(final String str) {
+    return String.valueOf(Character.toLowerCase(str.charAt(0))) + str.substring(1);
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean isAlphanumeric(final String str) {
+    final int sz = str.length();
+    for (int i = 0; i < sz; i++) {
+      if (!Character.isLetterOrDigit(str.charAt(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static String join(final List<String> list, final char separator) {
+    final int size = list.size();
+    if (size <= 0) {
+      return "";
+    }
+
+    final int bufSize = size * list.get(0).length() + 1;
+    final StringBuilder builder = new StringBuilder(bufSize);
+
+    for (int i = 0; i < size; i++) {
+      if (i > 0) {
+        builder.append(separator);
+      }
+      final String string = list.get(i);
+      if (string != null) {
+        builder.append(string);
+      }
+    }
+    return builder.toString();
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static String defaultString(final String string) {
+    return string == null ? "" : string;
+  }
+
+  /**
+   * Basically taken from commons-lang
+   */
+  public static boolean notEquals(String a, String b) {
+    return a == null ? b != null : !a.equals(b);
+  }
+
+  /**
+   * Checks if the String starts like a url, e.g. http: or xyz:
+   */
+  public static boolean isUrl(final String link) {
+    if (link == null) {
+      return false;
+    }
+    int colon = link.indexOf(':');
+    if (colon < 1) {
+      return false;
+    }
+    for (int i = 0; i < colon; i++) {
+      if (!Character.isLetter(link.charAt(i))) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  public static boolean startsWith(String string, String prefix) {
+    if (string == null || prefix == null) {
+      return (string == null && prefix == null);
+    }
+    if (prefix.length() > string.length()) {
+      return false;
+    }
+    return string.regionMatches(0, prefix, 0, prefix.length());
+  }
+
+  /**
+   * <p>
+   * Checks if the String contains any character in the given set of characters.
+   * </p>
+   *
+   * <p>
+   * A <code>null</code> String will return <code>false</code>. A <code>null</code> search string will return
+   * <code>false</code>.
+   * </p>
+   *
+   * <pre>
+   * StringUtils.containsAny(null, *)            = false
+   * StringUtils.containsAny("", *)              = false
+   * StringUtils.containsAny(*, null)            = false
+   * StringUtils.containsAny(*, "")              = false
+   * StringUtils.containsAny("zzabyycdxx", "za") = true
+   * StringUtils.containsAny("zzabyycdxx", "by") = true
+   * StringUtils.containsAny("aba","z")          = false
+   * </pre>
+   *
+   * @param str the String to check, may be null
+   * @param searchChars the chars to search for, may be null
+   * @return the <code>true</code> if any of the chars are found, <code>false</code> if no match or null input
+   *
+   * Basically taken from commons-lang
+   */
+  public static boolean containsAny(String str, String searchChars) {
+    if (searchChars == null) {
+      return false;
+    }
+    char[] searchChars1 = searchChars.toCharArray();
+    if (isEmpty(str) || searchChars1.length == 0) {
+      return false;
+    }
+    int csLength = str.length();
+    int searchLength = searchChars1.length;
+    int csLast = csLength - 1;
+    int searchLast = searchLength - 1;
+    for (int i = 0; i < csLength; i++) {
+      char ch = str.charAt(i);
+      for (int j = 0; j < searchLength; j++) {
+        if (searchChars1[j] == ch) {
+          if (isHighSurrogate(ch)) {
+            if (j == searchLast) {
+              // missing low surrogate, fine, like String.indexOf(String)
+              return true;
+            }
+            if (i < csLast && searchChars1[j + 1] == str.charAt(i + 1)) {
+              return true;
+            }
+          } else {
+            // ch is in the Basic Multilingual Plane
+            return true;
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  /**
+   * Indicates whether {@code ch} is a high- (or leading-) surrogate code unit
+   * that is used for representing supplementary characters in UTF-16
+   * encoding.
+   *
+   * @param ch the character to test.
+   * @return {@code true} if {@code ch} is a high-surrogate code unit;
+   *         {@code false} otherwise.
+   */
+  private static boolean isHighSurrogate(char ch) {
+    return ('\uD800' <= ch && '\uDBFF' >= ch);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/WriterUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/WriterUtils.java
new file mode 100644
index 0000000..753f0bc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/util/WriterUtils.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import java.io.IOException;
+import java.io.Writer;
+
+public abstract class WriterUtils {
+  protected static final char[] EMPTY = new char[0];
+  //
+  // Entities from HTML 4.0, section 24.2.1; character codes 0xA0 to 0xFF
+  //
+  protected static final char[][] ISO8859_1_ENTITIES = new char[][]{
+      "nbsp".toCharArray(),
+      "iexcl".toCharArray(),
+      "cent".toCharArray(),
+      "pound".toCharArray(),
+      "curren".toCharArray(),
+      "yen".toCharArray(),
+      "brvbar".toCharArray(),
+      "sect".toCharArray(),
+      "uml".toCharArray(),
+      "copy".toCharArray(),
+      "ordf".toCharArray(),
+      "laquo".toCharArray(),
+      "not".toCharArray(),
+      "shy".toCharArray(),
+      "reg".toCharArray(),
+      "macr".toCharArray(),
+      "deg".toCharArray(),
+      "plusmn".toCharArray(),
+      "sup2".toCharArray(),
+      "sup3".toCharArray(),
+      "acute".toCharArray(),
+      "micro".toCharArray(),
+      "para".toCharArray(),
+      "middot".toCharArray(),
+      "cedil".toCharArray(),
+      "sup1".toCharArray(),
+      "ordm".toCharArray(),
+      "raquo".toCharArray(),
+      "frac14".toCharArray(),
+      "frac12".toCharArray(),
+      "frac34".toCharArray(),
+      "iquest".toCharArray(),
+      "Agrave".toCharArray(),
+      "Aacute".toCharArray(),
+      "Acirc".toCharArray(),
+      "Atilde".toCharArray(),
+      "Auml".toCharArray(),
+      "Aring".toCharArray(),
+      "AElig".toCharArray(),
+      "Ccedil".toCharArray(),
+      "Egrave".toCharArray(),
+      "Eacute".toCharArray(),
+      "Ecirc".toCharArray(),
+      "Euml".toCharArray(),
+      "Igrave".toCharArray(),
+      "Iacute".toCharArray(),
+      "Icirc".toCharArray(),
+      "Iuml".toCharArray(),
+      "ETH".toCharArray(),
+      "Ntilde".toCharArray(),
+      "Ograve".toCharArray(),
+      "Oacute".toCharArray(),
+      "Ocirc".toCharArray(),
+      "Otilde".toCharArray(),
+      "Ouml".toCharArray(),
+      "times".toCharArray(),
+      "Oslash".toCharArray(),
+      "Ugrave".toCharArray(),
+      "Uacute".toCharArray(),
+      "Ucirc".toCharArray(),
+      "Uuml".toCharArray(),
+      "Yacute".toCharArray(),
+      "THORN".toCharArray(),
+      "szlig".toCharArray(),
+      "agrave".toCharArray(),
+      "aacute".toCharArray(),
+      "acirc".toCharArray(),
+      "atilde".toCharArray(),
+      "auml".toCharArray(),
+      "aring".toCharArray(),
+      "aelig".toCharArray(),
+      "ccedil".toCharArray(),
+      "egrave".toCharArray(),
+      "eacute".toCharArray(),
+      "ecirc".toCharArray(),
+      "euml".toCharArray(),
+      "igrave".toCharArray(),
+      "iacute".toCharArray(),
+      "icirc".toCharArray(),
+      "iuml".toCharArray(),
+      "eth".toCharArray(),
+      "ntilde".toCharArray(),
+      "ograve".toCharArray(),
+      "oacute".toCharArray(),
+      "ocirc".toCharArray(),
+      "otilde".toCharArray(),
+      "ouml".toCharArray(),
+      "divide".toCharArray(),
+      "oslash".toCharArray(),
+      "ugrave".toCharArray(),
+      "uacute".toCharArray(),
+      "ucirc".toCharArray(),
+      "uuml".toCharArray(),
+      "yacute".toCharArray(),
+      "thorn".toCharArray(),
+      "yuml".toCharArray()
+  };
+  private final Writer out;
+  private final ResponseWriterBuffer buffer;
+  private final boolean utf8;
+
+  public WriterUtils(final Writer out, final String characterEncoding) {
+    this.out = out;
+    buffer = new ResponseWriterBuffer(out);
+    utf8 = "utf-8".equalsIgnoreCase(characterEncoding);
+  }
+
+  public void writeAttributeValue(final String text)
+      throws IOException {
+    writeEncodedValue(text.toCharArray(), 0, text.length(), true);
+  }
+
+  public void writeText(final String text) throws IOException {
+    writeEncodedValue(text.toCharArray(), 0, text.length(), false);
+  }
+
+  public void writeText(final char[] text, final int start, final int length)
+      throws IOException {
+    writeEncodedValue(text, start, length, false);
+  }
+
+  protected abstract void writeEncodedValue(char[] text, int start,
+                                            int length, boolean isAttribute)
+      throws IOException;
+
+  /**
+   * Writes a character as a decimal escape.  Hex escapes are smaller than
+   * the decimal version, but Netscape didn't support hex escapes until
+   * 4.7.4.
+   */
+  protected void writeDecRef(final char ch) throws IOException {
+    if (ch == '\u20ac') {
+      out.write("&euro;");
+      return;
+    }
+    out.write("&#");
+    // Formerly used String.valueOf().  This version tests out
+    // about 40% faster in a microbenchmark (and on systems where GC is
+    // going gonzo, it should be even better)
+    int i = (int) ch;
+    if (i > 10000) {
+      out.write('0' + (i / 10000));
+      i = i % 10000;
+      out.write('0' + (i / 1000));
+      i = i % 1000;
+      out.write('0' + (i / 100));
+      i = i % 100;
+      out.write('0' + (i / 10));
+      i = i % 10;
+      out.write('0' + i);
+    } else if (i > 1000) {
+      out.write('0' + (i / 1000));
+      i = i % 1000;
+      out.write('0' + (i / 100));
+      i = i % 100;
+      out.write('0' + (i / 10));
+      i = i % 10;
+      out.write('0' + i);
+    } else {
+      out.write('0' + (i / 100));
+      i = i % 100;
+      out.write('0' + (i / 10));
+      i = i % 10;
+      out.write('0' + i);
+    }
+
+    out.write(';');
+  }
+
+  protected final Writer getOut() {
+    return out;
+  }
+
+  protected final ResponseWriterBuffer getBuffer() {
+    return buffer;
+  }
+
+  protected final boolean isUtf8() {
+    return utf8;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugContentTypeFilter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugContentTypeFilter.java
new file mode 100644
index 0000000..42d31fa
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugContentTypeFilter.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+public class DebugContentTypeFilter implements Filter {
+  private static final Logger LOG = LoggerFactory.getLogger(DebugContentTypeFilter.class);
+
+  @Override
+  public void init(final FilterConfig filterConfig) throws ServletException {
+    if (LOG.isInfoEnabled()) {
+      LOG.info("init " + getClass().getName());
+    }
+  }
+
+  @Override
+  public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+      throws IOException, ServletException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("do Filter " + getClass().getName());
+    }
+    if (response instanceof HttpServletResponse) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("wrapping response " + getClass().getName());
+      }
+      chain.doFilter(request, new DebugContentTypeResponse((HttpServletResponse) response));
+    } else {
+      chain.doFilter(request, response);
+    }
+  }
+
+  @Override
+  public void destroy() {
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugContentTypeResponse.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugContentTypeResponse.java
new file mode 100644
index 0000000..59dd9fd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugContentTypeResponse.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+public class DebugContentTypeResponse extends HttpServletResponseWrapper {
+  private static final Logger LOG = LoggerFactory.getLogger(DebugContentTypeResponse.class);
+
+  public DebugContentTypeResponse(final HttpServletResponse response) {
+    super(response);
+  }
+
+  @Override
+  public void setContentType(final String type) {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Setting Content-Type to '" + type + "'.", new Exception());
+    }
+    super.setContentType(type);
+  }
+
+  @Override
+  public String getContentType() {
+    final String type = super.getContentType();
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Getting Content-Type '" + type + "'.", new Exception());
+    }
+    return type;
+  }
+
+  @Override
+  public void setHeader(final String name, final String value) {
+    if ("Content-Type".equals(name)) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Setting Content-Type to '" + value + "'.", new Exception());
+      }
+    }
+    super.setHeader(name, value);
+  }
+
+  @Override
+  public void addHeader(final String name, final String value) {
+    if ("Content-Type".equals(name)) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Setting Content-Type to '" + value + "'.", new Exception());
+      }
+    }
+    super.addHeader(name, value);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugResponseWriterWrapper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugResponseWriterWrapper.java
new file mode 100644
index 0000000..abc255f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/DebugResponseWriterWrapper.java
@@ -0,0 +1,228 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlTypes;
+import org.apache.myfaces.tobago.renderkit.html.MarkupLanguageAttributes;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.EmptyStackException;
+import java.util.Stack;
+
+public class DebugResponseWriterWrapper extends TobagoResponseWriter {
+
+  private Stack<Object> stack = new Stack<Object>();
+
+  private static final Logger LOG = LoggerFactory.getLogger(DebugResponseWriterWrapper.class);
+
+  private final TobagoResponseWriter responseWriter;
+
+  public DebugResponseWriterWrapper(final TobagoResponseWriter responseWriter) {
+    this.responseWriter = responseWriter;
+  }
+
+  @Override
+  public void write(final String string) throws IOException {
+    responseWriter.write(string);
+  }
+
+  @Override
+  public void writeComment(final Object comment) throws IOException {
+    String commentStr = comment.toString();
+    if (commentStr.indexOf("--") > 0) {
+      LOG.error("Comment must not contain the sequence '--', comment = '" + comment + "'.",
+          new IllegalArgumentException());
+
+      commentStr = StringUtils.replace(commentStr, "--", "++");
+    }
+    responseWriter.writeComment(commentStr);
+  }
+
+  @Override
+  public ResponseWriter cloneWithWriter(final Writer writer) {
+    return new DebugResponseWriterWrapper((TobagoResponseWriter) responseWriter.cloneWithWriter(writer));
+  }
+
+  @Override
+  @Deprecated
+  public void writeAttribute(final String name, final Object value, final String property) throws IOException {
+    responseWriter.writeAttribute(name, value, property);
+  }
+
+  @Override
+  @Deprecated
+  public void writeText(final Object text, final String property) throws IOException {
+    responseWriter.writeText(text, property);
+  }
+
+  @Override
+  public void flush() throws IOException {
+    responseWriter.flush();
+  }
+
+  @Override
+  public void writeAttribute(final MarkupLanguageAttributes name, final String value, final boolean escape)
+      throws IOException {
+    responseWriter.writeAttribute(name, value, escape);
+  }
+
+  @Override
+  public void writeAttribute(final MarkupLanguageAttributes name, final HtmlTypes types) throws IOException {
+    responseWriter.writeAttribute(name, types);
+  }
+
+  @Override
+  public void writeURIAttribute(MarkupLanguageAttributes name, String string) throws IOException {
+    responseWriter.writeURIAttribute(name, string);
+  }
+
+  @Override
+  public String getContentType() {
+    return responseWriter.getContentType();
+  }
+
+  @Override
+  public String getCharacterEncoding() {
+    return responseWriter.getCharacterEncoding();
+  }
+
+  @Override
+  public void startDocument() throws IOException {
+    responseWriter.startDocument();
+  }
+
+  @Override
+  public void endDocument() throws IOException {
+    responseWriter.endDocument();
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  @Override
+  public void writeJavascript(final String script) throws IOException {
+    responseWriter.writeJavascript(script);
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  @Override
+  public void endJavascript() throws IOException {
+    responseWriter.endJavascript();
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  @Override
+  public void startJavascript() throws IOException {
+    responseWriter.startJavascript();
+  }
+
+  @Override
+  public void writeURIAttribute(final String name, final Object value, final String property) throws IOException {
+    responseWriter.writeURIAttribute(name, value, property);
+  }
+
+  @Override
+  public void writeText(final char[] text, final int off, final int len) throws IOException {
+    responseWriter.writeText(text, off, len);
+  }
+
+  @Override
+  public void write(final char[] chars, final int i, final int i1) throws IOException {
+    responseWriter.write(chars, i, i1);
+  }
+
+  @Override
+  public void close() throws IOException {
+    responseWriter.close();
+  }
+
+  @Override
+  public void startElement(final String name, final UIComponent currentComponent) throws IOException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("start element: '" + name + "'");
+    }
+    stack.push(name);
+    responseWriter.startElement(name, currentComponent);
+  }
+
+  @Override
+  public void startElement(final HtmlElements name) throws IOException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("start element: '" + name + "'");
+    }
+    stack.push(name);
+    responseWriter.startElement(name);
+  }
+
+  @Override
+  public void endElement(final String name) throws IOException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("end element: '" + name + "'");
+    }
+    Object top;
+    try {
+      top = stack.pop();
+    } catch (final EmptyStackException e) {
+      LOG.error("Failed to close element \"" + name + "\"!", e);
+      top = "*** failure ***";
+    }
+
+    if (!top.equals(name)) {
+      LOG.error("Element end with name='" + name + "' doesn't match with top element on the stack='" + top + "'.",
+          new IllegalArgumentException());
+    }
+    responseWriter.endElement(name);
+  }
+
+  @Override
+  public void endElement(final HtmlElements name) throws IOException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("end element: '" + name + "'");
+    }
+    Object top;
+    try {
+      top = stack.pop();
+    } catch (final EmptyStackException e) {
+      LOG.error("Failed to close element \"" + name + "\"!", e);
+      top = "*** failure ***";
+    }
+
+    if (!top.equals(name)) {
+      LOG.error("Element end with name='" + name + "' doesn't match with top element on the stack='" + top + "'.",
+          new IllegalArgumentException());
+    }
+    responseWriter.endElement(name);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/HtmlResponseWriter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/HtmlResponseWriter.java
new file mode 100644
index 0000000..6f6b6fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/HtmlResponseWriter.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.apache.myfaces.tobago.internal.util.FastStringWriter;
+import org.apache.myfaces.tobago.internal.util.HtmlWriterUtils;
+import org.apache.myfaces.tobago.internal.util.JsonWriterUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.internal.util.WriterUtils;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+
+public class HtmlResponseWriter extends TobagoResponseWriterBase {
+
+  private static final String HTML_DOCTYPE = "<!DOCTYPE html>";
+
+  private final WriterUtils helper;
+  private FastStringWriter javascriptWriter;
+  private boolean javascriptMode;
+
+  public HtmlResponseWriter(
+      final Writer writer, final String contentType, final String characterEncoding) {
+    super(writer, contentType, characterEncoding);
+    if ("application/json".equals(contentType)) {
+      this.helper = new JsonWriterUtils(writer, characterEncoding);
+    } else {
+      this.helper = new HtmlWriterUtils(writer, characterEncoding);
+    }
+    this.javascriptWriter = new FastStringWriter();
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  @Override
+  public void endJavascript() throws IOException {
+    javascriptMode = false;
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  @Override
+  public void startJavascript() throws IOException {
+    javascriptMode = true;
+  }
+
+  @Override
+  public void write(final String string) throws IOException {
+    if (javascriptMode) {
+      writeJavascript(string);
+    } else {
+      writeInternal(getWriter(), string);
+    }
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  @Override
+  public void writeJavascript(final String script) throws IOException {
+    writeInternal(javascriptWriter, script);
+  }
+
+  public String getJavascript() {
+    return javascriptWriter.toString();
+  }
+
+  public final WriterUtils getHelper() {
+    return helper;
+  }
+
+  @Override
+  public void writeText(final Object text, final String property)
+      throws IOException {
+    closeOpenTag();
+    final String value = findValue(text, property);
+    helper.writeText(value);
+  }
+
+  @Override
+  public void writeText(final char[] text, final int offset, final int length)
+      throws IOException {
+    closeOpenTag();
+    helper.writeText(text, offset, length);
+  }
+
+  @Override
+  public void write(final char[] cbuf, final int off, final int len) throws IOException {
+    // Related to http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-696
+    if (Arrays.equals(cbuf, XML_VERSION_1_0_ENCODING_UTF_8_CHARS)) {
+      // drop
+    } else {
+      super.write(cbuf, off, len);
+    }
+  }
+
+  @Override
+  protected void closeEmptyTag() throws IOException {
+    getWriter().write(">");
+  }
+
+  @Override
+  protected void writerAttributeValue(final String value, final boolean escape) throws IOException {
+    if (escape) {
+      helper.writeAttributeValue(value);
+    } else {
+      getWriter().write(value);
+    }
+  }
+
+  @Override
+  public ResponseWriter cloneWithWriter(final Writer originalWriter) {
+    return new HtmlResponseWriter(
+        originalWriter, getContentType(), getCharacterEncoding());
+  }
+
+  @Override
+  public void startDocument() throws IOException {
+    getWriter().write(HTML_DOCTYPE);
+    getWriter().write('\n');
+  }
+
+  @Override
+  public void endElement(final String name) throws IOException {
+    if (name.equals(HtmlElements.BODY.getValue())) {
+      final String javascript = getJavascript();
+      if (StringUtils.isNotEmpty(javascript)) {
+        startElement(HtmlElements.SCRIPT);
+        writeAttribute(HtmlAttributes.TYPE, "text/javascript", false);
+        write(javascript);
+        super.endElement(HtmlElements.SCRIPT);
+      }
+    }
+    super.endElement(name);
+  }
+
+  @Override
+  public void endDocument() throws IOException {
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/LoggingMdcFilter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/LoggingMdcFilter.java
new file mode 100644
index 0000000..ac2c1ad
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/LoggingMdcFilter.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+public class LoggingMdcFilter implements Filter {
+  private static final Logger LOG = LoggerFactory.getLogger(LoggingMdcFilter.class);
+
+  @Override
+  public void init(final FilterConfig filterConfig) throws ServletException {
+    if (LOG.isInfoEnabled()) {
+      LOG.info("init " + getClass().getName());
+    }
+  }
+
+  @Override
+  public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+      throws IOException, ServletException {
+
+    try {
+      if (request instanceof HttpServletRequest) {
+        HttpServletRequest httpRequest = (HttpServletRequest) request;
+        HttpSession session = httpRequest.getSession(false);
+        if (session != null) {
+          MDC.put("sessionId", session.getId());
+        }
+        String remoteAddr = httpRequest.getRemoteAddr();
+        if (remoteAddr != null) {
+          MDC.put("ip", remoteAddr);
+        }
+        String remoteUser = httpRequest.getRemoteUser();
+        if (remoteUser != null) {
+          MDC.put("user", remoteUser);
+        }
+      }
+
+      chain.doFilter(request, response);
+
+    } finally {
+      MDC.clear();
+    }
+  }
+
+  @Override
+  public void destroy() {
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
new file mode 100644
index 0000000..1aab1f6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterBase.java
@@ -0,0 +1,369 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlTypes;
+import org.apache.myfaces.tobago.renderkit.html.MarkupLanguageAttributes;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.io.Writer;
+import java.net.URI;
+
+public abstract class TobagoResponseWriterBase extends TobagoResponseWriter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoResponseWriterBase.class);
+
+  protected static final String XML_VERSION_1_0_ENCODING_UTF_8 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+
+  protected static final char[] XML_VERSION_1_0_ENCODING_UTF_8_CHARS = XML_VERSION_1_0_ENCODING_UTF_8.toCharArray();
+
+  private int i = 0;
+
+  private int inlineStack = 0;
+
+  private UIComponent component;
+
+  private boolean startStillOpen;
+
+  private final Writer writer;
+
+  private final String contentType;
+
+  private final String characterEncoding;
+
+  private final boolean ajax;
+
+  protected TobagoResponseWriterBase(final Writer writer, final String contentType, final String characterEncoding) {
+    this.writer = writer;
+    this.contentType = contentType;
+    this.characterEncoding = characterEncoding != null ? characterEncoding : "UTF-8";
+    this.ajax = FacesContext.getCurrentInstance().getPartialViewContext().isPartialRequest();
+  }
+
+  protected final Writer getWriter() {
+    return writer;
+  }
+
+  protected final UIComponent getComponent() {
+    return component;
+  }
+
+  protected final void setComponent(final UIComponent component) {
+    this.component = component;
+  }
+
+  protected final boolean isStartStillOpen() {
+    return startStillOpen;
+  }
+
+  protected final void setStartStillOpen(final boolean startStillOpen) {
+    this.startStillOpen = startStillOpen;
+  }
+
+  protected final String findValue(final Object value, final String property) {
+    if (value != null) {
+      return value instanceof String ? (String) value : value.toString();
+    } else if (property != null) {
+      if (component != null) {
+        final Object object = component.getAttributes().get(property);
+        if (object != null) {
+          return object instanceof String ? (String) object : object.toString();
+        } else {
+          return null;
+        }
+      } else {
+        final String trace = getCallingClassStackTraceElementString();
+        LOG.warn("Don't know what to do! "
+            + "Property defined, but no component to get a value. (value=null, property='" + property + "') "
+            + trace.substring(trace.indexOf('(')));
+        return null;
+      }
+    } else {
+      final String trace = getCallingClassStackTraceElementString();
+      LOG.warn("Don't know what to do! "
+          + "No value and no property defined. (value=null, property=null)"
+          + trace.substring(trace.indexOf('(')));
+      return null;
+    }
+  }
+
+  @Override
+  public void write(final char[] cbuf, final int off, final int len)
+      throws IOException {
+    writer.write(cbuf, off, len);
+  }
+
+  @Override
+  public void write(final String string) throws IOException {
+    writeInternal(writer, string);
+  }
+
+  protected final void writeInternal(final Writer writer, final String string) throws IOException {
+    closeOpenTag();
+    writer.write(string);
+  }
+
+  @Override
+  public void write(final int i) throws IOException {
+    closeOpenTag();
+    writer.write(i);
+  }
+
+  @Override
+  public void write(final char[] chars) throws IOException {
+    closeOpenTag();
+    writer.write(chars);
+  }
+
+  @Override
+  public void write(final String string, final int i, final int i1) throws IOException {
+    closeOpenTag();
+    writer.write(string, i, i1);
+  }
+
+  @Override
+  public void close() throws IOException {
+    closeOpenTag();
+    writer.close();
+  }
+
+  @Override
+  public void flush() throws IOException {
+    /*
+    From the api:
+    Flush any ouput buffered by the output method to the underlying Writer or OutputStream.
+    This method will not flush the underlying Writer or OutputStream;
+    it simply clears any values buffered by this ResponseWriter.
+     */
+    closeOpenTag();
+  }
+
+  protected void closeOpenTag() throws IOException {
+    if (startStillOpen) {
+      writer.write(">");
+      startStillOpen = false;
+    }
+  }
+
+  @Override
+  public void startDocument() throws IOException {
+    // nothing to do
+  }
+
+  @Override
+  public void endDocument() throws IOException {
+    // nothing to do
+  }
+
+  @Override
+  public String getContentType() {
+    return contentType;
+  }
+
+  @Override
+  public String getCharacterEncoding() {
+    return characterEncoding;
+  }
+
+  @Override
+  public void startElement(final String name, final UIComponent currentComponent) throws IOException {
+    final boolean inline = HtmlElements.isInline(name);
+    if (inline) {
+      inlineStack++;
+    }
+    this.component = currentComponent;
+    startElementInternal(writer, name, HtmlElements.isInline(name));
+  }
+
+  @Override
+  public void startElement(final HtmlElements name) throws IOException {
+    final boolean inline = name.isInline();
+    if (inline) {
+      inlineStack++;
+    }
+    startElementInternal(writer, name.getValue(), name.isInline());
+    if (!name.isVoid()) {
+      i++;
+    }
+  }
+
+  protected void startElementInternal(final Writer writer, final String name, final boolean inline)
+      throws IOException {
+//    closeOpenTag();
+    if (startStillOpen) {
+      writer.write(">");
+    }
+    if (!ajax && inlineStack <= 1) {
+      writer.write("\n");
+      writer.write(StringUtils.repeat("  ", i));
+    }
+    writer.write("<");
+    writer.write(name);
+    startStillOpen = true;
+  }
+
+  @Override
+  public void endElement(final String name) throws IOException {
+    final boolean inline = HtmlElements.isInline(name);
+    if (HtmlElements.isVoid(name)) {
+      closeEmptyTag();
+    } else {
+      endElementInternal(writer, name, inline);
+    }
+    startStillOpen = false;
+    if (inline) {
+      inlineStack--;
+      assert inlineStack >= 0;
+    }
+  }
+
+  @Override
+  public void endElement(final HtmlElements name) throws IOException {
+    final boolean inline = name.isInline();
+    if (name.isVoid()) {
+      closeEmptyTag();
+    } else {
+      if (!name.isVoid()) {
+        i--;
+      }
+      endElementInternal(writer, name.getValue(), inline);
+    }
+    startStillOpen = false;
+    if (inline) {
+      inlineStack--;
+      assert inlineStack >= 0;
+    }
+  }
+
+  @Override
+  public void writeComment(final Object obj) throws IOException {
+    closeOpenTag();
+    final String comment = obj.toString();
+    if (!ajax) {
+      writer.write("\n");
+      writer.write(StringUtils.repeat("  ", i));
+    }
+    write("<!--");
+    write(comment);
+    write("-->");
+  }
+
+  @Override
+  @Deprecated
+  public void writeAttribute(final String name, final Object value, final String property)
+      throws IOException {
+
+    final String attribute = findValue(value, property);
+    writeAttribute(new MarkupLanguageAttributes() {
+      @Override
+      public String getValue() {
+          return name;
+      }
+    }, attribute, true);
+  }
+
+  protected final String getCallingClassStackTraceElementString() {
+    final StackTraceElement[] stackTrace = new Exception().getStackTrace();
+    int i = 1;
+    while (stackTrace[i].getClassName().contains("ResponseWriter")) {
+      i++;
+    }
+    return stackTrace[i].toString();
+  }
+
+  @Override
+  public void writeURIAttribute(final String name, final Object value, final String property)
+      throws IOException {
+    if (value != null) {
+      final URI uri = URI.create(value.toString());
+      writeAttribute(name, uri.toASCIIString(), property);
+    }
+  }
+
+// interface TobagoResponseWriter //////////////////////////////////////////////////////////////////////////////////
+
+  @Override
+  public void writeAttribute(final MarkupLanguageAttributes name, final String value, final boolean escape)
+      throws IOException {
+    writeAttributeInternal(writer, name, value, escape);
+  }
+
+  @Override
+  public void writeAttribute(final MarkupLanguageAttributes name, final HtmlTypes types) throws IOException {
+    writeAttributeInternal(writer, name, types.getValue(), false);
+  }
+
+  @Override
+  public void writeURIAttribute(final MarkupLanguageAttributes name, final String value)
+      throws IOException {
+    if (value != null) {
+      final URI uri = URI.create(value);
+      writeAttribute(name, uri.toASCIIString(), true);
+    }
+  }
+
+  protected void endElementInternal(final Writer writer, final String name, final boolean inline) throws IOException {
+    if (startStillOpen) {
+      writer.write(">");
+    }
+    if (inline || ajax) {
+      writer.write("</");
+    } else {
+      writer.write("\n" + StringUtils.repeat("  ", i) + "</");
+    }
+    writer.write(name);
+    writer.write(">");
+  }
+
+  protected abstract void closeEmptyTag() throws IOException;
+
+  protected void writeAttributeInternal(
+      final Writer writer, final MarkupLanguageAttributes name, final String value, final boolean escape)
+      throws IOException {
+    if (!startStillOpen) {
+      final String trace = getCallingClassStackTraceElementString();
+      final String error = "Cannot write attribute when start-tag not open. "
+          + "name = '" + name + "' "
+          + "value = '" + value + "' "
+          + trace.substring(trace.indexOf('('));
+      LOG.error(error);
+      throw new IllegalStateException(error);
+    }
+
+    if (value != null) {
+      writer.write(' ');
+      writer.write(name.getValue());
+      writer.write("='");
+      writerAttributeValue(value, escape);
+      writer.write('\'');
+    }
+  }
+  protected abstract void writerAttributeValue(String value, boolean escape) throws IOException;
+
+
+}
+
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java
new file mode 100644
index 0000000..d22b726
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/TobagoResponseWriterWrapper.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlTypes;
+import org.apache.myfaces.tobago.renderkit.html.MarkupLanguageAttributes;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+public class TobagoResponseWriterWrapper extends TobagoResponseWriter {
+
+  private ResponseWriter responseWriter;
+
+  public TobagoResponseWriterWrapper(final ResponseWriter responseWriter) {
+    this.responseWriter = responseWriter;
+  }
+
+  @Override
+  public void startElement(final String name, final UIComponent component) throws IOException {
+    responseWriter.startElement(name, component);
+  }
+
+  @Override
+  public void startElement(HtmlElements name) throws IOException {
+    responseWriter.startElement(name.getValue(), null);
+  }
+
+  @Override
+  public void endElement(final String name) throws IOException {
+    responseWriter.endElement(name);
+  }
+
+  @Override
+  public void endElement(HtmlElements name) throws IOException {
+    responseWriter.endElement(name.getValue());
+  }
+
+  @Override
+  public void write(final String string) throws IOException {
+    responseWriter.write(string);
+  }
+
+  @Override
+  public void writeComment(final Object comment) throws IOException {
+    responseWriter.writeComment(comment);
+  }
+
+  @Override
+  public ResponseWriter cloneWithWriter(final Writer writer) {
+    return responseWriter.cloneWithWriter(writer);
+  }
+
+  @Override
+  @Deprecated
+  public void writeAttribute(final String name, final Object value, final String property) throws IOException {
+    responseWriter.writeAttribute(name, value, property);
+  }
+
+  @Override
+  @Deprecated
+  public void writeText(final Object text, final String property) throws IOException {
+    responseWriter.writeText(text, property);
+  }
+
+  @Override
+  public void flush() throws IOException {
+    responseWriter.flush();
+  }
+
+  @Override
+  public void writeAttribute(final MarkupLanguageAttributes name, final String value, final boolean escape)
+      throws IOException {
+    if (value != null) {
+      responseWriter.writeAttribute(name.getValue(), value, null);
+    }
+  }
+
+  @Override
+  public void writeAttribute(final MarkupLanguageAttributes name, final HtmlTypes types)
+      throws IOException {
+    responseWriter.writeAttribute(name.getValue(), types.getValue(), null);
+  }
+
+  @Override
+  public String getContentType() {
+    return responseWriter.getContentType();
+  }
+
+  @Override
+  public String getCharacterEncoding() {
+    return responseWriter.getCharacterEncoding();
+  }
+
+  @Override
+  public void startDocument() throws IOException {
+    responseWriter.startDocument();
+  }
+
+  @Override
+  public void endDocument() throws IOException {
+    responseWriter.endDocument();
+  }
+
+  @Override
+  public void writeURIAttribute(final String name, final Object value, final String property) throws IOException {
+    responseWriter.writeURIAttribute(name, value, property);
+  }
+
+  @Override
+  public void writeURIAttribute(MarkupLanguageAttributes name, String string) throws IOException {
+    responseWriter.writeURIAttribute(name.getValue(), string, null);
+  }
+
+  @Override
+  public void writeText(final char[] text, final int off, final int len) throws IOException {
+    responseWriter.writeText(text, off, len);
+  }
+
+  @Override
+  public void write(final char[] chars, final int i, final int i1) throws IOException {
+    responseWriter.write(chars, i, i1);
+  }
+
+  @Override
+  public void close() throws IOException {
+    responseWriter.close();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/XmlResponseWriter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/XmlResponseWriter.java
new file mode 100644
index 0000000..b75cd53
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/internal/webapp/XmlResponseWriter.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.webapp;
+
+import org.apache.myfaces.tobago.util.XmlUtils;
+
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Arrays;
+
+public final class XmlResponseWriter extends TobagoResponseWriterBase {
+
+  private static final String XHTML_DOCTYPE =
+      "<!DOCTYPE html      PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\""
+          + "     \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">";
+
+  public XmlResponseWriter(
+      final Writer writer, final String contentType, final String characterEncoding) {
+    super(writer, contentType, characterEncoding);
+  }
+
+  @Override
+  public void writeText(final Object text, final String property)
+      throws IOException {
+    closeOpenTag();
+    final String value = findValue(text, property);
+    write(XmlUtils.escape(value));
+  }
+
+  @Override
+  public void writeText(final char[] text, final int offset, final int length)
+      throws IOException {
+    closeOpenTag();
+    getWriter().write(XmlUtils.escape(text, offset, length, true));
+  }
+
+  @Override
+  public void write(final char[] cbuf, final int off, final int len) throws IOException {
+    // Related to http://java.net/jira/browse/JAVASERVERFACES_SPEC_PUBLIC-696
+    if (Arrays.equals(cbuf, XML_VERSION_1_0_ENCODING_UTF_8_CHARS)) {
+      // drop
+    } else {
+      super.write(cbuf, off, len);
+    }
+  }
+
+  @Override
+  public ResponseWriter cloneWithWriter(final Writer originalWriter) {
+    return new XmlResponseWriter(
+        originalWriter, getContentType(), getCharacterEncoding());
+  }
+
+  @Override
+  public void closeEmptyTag() throws IOException {
+    getWriter().write("/>");
+  }
+
+  @Override
+  protected void writerAttributeValue(final String value, final boolean escape) throws IOException {
+    getWriter().write(XmlUtils.escape(value));
+  }
+
+  @Override
+  public void startDocument() throws IOException {
+//    getWriter().write(XHTML_DOCTYPE);
+//    getWriter().write('\n');
+//    startElement(HtmlElements.HTML);
+//    writeAttribute(HtmlAttributes.XMLNS, "http://www.w3.org/1999/xhtml", false);
+//
+  }
+
+  @Override
+  public void endDocument() throws IOException {
+//    endElement(HtmlElements.HTML);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AlignItems.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AlignItems.java
new file mode 100644
index 0000000..b5884a2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AlignItems.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public enum AlignItems {
+
+  flexStart,
+  flexEnd,
+  center,
+  baseline,
+  stretch;
+
+  public static final String FLEX_START = "flexStart";
+  public static final String FLEX_END = "flexEnd";
+  public static final String CENTER = "center";
+  public static final String BASELINE = "baseline";
+  public static final String STRETCH = "stretch";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AutoLayoutToken.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AutoLayoutToken.java
new file mode 100644
index 0000000..25a86e2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/AutoLayoutToken.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public final class AutoLayoutToken extends LayoutToken {
+  
+  public static final AutoLayoutToken INSTANCE = new AutoLayoutToken();
+
+  public String toString() {
+    return "auto";
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/ColumnPartition.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/ColumnPartition.java
new file mode 100644
index 0000000..ae85067
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/ColumnPartition.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * A list of positive integers with sum 12 (separated by a semicolon ";"). Is used for the 12 columns partitioning.
+ */
+public final class ColumnPartition implements Serializable {
+
+  private static final Integer[] INTEGER_12 = new Integer[]{12};
+  public static final ColumnPartition PARTITION_12 = new ColumnPartition(INTEGER_12);
+
+  private Integer[] parts;
+
+  public ColumnPartition() {
+    this(new Integer[0]);
+  }
+
+  public ColumnPartition(Integer... parts) {
+    setParts(parts);
+  }
+
+  public static ColumnPartition valueOf(String string) {
+    final List<Integer> integers = StringUtils.parseIntegerList(string, ";");
+    return new ColumnPartition(integers.toArray(new Integer[integers.size()]));
+  }
+
+  public static ColumnPartition valueOf(Object object) {
+    if (object instanceof String) {
+      return valueOf((String) object);
+    } else if (object instanceof Integer[]) {
+      return new ColumnPartition((Integer[]) object);
+    } else if (object != null) {
+      return valueOf(object.toString());
+    } else {
+      return PARTITION_12;
+    }
+  }
+
+  private boolean checkSum(final Integer[] summands) {
+    if (summands == null || summands.length == 0) {
+      return false;
+    }
+    int sum = 0;
+    for (int summand : summands) {
+      if (summand < 1) {
+        return false;
+      }
+      sum += summand;
+      if (sum > 12) {
+        return false;
+      }
+    }
+    return sum == 12;
+  }
+
+  private Integer[] createParts(Integer[] summands) {
+    return createParts(Arrays.asList(summands));
+  }
+
+  private Integer[] createParts(List<Integer> summands) {
+    List<Integer> list = new ArrayList<Integer>();
+    if (summands == null || summands.size() == 0) {
+      return INTEGER_12;
+    }
+    int sum = 0;
+    for (int summand : summands) {
+      if (summand < 1) {
+        summand = 1;
+      }
+      if (sum + summand > 12) {
+        break;
+      }
+      sum += summand;
+      list.add(summand);
+    }
+    if (sum < 12) {
+      list.add(12 - sum);
+    }
+    return list.toArray(new Integer[list.size()]);
+  }
+
+  public Integer[] getParts() {
+    return parts;
+  }
+
+  private void setParts(Integer[] parts) {
+    if (checkSum(parts)) {
+      this.parts = parts;
+    } else {
+      this.parts = createParts(parts);
+    }
+  }
+
+  public int getSize() {
+    return parts.length;
+  }
+
+  public int getPart(final int column) {
+    return parts[column];
+  }
+
+  @Override
+  public String toString() {
+    return Arrays.toString(parts);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Display.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Display.java
new file mode 100644
index 0000000..33d4305
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Display.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+/**
+ * Values for display attribute used with CSS.
+ *
+ * Note: the enums are not capitalized, because of problems with {@link java.beans.PropertyEditor}.
+ */
+public enum Display {
+
+  block,
+  inline,
+  none;
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Display#block}
+   */
+  public static final String BLOCK = "block";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Display#inline}
+   */
+  public static final String INLINE = "inline";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Display#none}
+   */
+  public static final String NONE = "none";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/HideLayoutToken.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/HideLayoutToken.java
new file mode 100644
index 0000000..a893627
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/HideLayoutToken.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public final class HideLayoutToken extends LayoutToken {
+  public String toString() {
+    return "hide";
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/JustifyContent.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/JustifyContent.java
new file mode 100644
index 0000000..a678843
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/JustifyContent.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public enum JustifyContent {
+
+  flexStart,
+  flexEnd,
+  center,
+  spaceBetween,
+  spaceAround;
+
+  public static final String FLEX_START = "flexStart";
+  public static final String FLEX_END = "flexEnd";
+  public static final String CENTER = "center";
+  public static final String SPACE_BETWEEN = "spaceBetween";
+  public static final String SPACE_AROUND = "spaceAround";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutToken.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutToken.java
new file mode 100644
index 0000000..67f412f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutToken.java
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public class LayoutToken {
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutTokens.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutTokens.java
new file mode 100644
index 0000000..cecb1bb
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/LayoutTokens.java
@@ -0,0 +1,146 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.internal.util.NumberUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.StringTokenizer;
+
+public final class LayoutTokens implements Iterable<LayoutToken> {
+
+  private static final Logger LOG = LoggerFactory.getLogger(LayoutTokens.class);
+
+  private List<LayoutToken> tokens = new ArrayList<LayoutToken>();
+
+  public LayoutTokens() {
+  }
+
+  public int getSize() {
+    return tokens.size();
+  }
+
+  public void set(final int index, final LayoutToken token) {
+    tokens.set(index, token);
+  }
+
+  public boolean isEmpty() {
+    return getSize() == 0;
+  }
+
+  public LayoutToken get(final int index) {
+    return tokens.get(index);
+  }
+
+  public void addToken(final LayoutToken token) {
+    tokens.add(token);
+  }
+
+  public List<LayoutToken> getTokens() {
+    return tokens;
+  }
+
+  @Override
+  public Iterator<LayoutToken> iterator() {
+    return tokens.iterator();
+  }
+
+  public static LayoutTokens parse(final String[] tokens) {
+    final LayoutTokens layoutTokens = new LayoutTokens();
+    for (final String token : tokens) {
+      parseToken(token, layoutTokens);
+    }
+    return layoutTokens;
+  }
+
+  public static LayoutTokens parse(final String tokens) {
+    return parse(tokens, null);
+  }
+
+  public static LayoutTokens parse(final String tokens, final LayoutToken defaultToken) {
+    final LayoutTokens layoutTokens = new LayoutTokens();
+    if (tokens == null) {
+      layoutTokens.addToken(defaultToken);
+      return layoutTokens;
+    }
+    final StringTokenizer tokenizer = new StringTokenizer(tokens, ";");
+
+    while (tokenizer.hasMoreTokens()) {
+      final String token = tokenizer.nextToken().trim();
+      parseToken(token, layoutTokens);
+    }
+    return layoutTokens;
+  }
+
+  private static void parseToken(final String token, final LayoutTokens layoutTokens) {
+    final LayoutToken layoutToken = parseToken(token);
+    if (layoutToken != null) {
+      layoutTokens.addToken(layoutToken);
+    }
+  }
+
+  public static LayoutToken parseToken(final String token) {
+    try {
+      if ("*".equals(token)) {
+        return RelativeLayoutToken.DEFAULT_INSTANCE;
+      } else if (token == null) {
+        LOG.error("Empty layout token! Using 'auto' instead.");
+        return AutoLayoutToken.INSTANCE;
+      } else if ("fixed".equals(token) || "auto".equals(token)) {
+        return AutoLayoutToken.INSTANCE;
+      } else if ("minimum".equals(token)) {
+        return new MinimumLayoutToken();
+      } else if (isRelativeToken(token)) {
+        return new RelativeLayoutToken(Integer.parseInt(removeSuffix(token, RelativeLayoutToken.SUFFIX)));
+      } else {
+        return new MeasureLayoutToken(token);
+      }
+    } catch (final NumberFormatException e) {
+      LOG.error("Error parsing layout token '" + token + "'! Using 'auto' instead.");
+      return AutoLayoutToken.INSTANCE;
+    }
+  }
+
+  static boolean isRelativeToken(final String token) {
+    return isNumberAndSuffix(token, RelativeLayoutToken.SUFFIX);
+  }
+
+  static boolean isNumberAndSuffix(final String token, final String suffix) {
+    return token.endsWith(suffix) && NumberUtils.isDigits(removeSuffix(token, suffix));
+  }
+
+  private static String removeSuffix(final String token, final String suffix) {
+    return token.substring(0, token.length() - suffix.length());
+  }
+
+  public String toString() {
+    final StringBuilder str = new StringBuilder();
+    for (final LayoutToken token : tokens) {
+      str.append(token);
+      str.append(";");
+    }
+    return str.toString();
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Measure.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Measure.java
new file mode 100644
index 0000000..a295a2c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Measure.java
@@ -0,0 +1,188 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+
+/**
+ * In JSPs the class {@link org.apache.myfaces.tobago.layout.MeasureEditor} will convert the string literals.
+ */
+public final class Measure implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(Measure.class);
+
+  public static final Measure ZERO = valueOf(0);
+
+  // todo: refactor and consolidate with LayoutToken
+
+  private final Double d;
+  private final Integer i;
+  private final Unit unit;
+
+  public Measure(int i, Unit unit) {
+    this.d = null;
+    this.i = i;
+    this.unit = unit;
+  }
+
+  public Measure(double d, Unit unit) {
+    this.d = d;
+    this.i = null;
+    this.unit = unit;
+  }
+
+  public Measure(String string, Unit unit) {
+    if (string.contains(".")) {
+      this.d = Double.parseDouble(string);
+      this.i = null;
+    } else {
+      this.d = null;
+      this.i = Integer.parseInt(string);
+    }
+    this.unit = unit;
+  }
+
+  public static Measure valueOf(final Measure value) {
+    if (value == null) {
+      return ZERO;
+    }
+    return value;
+  }
+
+  public static Measure valueOf(final int value) {
+    return new Measure(value, Unit.PX);
+  }
+
+  public static Measure valueOf(final Integer value) {
+    if (value == null) {
+      return ZERO;
+    }
+    return valueOf(value.intValue());
+  }
+
+  public static Measure valueOf(final Number value) {
+    if (value == null) {
+      return ZERO;
+    }
+    return valueOf(value.doubleValue());
+  }
+
+  public static Measure valueOf(final String value) {
+    try {
+      if (StringUtils.isEmpty(value)) {
+        return null;
+      }
+      final int length = value.length();
+      if (value.endsWith("%")) {
+        return new Measure(value.substring(0, length - 1), Unit.PERCENT);
+      }
+      if (length >= 2 && Character.isLetter(value.charAt(length - 2))) {
+        return new Measure(value.substring(0, length - 2), Unit.valueOf(value.substring(length - 2).toUpperCase()));
+      }
+      return new Measure(value, Unit.PX);
+
+    } catch (final RuntimeException e) {
+      LOG.warn("Can't parse to any measure: '" + value + "'");
+    }
+    return null;
+  }
+
+  public static Measure valueOf(final Object object) {
+    if (object == null) {
+      return null;
+    }
+    if (object instanceof Measure) {
+      return valueOf((Measure) object);
+    }
+    if (object instanceof Number) {
+      return valueOf((Number) object);
+    }
+    if (object instanceof String) {
+      return valueOf((String) object);
+    }
+    return valueOf(object.toString());
+  }
+
+  public String serialize() {
+    return "" + (i != null ? i : "") + (d != null ? d : "") + unit.getValue();
+  }
+
+  public String toString() {
+    return serialize();
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    Measure measure = (Measure) o;
+
+    if (d != null ? !d.equals(measure.d) : measure.d != null) {
+      return false;
+    }
+    if (i != null ? !i.equals(measure.i) : measure.i != null) {
+      return false;
+    }
+    return unit == measure.unit;
+
+  }
+
+  @Override
+  public int hashCode() {
+    int result = d != null ? d.hashCode() : 0;
+    result = 31 * result + (i != null ? i.hashCode() : 0);
+    result = 31 * result + unit.hashCode();
+    return result;
+  }
+
+  private enum Unit {
+
+    EM,
+    PX,
+    EX,
+    PT,
+    CM,
+    MM,
+    IN,
+    PC,
+    PERCENT;
+
+    private final String value;
+
+    Unit() {
+      value = name().equals("PERCENT") ? "%" : name().toLowerCase();
+    }
+
+    String getValue() {
+      return value;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureEditor.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureEditor.java
new file mode 100644
index 0000000..d3279b7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureEditor.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import java.beans.PropertyEditorSupport;
+
+/**
+ * Converter for {@link org.apache.myfaces.tobago.layout.Measure}
+ */
+public class MeasureEditor extends PropertyEditorSupport {
+
+    @Override
+    public void setAsText(final String text) throws IllegalArgumentException {
+        setValue(Measure.valueOf(text));
+    }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureLayoutToken.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureLayoutToken.java
new file mode 100644
index 0000000..41f535b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MeasureLayoutToken.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+/**
+ * @since Tobago 3.0. Was renamed from PixelLayoutToken, because it's generalization.
+ */
+public class MeasureLayoutToken extends LayoutToken {
+
+  private final Measure measure;
+
+  public MeasureLayoutToken(final String measure) {
+    // here we cannot use this(PixelMeasure.pixelValueOf(pixel)), because of class initialization problems
+    this(Measure.valueOf(measure));
+    if (this.measure == null) {
+      throw new NumberFormatException(measure);
+    }
+  }
+
+  public MeasureLayoutToken(final Measure measure) {
+    this.measure = measure;
+  }
+
+  public Measure getMeasure() {
+    return measure;
+  }
+
+  public String toString() {
+    return measure.toString();
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final MeasureLayoutToken that = (MeasureLayoutToken) o;
+
+    return measure.equals(that.measure);
+
+  }
+
+  public int hashCode() {
+    return measure.hashCode();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MinimumLayoutToken.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MinimumLayoutToken.java
new file mode 100644
index 0000000..1e6bb21
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/MinimumLayoutToken.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public final class MinimumLayoutToken extends LayoutToken {
+  public String toString() {
+    return "minimum";
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/OrderBy.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/OrderBy.java
new file mode 100644
index 0000000..f5075b2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/OrderBy.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public enum OrderBy {
+
+  occurrence,
+  severity;
+
+  public static final String OCCURRENCE = "occurrence";
+
+  public static final String SEVERITY = "severity";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Orientation.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Orientation.java
new file mode 100644
index 0000000..6500b7d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Orientation.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+/**
+ * Layout relevant values for the orientation.
+ */
+public enum Orientation {
+  
+  horizontal,
+  vertical;
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Orientation#horizontal}
+   */
+  public static final String HORIZONTAL = "horizontal";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Orientation#horizontal}
+   */
+  public static final String VERTICAL = "vertical";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Overflow.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Overflow.java
new file mode 100644
index 0000000..b198593
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Overflow.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public enum Overflow {
+
+  auto,
+  hidden,
+  scroll;
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Overflow#auto}
+   */
+  public static final String AUTO = "auto";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Overflow#hidden}
+   */
+  public static final String HIDDEN = "hidden";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Overflow#scroll}
+   */
+  public static final String SCROLL = "scroll";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/PixelMeasure.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/PixelMeasure.java
new file mode 100644
index 0000000..33169cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/PixelMeasure.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class PixelMeasure /*extends Measure*/ {
+
+  private static final Logger LOG = LoggerFactory.getLogger(PixelMeasure.class);
+
+  static final PixelMeasure[] PIXEL_CACHE;
+  static final int PIXEL_CACHE_MAX = 4000;
+  
+  static {
+    PIXEL_CACHE = new PixelMeasure[PIXEL_CACHE_MAX + 1];
+    for (int i = 0; i < PIXEL_CACHE.length; i++) {
+      PIXEL_CACHE[i] = new PixelMeasure(i);
+    }
+  }
+  
+  private final int pixel;
+
+  private PixelMeasure(final int pixel) {
+    this.pixel = pixel;
+  }
+
+  static PixelMeasure pixelValueOf(final int value) {
+    if (value >= 0 && value <= PixelMeasure.PIXEL_CACHE_MAX) {
+      return PixelMeasure.PIXEL_CACHE[value];
+    }
+    return new PixelMeasure(value);
+  }
+  
+  public int getPixel() {
+    return pixel;
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final PixelMeasure that = (PixelMeasure) o;
+
+    if (pixel != that.pixel) {
+      return false;
+    }
+
+    return true;
+  }
+
+  @Override
+  public int hashCode() {
+    return pixel;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Position.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Position.java
new file mode 100644
index 0000000..30da573
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/Position.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+/**
+ * Values for position used with CSS.
+ *
+ * Note: the enums are not capitalized, because of problems with {@link java.beans.PropertyEditor}.
+ */
+public enum Position {
+
+  absolute,
+  relative,
+  fixed;
+//  static; XXX not possible
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Position#absolute}
+   */
+  public static final String ABSOLUTE = "absolute";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Position#relative}
+   */
+  public static final String RELATIVE = "relative";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link Position#fixed}
+   */
+  public static final String FIXED = "fixed";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/RelativeLayoutToken.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/RelativeLayoutToken.java
new file mode 100644
index 0000000..9d1a6c8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/RelativeLayoutToken.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public class RelativeLayoutToken extends LayoutToken {
+
+  static final String SUFFIX = "*";
+
+  public static final String DEFAULT_TOKEN_STRING = "1*";
+  public static final RelativeLayoutToken DEFAULT_INSTANCE = new RelativeLayoutToken(1);
+
+  private int factor = 1;
+
+  public RelativeLayoutToken(final int factor) {
+    this.factor = factor;
+  }
+
+  public int getFactor() {
+    return factor;
+  }
+
+  public String toString() {
+    return factor + SUFFIX;
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final RelativeLayoutToken that = (RelativeLayoutToken) o;
+
+    if (factor != that.factor) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public int hashCode() {
+    return factor;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/ShowPosition.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/ShowPosition.java
new file mode 100644
index 0000000..2d5e4cd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/ShowPosition.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+public enum ShowPosition {
+
+  left,
+  center,
+  right,
+  none;
+
+  public static final String LEFT = "left";
+  public static final String CENTER = "center";
+  public static final String RIGHT = "right";
+  public static final String NONE = "none";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/TextAlign.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/TextAlign.java
new file mode 100644
index 0000000..bd90f90
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/layout/TextAlign.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+/**
+ * Values for text alignments used with CSS.
+ *
+ * Note: the enums are not capitalized, because of problems with {@link java.beans.PropertyEditor}.
+ */
+public enum TextAlign {
+
+  left,
+  right,
+  center,
+  justify;
+
+  /**
+   * Internal constant to use in annotations. Please use {@link TextAlign#left}
+   */
+  public static final String LEFT = "left";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link TextAlign#right}
+   */
+  public static final String RIGHT = "right";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link TextAlign#center}
+   */
+  public static final String CENTER = "center";
+
+  /**
+   * Internal constant to use in annotations. Please use {@link TextAlign#justify}
+   */
+  public static final String JUSTIFY = "justify";
+
+  /**
+   * @deprecated Since Tobago 3.0.0 Please use {@link TextAlign#name}
+   */
+  public String getValue() {
+    return name();
+  }
+
+  /**
+   * @deprecated Since Tobago 3.0.0 Please use {@link TextAlign#valueOf}
+   */
+  @Deprecated
+  public static TextAlign parse(final String string) {
+    return valueOf(string);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/lifecycle/SecretPhaseListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/lifecycle/SecretPhaseListener.java
new file mode 100644
index 0000000..175c088
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/lifecycle/SecretPhaseListener.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.lifecycle;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.webapp.Secret;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+public class SecretPhaseListener implements PhaseListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SecretPhaseListener.class);
+
+  @Override
+  public void afterPhase(final PhaseEvent event) {
+    final FacesContext facesContext = event.getFacesContext();
+    if (!facesContext.getResponseComplete()
+        && facesContext.isPostback()
+        && TobagoConfig.getInstance(facesContext).isCheckSessionSecret()
+        && !Secret.check(facesContext)) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Secret is invalid!");
+      }
+      facesContext.renderResponse();
+    }
+  }
+
+  @Override
+  public void beforePhase(final PhaseEvent event) {
+  }
+
+  @Override
+  public PhaseId getPhaseId() {
+    return PhaseId.RESTORE_VIEW;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestExtensionItem.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestExtensionItem.java
new file mode 100644
index 0000000..3b22356
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestExtensionItem.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+
+public class AutoSuggestExtensionItem {
+  private String id;
+  private String value;
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(final String id) {
+    this.id = id;
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(final String value) {
+    this.value = value;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestItem.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestItem.java
new file mode 100644
index 0000000..71b2de5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestItem.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import java.util.List;
+
+public class AutoSuggestItem extends AutoSuggestExtensionItem {
+
+  private String label;
+
+  private String nextFocusId;
+
+  private List<AutoSuggestExtensionItem> extensionItems;
+
+  public String getLabel() {
+    return label;
+  }
+
+  public void setLabel(final String label) {
+    this.label = label;
+  }
+
+  public String getNextFocusId() {
+    return nextFocusId;
+  }
+
+  public void setNextFocusId(final String nextFocusId) {
+    this.nextFocusId = nextFocusId;
+  }
+
+  public List<AutoSuggestExtensionItem> getExtensionItems() {
+    return extensionItems;
+  }
+
+  public void setExtensionItems(final List<AutoSuggestExtensionItem> extensionItems) {
+    this.extensionItems = extensionItems;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestItems.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestItems.java
new file mode 100644
index 0000000..de73557
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/AutoSuggestItems.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+
+import java.util.List;
+
+public class AutoSuggestItems {
+
+  private List<AutoSuggestItem> items;
+
+  private String nextFocusId;
+
+  private int maxSuggestedCount = 25;
+
+  public List<AutoSuggestItem> getItems() {
+    return items;
+  }
+
+  public void setItems(final List<AutoSuggestItem> items) {
+    this.items = items;
+  }
+
+  public String getNextFocusId() {
+    return nextFocusId;
+  }
+
+  public void setNextFocusId(final String nextFocusId) {
+    this.nextFocusId = nextFocusId;
+  }
+
+  public int getMaxSuggestedCount() {
+    return maxSuggestedCount;
+  }
+
+  public void setMaxSuggestedCount(final int maxSuggestedCount) {
+    this.maxSuggestedCount = maxSuggestedCount;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/CalendarModel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/CalendarModel.java
new file mode 100644
index 0000000..f931ae5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/CalendarModel.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import java.text.DecimalFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+
+public class CalendarModel {
+
+  private DateModel[][] calendarArray;
+  private int firstDayOffset;
+
+  public CalendarModel(final Calendar calendar) {
+//    int weekCount = CalendarUtils.weekCount(calendar);
+    final int weekCount = 6; // switching off dynamic weekCount!
+    calendarArray = new DateModel[weekCount][7];
+    final Calendar c = (Calendar) calendar.clone();
+    c.clear(Calendar.DAY_OF_MONTH);
+    c.set(Calendar.DAY_OF_MONTH, 1);
+    // assert c.isLenient() : "'add -x days' may not work in a non-lenient calendar";
+    firstDayOffset = firstDayOffset(c);
+    c.add(Calendar.DAY_OF_WEEK, -firstDayOffset);
+    for (int week = 0; week < weekCount; ++week) {
+      for (int day = 0; day < 7; ++day) {
+        calendarArray[week][day] = new DateModel(c);
+        c.add(Calendar.DAY_OF_MONTH, 1);
+      }
+    }
+  }
+
+  public int getWeekCount() {
+    return calendarArray.length;
+  }
+
+  public int getMonth() {
+    return calendarArray[0][firstDayOffset].getMonth();
+  }
+
+  public int getYear() {
+    return calendarArray[0][firstDayOffset].getYear();
+  }
+
+  public DateModel getDate(final int week, final int day) {
+    return calendarArray[week][day];
+  }
+
+  private int firstDayOffset(final Calendar calendar) {
+    final Calendar c = (Calendar) calendar.clone();
+    c.clear(Calendar.DAY_OF_MONTH);
+    c.set(Calendar.DAY_OF_MONTH, 1);
+    final int day = c.get(Calendar.DAY_OF_WEEK);
+    final int firstDayOfWeek = c.getFirstDayOfWeek();
+    // Fails: assertEquals((1+7-3)%7, (1-3)%7);
+    return (day + 7 - firstDayOfWeek) % 7;
+  }
+
+  public String toString() {
+    final StringBuilder buffer = new StringBuilder();
+    buffer.append("Month: ").append(getMonth()).append("\n");
+    final int weekCount = getWeekCount();
+    final DecimalFormat format = new DecimalFormat("00");
+    final SimpleDateFormat dateFormat = new SimpleDateFormat("E");
+    for (int day = 0; day < 7; ++day) {
+      final DateModel date = getDate(0, day);
+      final String dayName = dateFormat.format(date.getCalendar().getTime());
+      buffer.append(dayName.substring(0, 2)).append(" ");
+    }
+    buffer.append("\n");
+    for (int week = 0; week < weekCount; ++week) {
+      for (int day = 0; day < 7; ++day) {
+        final DateModel date = getDate(week, day);
+        buffer.append(format.format(date.getDay())).append(" ");
+      }
+      buffer.append("\n");
+    }
+    return buffer.toString();
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/CollapseMode.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/CollapseMode.java
new file mode 100644
index 0000000..29bf6f8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/CollapseMode.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+public enum CollapseMode {
+
+  hidden,
+  absent,
+  none;
+
+  public static final String HIDDEN = "hidden";
+  public static final String ABSENT = "absent";
+  public static final String NONE = "none";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/DateModel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/DateModel.java
new file mode 100644
index 0000000..77b3912
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/DateModel.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+public class DateModel {
+
+  private int year;
+  private int month;
+  private int day;
+
+  public DateModel(final int year, final int month, final int day) {
+    this.year = year;
+    this.month = month;
+    this.day = day;
+  }
+
+  public DateModel(final Calendar calendar) {
+    this.year = calendar.get(Calendar.YEAR);
+    this.month = calendar.get(Calendar.MONTH) + 1;
+    this.day = calendar.get(Calendar.DAY_OF_MONTH);
+  }
+
+  public int getYear() {
+    return year;
+  }
+
+  public void setYear(final int year) {
+    this.year = year;
+  }
+
+  public int getMonth() {
+    return month;
+  }
+
+  public void setMonth(final int month) {
+    this.month = month;
+  }
+
+  public int getDay() {
+    return day;
+  }
+
+  public void setDay(final int day) {
+    this.day = day;
+  }
+
+  public Calendar getCalendar() {
+    return getCalendar(null);
+  }
+
+  public Calendar getCalendar(final Locale locale) {
+    final Calendar calendar = locale != null
+        ? Calendar.getInstance(locale) : Calendar.getInstance();
+    calendar.set(year, month - 1, day);
+    return calendar;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ExpandedState.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ExpandedState.java
new file mode 100644
index 0000000..3a0c78b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ExpandedState.java
@@ -0,0 +1,251 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import javax.swing.tree.TreeNode;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manages the expanded state of an tree.
+ *
+ * @since 2.0.0
+ */
+public class ExpandedState implements Serializable {
+
+  private int defaultExpandedLevels;
+  private Set<TreePath> expandedSet;
+  private Set<TreePath> collapsedSet;
+
+  /**
+   * Creates a new state object to store which nodes of a tree are expanded and collapsed in a view.
+   *
+   * @param defaultExpandedLevels All nodes up to this level are expanded by default.
+   */
+  public ExpandedState(final int defaultExpandedLevels) {
+    this.defaultExpandedLevels = defaultExpandedLevels;
+    this.expandedSet = new HashSet<TreePath>();
+    this.collapsedSet = new HashSet<TreePath>();
+  }
+
+  /**
+   * Checks if a node is expanded.
+   *
+   * @param node The node to check.
+   * @return Is the node expanded?
+   */
+  public boolean isExpanded(final TreeNode node) {
+    final TreePath path = new TreePath(node);
+    return isExpanded(path);
+  }
+
+  /**
+   * Checks if a node is expanded.
+   *
+   * @param path The path of the node to check.
+   * @return Is the node behind this path is expanded?
+   */
+  public boolean isExpanded(final TreePath path) {
+    if (expandedSet.contains(path)) {
+      return true;
+    }
+    if (collapsedSet.contains(path)) {
+      return false;
+    }
+    return path.getLength() < defaultExpandedLevels;
+  }
+
+  /**
+   * Expands a single node.
+   *
+   * @param node The node to expand. Also the parents will be expanded since Tobago 3.0.0.
+   */
+  public void expand(final TreeNode node) {
+    expand(node, true);
+  }
+
+  /**
+   * Expands a single node.
+   *
+   * @param node The node to expand.
+   * @param parents Should the parents also be expanded?
+   */
+  public void expand(final TreeNode node, final boolean parents) {
+    final TreePath path = new TreePath(node);
+    expand(path, parents);
+  }
+
+  /**
+   * Expands a single node.
+   *
+   * @param path The path of the node to expand. Also the parents will be expanded since Tobago 3.0.0.
+   */
+  public void expand(final TreePath path) {
+    expand(path, true);
+  }
+
+  /**
+   * Expands a single node.
+   *
+   * @param path The path of the node to expand.
+   * @param parents Should the parents also be expanded?
+   */
+  public void expand(final TreePath path, final boolean parents) {
+    if (path.getLength() >= defaultExpandedLevels) {
+      expandedSet.add(path);
+    } else {
+      collapsedSet.remove(path);
+    }
+    if (parents && !path.isRoot()) {
+      expand(path.getParent(), true);
+    }
+  }
+
+  /**
+   * Expands all nodes that level are lower or equals the parameter level.
+   *
+   * @param level The level to expand.
+   */
+  public void expand(final int level) {
+    final ArrayList<TreePath> toRemove = new ArrayList<TreePath>();
+    if (level > defaultExpandedLevels) {
+      defaultExpandedLevels = level;
+      for (final TreePath treePath : expandedSet) {
+        if (treePath.getLength() < defaultExpandedLevels) {
+          toRemove.add(treePath);
+        }
+      }
+      expandedSet.removeAll(toRemove);
+      collapsedSet.clear();
+    } else {
+      for (final TreePath treePath : collapsedSet) {
+        if (treePath.getLength() < level) {
+          toRemove.add(treePath);
+        }
+      }
+      collapsedSet.removeAll(toRemove);
+    }
+  }
+
+  /**
+   * Expands a nodes of the tree.
+   */
+  public void expandAll() {
+    defaultExpandedLevels = Integer.MAX_VALUE;
+    expandedSet.clear();
+    collapsedSet.clear();
+  }
+
+  /**
+   * Collapses a single node.
+   *
+   * @param node The node to collapse.
+   */
+  public void collapse(final TreeNode node) {
+    final TreePath path = new TreePath(node);
+    collapse(path);
+  }
+
+  /**
+   * Collapses a single node.
+   *
+   * @param path The path of the node to collapse.
+   */
+  public void collapse(final TreePath path) {
+    if (path.getLength() < defaultExpandedLevels) {
+      collapsedSet.add(path);
+    } else {
+      expandedSet.remove(path);
+    }
+  }
+
+  /**
+   * Collapses all nodes that level are higher or equals the parameter level.
+   *
+   * @param level The level to expand.
+   */
+  public void collapse(int level) {
+    // to use a symmetric algorithm like in expand
+    level--;
+
+    final ArrayList<TreePath> toRemove = new ArrayList<TreePath>();
+    if (level < defaultExpandedLevels) {
+      defaultExpandedLevels = level;
+      for (final TreePath treePath : collapsedSet) {
+        if (treePath.getLength() >= defaultExpandedLevels) {
+          toRemove.add(treePath);
+        }
+      }
+      collapsedSet.removeAll(toRemove);
+      expandedSet.clear();
+    } else {
+      for (final TreePath treePath : expandedSet) {
+        if (treePath.getLength() >= level) {
+          toRemove.add(treePath);
+        }
+      }
+      expandedSet.removeAll(toRemove);
+    }
+  }
+
+  /**
+   * Collapses a nodes of the tree.
+   */
+  public void collapseAll() {
+    defaultExpandedLevels = 0;
+    expandedSet.clear();
+    collapsedSet.clear();
+  }
+
+  /**
+   * Collapses a nodes of the tree. The root node will be expanded.
+   */
+  public void collapseAllButRoot() {
+    defaultExpandedLevels = 1;
+    expandedSet.clear();
+    collapsedSet.clear();
+  }
+
+  /**
+   * Resets the state to the defaults. After this call, the nodes with level smaller than defaultExpandedLevels
+   * are expanded, the other ones are collapsed.
+   */
+  public void reset() {
+    expandedSet.clear();
+    collapsedSet.clear();
+  }
+
+  /**
+   * @return A unmodifiable set of paths of the expanded nodes.
+   */
+  public Set<TreePath> getExpandedSet() {
+    return Collections.unmodifiableSet(expandedSet);
+  }
+
+  /**
+   * @return A unmodifiable set of paths of the collapsed nodes.
+   */
+  public Set<TreePath> getCollapsedSet() {
+    return Collections.unmodifiableSet(collapsedSet);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ScrollPosition.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ScrollPosition.java
new file mode 100644
index 0000000..4696430
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ScrollPosition.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+
+public class ScrollPosition implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ScrollPosition.class);
+
+  private Integer left;
+  private Integer top;
+
+  public String encode() {
+    return (left != null ? left : "0") + ";" + (top != null ? top : "0");
+  }
+
+  public void clear() {
+    top = null;
+    left = null;
+  }
+
+  public void update(final String value) {
+    if (StringUtils.isBlank(value)) {
+      top = null;
+      left = null;
+    } else {
+      final int sep = value.indexOf(";");
+      if (sep == -1) {
+        LOG.warn("Can't parse: '{}'", value);
+        return;
+      }
+      left = Integer.parseInt(value.substring(0, sep));
+      top = Integer.parseInt(value.substring(sep + 1));
+    }
+  }
+
+  public Integer getLeft() {
+    return left;
+  }
+
+  public void setLeft(Integer left) {
+    this.left = left;
+  }
+
+  public Integer getTop() {
+    return top;
+  }
+
+  public void setTop(Integer top) {
+    this.top = top;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ScrollPositionState.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ScrollPositionState.java
new file mode 100644
index 0000000..47888e2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/ScrollPositionState.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+public interface ScrollPositionState {
+
+  ScrollPosition getScrollPosition();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SelectItem.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SelectItem.java
new file mode 100644
index 0000000..5d54a2e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SelectItem.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.renderkit.css.CustomClass;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+
+public class SelectItem extends javax.faces.model.SelectItem implements Visual {
+
+  private static final long serialVersionUID = 2582455665060354639L;
+
+  private String image;
+  private Markup markup = Markup.NULL;
+  private Style style;
+  private CustomClass customClass;
+
+  public SelectItem() {
+    super();
+  }
+
+  public SelectItem(final Object value) {
+    super(value);
+  }
+
+  public SelectItem(final Object value, final String label) {
+    super(value, label);
+  }
+
+  public SelectItem(final Object value, final String label, final String tip) {
+    super(value, label, tip);
+  }
+
+  public SelectItem(final Object value, final String label, final String tip, final String image) {
+    this(value, label, tip, false, image);
+  }
+
+  public SelectItem(
+      final Object value, final String label, final String tip, final String image, final Markup markup) {
+    this(value, label, tip, false, image, markup);
+  }
+
+  public SelectItem(
+      final Object value, final String label, final String tip, final boolean disabled, final String image) {
+    this(value, label, tip, disabled, image, Markup.NULL);
+  }
+
+  public SelectItem(
+      final Object value, final String label, final String tip, final boolean disabled, final String image,
+      final Markup markup) {
+    super(value, label, tip, disabled);
+    this.image = image;
+    this.markup = markup;
+  }
+
+  /**
+   * Alias name for description.
+   */
+  public String getTip() {
+    return getDescription();
+  }
+
+  /**
+   * Alias name for description.
+   */
+  public void setTip(String tip) {
+    setDescription(tip);
+  }
+
+  public String getImage() {
+    return image;
+  }
+
+  public void setImage(final String image) {
+    this.image = image;
+  }
+
+  @Override
+  public Markup getMarkup() {
+    return markup;
+  }
+
+  @Override
+  public void setMarkup(final Markup markup) {
+    this.markup = markup;
+  }
+
+  @Override
+  public Style getStyle() {
+    return style;
+  }
+
+  @Override
+  public void setStyle(Style style) {
+    this.style = style;
+  }
+
+  @Override
+  public CustomClass getCustomClass() {
+    return customClass;
+  }
+
+  @Override
+  public void setCustomClass(CustomClass customClass) {
+    this.customClass = customClass;
+  }
+
+  @Override
+  public String getRendererType() {
+    throw new UnsupportedOperationException();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/Selectable.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/Selectable.java
new file mode 100644
index 0000000..c94cfbc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/Selectable.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import java.util.EnumSet;
+import java.util.Set;
+
+public enum Selectable {
+
+  /**
+   * Not selectable.
+   */
+  none,
+
+  /**
+   * Multi selection possible. No other limitations.
+   */
+  multi,
+
+  /**
+   * Only one item is selectable.
+   */
+  single,
+
+  /**
+   * Only one of no item is selectable.
+   */
+  singleOrNone,
+
+  /**
+   * Only leafs are selectable.
+   */
+  multiLeafOnly,
+
+  /**
+   * Only one item is selectable and it must be a leaf.
+   */
+  singleLeafOnly,
+
+  /**
+   * Only siblings are selectable.
+   */
+  sibling,
+
+  /**
+   * Only siblings are selectable and they have to be leafs.
+   */
+  siblingLeafOnly,
+
+  /**
+   * Multi selection possible. When selecting or deselecting an item, the subtree will also
+   * be selected or unselected.
+   */
+  multiCascade;
+
+  public static final String NONE = "none";
+
+  public static final String MULTI = "multi";
+
+  public static final String SINGLE = "single";
+
+  public static final String SINGLE_OR_NONE = "singleOrNone";
+
+  public static final String MULTI_LEAF_ONLY = "multiLeafOnly";
+
+  public static final String SINGLE_LEAF_ONLY = "singleLeafOnly";
+
+  public static final String SIBLING = "sibling";
+
+  public static final String SIBLING_LEAF_ONLY = "siblingLeafOnly";
+
+  public static final String MULTI_CASCADE = "multiCascade";
+
+  private static final Set<Selectable> SHEET_VALUES = EnumSet.of(
+      none,
+      multi,
+      single,
+      singleOrNone);
+
+  private static final Set<Selectable> TREE_VALUES = EnumSet.of(
+      none,
+      multi,
+      single,
+      multiLeafOnly,
+      singleLeafOnly,
+      multiCascade);
+
+  private static final Set<Selectable> TREE_LISTBOX_VALUES = EnumSet.of(
+      single,
+      singleLeafOnly,
+      multiLeafOnly);
+
+  /**
+   * @param name Name of the Selectable
+   * @return The matching tree selection (can't be null).
+   * @throws IllegalArgumentException When the name doesn't match any Selectable.
+   */
+  public static Selectable parse(final Object name) throws IllegalArgumentException {
+    if (name == null) {
+      return null;
+    }
+    if (name instanceof Selectable) {
+      return (Selectable) name;
+    }
+    return valueOf(name.toString());
+  }
+
+  public boolean isLeafOnly() {
+    return this == singleLeafOnly || this == multiLeafOnly || this == siblingLeafOnly;
+  }
+
+  public boolean isSingle() {
+    return this == single || this == singleOrNone || this == singleLeafOnly;
+  }
+
+  public boolean isMulti() {
+    return this == multi || this == multiLeafOnly || this == multiCascade;
+  }
+
+  public boolean isSupportedBySheet() {
+    return SHEET_VALUES.contains(this);
+  }
+
+  public boolean isSupportedByTree() {
+    return TREE_VALUES.contains(this);
+  }
+
+  public boolean isSupportedByTreeListbox() {
+    return TREE_LISTBOX_VALUES.contains(this);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SelectedState.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SelectedState.java
new file mode 100644
index 0000000..7fec7ef
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SelectedState.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import java.io.Serializable;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * Manages the selected tree paths of a tree.
+ */
+// TODO: might be renamed to SelectedTreeState?
+public class SelectedState implements Serializable {
+
+  private Set<TreePath> selected = new HashSet<TreePath>();
+
+  /**
+   * Checks if the given is selected.
+   */
+  public boolean isSelected(final TreePath path) {
+    return selected.contains(path);
+  }
+
+  /**
+   * Select the given path.
+   */
+  public void select(final TreePath path) {
+    selected.add(path);
+  }
+
+  /**
+   * Unselect the given path.
+   */
+  public void unselect(final TreePath path) {
+    selected.remove(path);
+  }
+
+  /**
+   * Set the selected path and remove all prior selections.
+   * This is useful for "single selection" mode.
+   */
+  public void clearAndSelect(final TreePath path) {
+    clear();
+    select(path);
+  }
+
+  /**
+   * Clears the selected state, so that no TreePath is selected.
+   */
+  public void clear() {
+    selected.clear();
+  }
+
+  /**
+   * Set the selection state of the given path
+   */
+  public void select(final TreePath path, final boolean selected) {
+    if (selected) {
+      select(path);
+    } else {
+      unselect(path);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java
new file mode 100644
index 0000000..6c5df2e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SheetState.java
@@ -0,0 +1,184 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.apache.myfaces.tobago.event.SortActionEvent;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIColumn;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SheetState implements Serializable, ScrollPositionState {
+
+  private static final long serialVersionUID = 2L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(SheetState.class);
+
+  public static final String SEPARATOR = ",";
+
+  private int first;
+  private String sortedColumnId;
+  private boolean ascending;
+  private boolean toBeSorted;
+  private List<Integer> columnWidths;
+  private List<Integer> selectedRows;
+  private ScrollPosition scrollPosition;
+  private ExpandedState expandedState;
+  private SelectedState selectedState;
+
+  public SheetState() {
+    reset();
+  }
+
+  public void reset() {
+    first = -1;
+    sortedColumnId = null;
+    ascending = true;
+    toBeSorted = false;
+    columnWidths = new ArrayList<Integer>();
+    resetSelected();
+    if (expandedState != null) {
+      expandedState.reset();
+    }
+    if (selectedState != null) {
+      selectedState.clear();
+    }
+    if (scrollPosition != null) {
+      scrollPosition.clear();
+    } else {
+      scrollPosition = new ScrollPosition();
+    }
+  }
+
+  public void resetSelected() {
+    selectedRows = new ArrayList<Integer>();
+  }
+
+  public List<Integer> getSelectedRows() {
+    return selectedRows;
+  }
+
+  public void setSelectedRows(final List<Integer> selectedRows) {
+    assert selectedRows != null;
+    this.selectedRows = selectedRows;
+  }
+
+  public String getSortedColumnId() {
+    return sortedColumnId;
+  }
+
+  public void setSortedColumnId(final String sortedColumnId) {
+    if (StringUtils.notEquals(this.sortedColumnId, sortedColumnId)) {
+      this.sortedColumnId = sortedColumnId;
+      toBeSorted = true;
+    }
+  }
+
+  public boolean isAscending() {
+    return ascending;
+  }
+
+  public void setAscending(final boolean ascending) {
+    if (this.ascending != ascending) {
+      this.ascending = ascending;
+      toBeSorted = true;
+    }
+  }
+
+  public List<Integer> getColumnWidths() {
+    return columnWidths;
+  }
+
+  public void setColumnWidths(final List<Integer> columnWidths) {
+    this.columnWidths = columnWidths;
+  }
+
+  public boolean isDefinedColumnWidths() {
+    for (Integer columnWidth : columnWidths) {
+      if(columnWidth < 0) {
+        return false;
+      }
+    }
+    return columnWidths.size() > 0;
+  }
+
+  public int getFirst() {
+    return first;
+  }
+
+  public void setFirst(final int first) {
+    this.first = first;
+  }
+
+  public void updateSortState(final SortActionEvent sortEvent) {
+
+    final UIColumn actualColumn = sortEvent.getColumn();
+
+    if (actualColumn.getId().equals(sortedColumnId)) {
+      setAscending(!isAscending());
+    } else {
+      setAscending(true);
+      setSortedColumnId(actualColumn.getId());
+    }
+  }
+
+  @Override
+  public ScrollPosition getScrollPosition() {
+    return scrollPosition;
+  }
+
+  public void setScrollPosition(final ScrollPosition scrollPosition) {
+    this.scrollPosition = scrollPosition;
+  }
+
+  public ExpandedState getExpandedState() {
+    if (expandedState == null) {
+      expandedState = new ExpandedState(2);
+    }
+    return expandedState;
+  }
+
+  public void setExpandedState(final ExpandedState expandedState) {
+    this.expandedState = expandedState;
+  }
+
+  public SelectedState getSelectedState() {
+    if (selectedState == null) {
+      selectedState = new SelectedState();
+    }
+    return selectedState;
+  }
+
+  public void setSelectedState(final SelectedState selectedState) {
+    this.selectedState = selectedState;
+  }
+
+  public boolean isToBeSorted() {
+    return toBeSorted;
+  }
+
+  public void setToBeSorted(boolean toBeSorted) {
+    this.toBeSorted = toBeSorted;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SortableByApplication.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SortableByApplication.java
new file mode 100644
index 0000000..a989654
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SortableByApplication.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+public interface SortableByApplication {
+
+  void sortBy(String sortMethod);
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SuggestFilter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SuggestFilter.java
new file mode 100644
index 0000000..fd99327
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SuggestFilter.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+public enum SuggestFilter {
+
+  ALL,
+  PREFIX,
+  CONTAINS;
+
+  public static final String STRING_ALL = "all";
+  public static final String STRING_PREFIX = "prefix";
+  public static final String STRING_CONTAINS = "contains";
+
+  public String getValue() {
+    return name().toLowerCase();
+  }
+
+  public static SuggestFilter parse(final String string) {
+    if (string == null) {
+      return null;
+    }
+    return valueOf(string.toUpperCase());
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SwitchType.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SwitchType.java
new file mode 100644
index 0000000..228c4f9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/SwitchType.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+public enum SwitchType {
+
+  client,
+  reloadPage,
+  reloadTab,
+  none;
+
+  public static final String CLIENT = "client";
+  public static final String RELOAD_PAGE = "reloadPage";
+  public static final String RELOAD_TAB = "reloadTab";
+  public static final String NONE = "none";
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java
new file mode 100644
index 0000000..a663265
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeDataModel.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import javax.faces.model.DataModel;
+import java.util.List;
+
+/**
+ * Abstract class that represents the data model for a tree.
+ */
+public abstract class TreeDataModel extends DataModel {
+
+  public abstract void reset();
+
+  public abstract void update(ExpandedState expandedState);
+
+  @Override
+  public abstract int getRowCount();
+
+  @Override
+  public abstract int getRowIndex();
+
+  public abstract int getLevel();
+
+  public abstract TreePath getPath();
+
+  public abstract int getDepth();
+
+  public abstract boolean isFolder();
+
+  @Override
+  public abstract Object getWrappedData();
+
+  @Override
+  public abstract boolean isRowAvailable();
+
+  @Override
+  public abstract void setRowIndex(int rowIndex);
+
+  @Override
+  public abstract void setWrappedData(Object data);
+
+  public abstract boolean isRowVisible();
+
+  public abstract String getRowClientId();
+
+  public abstract void setRowClientId(String clientId);
+
+  public abstract String getRowParentClientId();
+
+  public abstract List<Integer> getRowIndicesOfChildren();
+
+  public abstract List<Boolean> getJunctions();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeNodeDataModel.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeNodeDataModel.java
new file mode 100644
index 0000000..0fb5234
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeNodeDataModel.java
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Stack;
+
+/**
+ * Implementation for a {@link TreeNode} that represents the data model for a tree.
+ */
+public class TreeNodeDataModel extends TreeDataModel {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TreeNodeDataModel.class);
+
+  private TreeNode data;
+  private int rowIndex = -1;
+  private Map<Integer, Data> mapping;
+  private Map<TreeNode, Integer> back;
+  private boolean showRoot;
+  private ExpandedState expandedState;
+
+  /**
+   * @param data          The tree data, which shall be wrapped.
+   * @param showRoot      Is the root node visible.
+   * @param expandedState Defines which nodes are expanded, (XXX should it be so?) a value of {@code null} means all.
+   */
+  public TreeNodeDataModel(final TreeNode data, final boolean showRoot, final ExpandedState expandedState) {
+    this.data = data;
+    this.showRoot = showRoot;
+    this.mapping = new HashMap<Integer, Data>();
+    this.back = new HashMap<TreeNode, Integer>();
+    this.expandedState = expandedState;
+    reset();
+  }
+
+  @Override
+  public void reset() {
+    this.mapping.clear();
+    this.back.clear();
+    TreeNode current = data;
+    for (int counter = back.size(); current != null; counter++) {
+
+      mapping.put(counter, new Data(current));
+      back.put(current, counter);
+
+      // if the node has children and is expanded, go to the children
+      if (current.getChildCount() > 0 && expandedState.isExpanded(current)) {
+        current = current.getChildAt(0);
+      } else {
+        current = getNextNodeButNoChild(current);
+      }
+    }
+  }
+
+  @Override
+  public void update(final ExpandedState expandedState) {
+    this.expandedState = expandedState;
+    TreeNode current = data;
+    int counter = back.size();
+    while (current != null) {
+
+      if (!back.containsKey(current)) {
+        mapping.put(counter, new Data(current));
+        back.put(current, counter);
+        counter++;
+      }
+
+      // if the node has children and is expanded, go to the children
+      if (current.getChildCount() > 0 && expandedState.isExpanded(current)) {
+        current = current.getChildAt(0);
+      } else {
+        current = getNextNodeButNoChild(current);
+      }
+    }
+  }
+
+  private TreeNode getNextNodeButNoChild(TreeNode node) {
+    TreeNode next;
+    while (true) {
+      next = nextSibling(node);
+      if (next != null) {
+        break;
+      }
+      node = node.getParent();
+      if (node == null) {
+        return null;
+      }
+
+    }
+    return next;
+  }
+
+  private TreeNode nextSibling(final TreeNode node) {
+    final TreeNode parent = node.getParent();
+    if (parent == null) {
+      return null;
+    }
+    for (int i = 0; i < parent.getChildCount() - 1; i++) {
+      if (parent.getChildAt(i) == node) { // == is okay in this case
+        return parent.getChildAt(i + 1);
+      }
+    }
+    return null;
+  }
+
+  @Override
+  public int getRowCount() {
+    return mapping.size();
+  }
+
+  @Override
+  public TreeNode getRowData() {
+    return mapping.get(rowIndex).getNode();
+  }
+
+  @Override
+  public int getRowIndex() {
+    return rowIndex;
+  }
+
+  @Override
+  public int getLevel() {
+    int count = -1;
+    for (TreeNode node = getRowData(); node != null; node = node.getParent()) {
+      count++;
+    }
+    return count;
+  }
+
+  @Override
+  public TreePath getPath() {
+    return new TreePath(getRowData());
+  }
+
+  @Override
+  public int getDepth() {
+    if (data instanceof DefaultMutableTreeNode) {
+      return ((DefaultMutableTreeNode) data).getDepth();
+    }
+    return -1;
+  }
+
+  @Override
+  public boolean isFolder() {
+    return !getRowData().isLeaf();
+  }
+
+  @Override
+  public Object getWrappedData() {
+    return data;
+  }
+
+  @Override
+  public boolean isRowAvailable() {
+    return 0 <= rowIndex && rowIndex < getRowCount();
+  }
+
+  @Override
+  public void setRowIndex(final int rowIndex) {
+    this.rowIndex = rowIndex;
+  }
+
+  @Override
+  public void setWrappedData(final Object data) {
+    this.data = (TreeNode) data;
+  }
+
+  @Override
+  public boolean isRowVisible() {
+    if (!isRowAvailable()) {
+      return false;
+    }
+    final TreeNode start = getRowData();
+    if (start.getParent() == null) {
+      return showRoot;
+    }
+    TreeNode node = start.getParent();
+    while (node != null && back.get(node) != null) {
+      final Data data = mapping.get(back.get(node));
+      if (data.getNode().getParent() == null && !showRoot) {
+        return true;
+      }
+      if (!expandedState.isExpanded(new TreePath(node))) {
+        return false;
+      }
+      node = node.getParent();
+    }
+    return true;
+  }
+
+  @Override
+  public String getRowClientId() {
+    if (isRowAvailable()) {
+      return mapping.get(rowIndex).getClientId();
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public void setRowClientId(final String clientId) {
+    if (isRowAvailable()) {
+      mapping.get(rowIndex).setClientId(clientId);
+    } else {
+      LOG.warn("No row index set: clientId='" + clientId + "'");
+    }
+  }
+
+  @Override
+  public String getRowParentClientId() {
+    if (isRowAvailable()) {
+      final TreeNode parent = mapping.get(rowIndex).getNode().getParent();
+      if (parent != null && back.get(parent) != null) {
+        return mapping.get(back.get(parent)).getClientId();
+      } else {
+        return null;
+      }
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public List<Integer> getRowIndicesOfChildren() {
+    final TreeNode node = getRowData();
+    final int n = node.getChildCount();
+    final List<Integer> children = new ArrayList<Integer>(n);
+    for (int i = 0; i < n; i++) {
+      final Integer integer = back.get(node.getChildAt(i));
+      if (integer != null) { // integer == null happens, when the node is not expanded
+        children.add(integer); // XXX is this a good way to handle that case?
+      }
+    }
+    return children;
+  }
+
+  @Override
+  public List<Boolean> getJunctions() {
+    TreeNode node = getRowData();
+    final List<Boolean> junctions = new Stack<Boolean>();
+    while (node != null) {
+      junctions.add(hasNextSibling(node));
+      node = node.getParent();
+    }
+    Collections.reverse(junctions);
+    return junctions;
+  }
+
+  private boolean hasNextSibling(final TreeNode node) {
+    final TreeNode parent = node.getParent();
+    return parent != null && parent.getChildAt(parent.getChildCount() - 1) != node;
+  }
+
+  /**
+   * Here we cache some state information of the nodes, because we can't access the UITreeNode state of the other nodes
+   * while rendering.
+   */
+  private static class Data {
+
+    private TreeNode node;
+    private String clientId;
+
+    private Data(final TreeNode node) {
+      this.node = node;
+    }
+
+    public TreeNode getNode() {
+      return node;
+    }
+
+    public String getClientId() {
+      return clientId;
+    }
+
+    public void setClientId(final String clientId) {
+      this.clientId = clientId;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreePath.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreePath.java
new file mode 100644
index 0000000..c836701
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreePath.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import javax.swing.tree.TreeNode;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * Handles a path in a tree from the root node to the position inside this tree.
+ * The position of the root node is dropped in the list, because it would always be zero.
+ * The path of the root node as length 0.
+ * <br>
+ * Example:
+ * <pre>
+ *  + Root               Path: []
+ *  |
+ *  +-+ Node             Path: [0]
+ *  | |
+ *  | +-+ Sub-Node       Path: [0, 0]
+ *  | |
+ *  | +-+ Sub-Node       Path: [0, 1]
+ *  |
+ *  +-+ Node             Path: [1]
+ *    |
+ *    +-+ Sub-Node       Path: [1, 0]
+ *    |
+ *    +-+ Sub-Node       Path: [1, 1]
+ *    |
+ *    +-+ Sub-Node       Path: [1, 2]
+ * </pre>
+ *
+ * @since 1.5.0
+ */
+public class TreePath implements Serializable {
+
+  private final int[] path;
+
+  public TreePath(final int... path) {
+    this.path = path;
+  }
+
+  public TreePath(final List<Integer> pathList) {
+    path = new int[pathList.size()];
+    for (int i = 0; i < path.length; i++) {
+      path[i] = pathList.get(i);
+    }
+  }
+
+  public TreePath(TreeNode node) {
+    if (node == null) {
+      throw new IllegalArgumentException();
+    }
+
+    final List<TreeNode> list = new ArrayList<TreeNode>();
+    int n = 0;
+    while (node != null) {
+      list.add(node);
+      node = node.getParent();
+      n++;
+    }
+    path = new int[n - 1];
+    for (int i = n - 2; i >= 0; i--) {
+      final TreeNode parent = list.get(i + 1);
+      final TreeNode child = list.get(i);
+      for (int j = 0; j < parent.getChildCount(); j++) {
+        if (parent.getChildAt(j) == child) { // == is okay in this case
+          path[n - 2 - i] = j;
+          break;
+        }
+      }
+    }
+  }
+
+  public int[] getPath() {
+    return path;
+  }
+
+  public TreePath getParent() {
+    return new TreePath(Arrays.copyOf(path, path.length - 1));
+  }
+
+  public boolean isRoot() {
+    return path.length == 0;
+  }
+
+  public int getLength() {
+    return path.length;
+  }
+
+  @Override
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    final TreePath nodeIndex = (TreePath) o;
+    return Arrays.equals(path, nodeIndex.path);
+
+  }
+
+  @Override
+  public int hashCode() {
+    return path != null ? Arrays.hashCode(path) : 0;
+  }
+
+  @Override
+  public String toString() {
+    return Arrays.toString(path);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeState.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeState.java
new file mode 100644
index 0000000..d21a83f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/model/TreeState.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import java.io.Serializable;
+
+public class TreeState implements Serializable, ScrollPositionState {
+
+  private ExpandedState expandedState;
+  private SelectedState selectedState;
+  private ScrollPosition scrollPosition;
+
+  public TreeState() {
+    this(new ExpandedState(2), new SelectedState(), new ScrollPosition());
+  }
+
+  public TreeState(final ExpandedState expandedState, final SelectedState selectedState) {
+    this(expandedState, selectedState, new ScrollPosition());
+  }
+
+  public TreeState(
+      final ExpandedState expandedState, final SelectedState selectedState, final ScrollPosition scrollPosition) {
+    this.expandedState = expandedState;
+    this.selectedState = selectedState;
+    this.scrollPosition = scrollPosition;
+  }
+
+  public ExpandedState getExpandedState() {
+    return expandedState;
+  }
+
+  public SelectedState getSelectedState() {
+    return selectedState;
+  }
+
+  @Override
+  public ScrollPosition getScrollPosition() {
+    return scrollPosition;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/portlet/PortletUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/portlet/PortletUtils.java
new file mode 100644
index 0000000..77f6a74
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/portlet/PortletUtils.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.portlet;
+
+import javax.portlet.PortletRequest;
+
+/**
+ * Static utility class for portlet-related operations.
+ */
+public final class PortletUtils {
+
+  private static final boolean PORTLET_API_AVAILABLE;
+
+  static {
+    boolean result;
+    try {
+      result = PortletRequest.class != null;
+    } catch (final NoClassDefFoundError e) {
+      result = false;
+    }
+    PORTLET_API_AVAILABLE = result;
+  }
+
+  private PortletUtils() {
+    // avoid instantiation
+  }
+
+  /**
+   * The Portlet API is optional in the class path. We are only allowed to check instance of e. g. PortletRequest,
+   * if the API exists.
+   *
+   * @return Are the Portlet classes available?
+   */
+  public static boolean isPortletApiAvailable() {
+    return PORTLET_API_AVAILABLE;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/GenericRenderer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/GenericRenderer.java
new file mode 100644
index 0000000..08afa94
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/GenericRenderer.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit;
+
+import javax.faces.render.Renderer;
+
+public class GenericRenderer extends Renderer {
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/LabelWithAccessKey.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/LabelWithAccessKey.java
new file mode 100644
index 0000000..a18c0be
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/LabelWithAccessKey.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.SupportsAccessKey;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import java.util.Locale;
+
+public final class LabelWithAccessKey {
+
+  private static final Logger LOG = LoggerFactory.getLogger(LabelWithAccessKey.class);
+
+  private final String label;
+  private final Character accessKey;
+  private final int pos;
+
+  public LabelWithAccessKey(final SupportsAccessKey component) {
+    this(component, false);
+  }
+
+  public LabelWithAccessKey(final SupportsAccessKey component, final boolean preferItemLabel) {
+
+    String label0;
+    Character accessKey0;
+    int pos0 = -1;
+
+    label0 = component.getLabel();
+
+    // compatibility since TOBAGO-1093
+    if (preferItemLabel) {
+      final String itemLabel = ComponentUtils.getStringAttribute((UIComponent) component, Attributes.itemLabel);
+      if (itemLabel != null) {
+        label0 = itemLabel;
+      }
+    }
+
+    accessKey0 = component.getAccessKey();
+    if (accessKey0 != null) {
+      accessKey0 = Character.toLowerCase(accessKey0);
+      if (!isPermitted(accessKey0)) {
+        LOG.warn("Ignoring illegal access key: " + accessKey0);
+        accessKey0 = null;
+      }
+    }
+
+    if (accessKey0 != null && label0 != null) {
+      pos0 = label0.toLowerCase(Locale.ENGLISH).indexOf(accessKey0);
+    }
+
+    label = label0;
+    accessKey = accessKey0;
+    pos = pos0;
+  }
+
+  public String getLabel() {
+    return label;
+  }
+
+  public Character getAccessKey() {
+    return accessKey;
+  }
+
+  public int getPos() {
+    return pos;
+  }
+
+  /**
+   * Ensures, that no illegal character will be write out.
+   * (If this is changed from only allowing normal letters and numbers, the renderers may change the escaping)
+   */
+  private boolean isPermitted(final Character accessKey) {
+    return accessKey == null || accessKey >= 'a' && accessKey <= 'z' || accessKey >= '0' && accessKey <= '9';
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/RendererBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/RendererBase.java
new file mode 100644
index 0000000..a94ea55
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/RendererBase.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit;
+
+import org.apache.myfaces.tobago.internal.webapp.TobagoResponseWriterWrapper;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.component.ValueHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseWriter;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.render.Renderer;
+
+public class RendererBase extends Renderer {
+
+  protected String getCurrentValue(final FacesContext facesContext, final UIComponent component) {
+
+    if (component instanceof ValueHolder) {
+      final ValueHolder valueHolder = (ValueHolder) component;
+      if (valueHolder instanceof EditableValueHolder) {
+        final EditableValueHolder editableValueHolder = (EditableValueHolder) component;
+        final Object submittedValue = editableValueHolder.getSubmittedValue();
+        if (submittedValue != null || !editableValueHolder.isValid()) {
+          return (String) submittedValue;
+        }
+      }
+      String currentValue = null;
+      final Object result = ((ValueHolder) component).getValue();
+      if (result != null) {
+        currentValue = ComponentUtils.getFormattedValue(facesContext, component, result);
+      }
+      return currentValue;
+    } else {
+      return null;
+    }
+  }
+
+  @Override
+  public Object getConvertedValue(final FacesContext context, final UIComponent component, final Object submittedValue)
+      throws ConverterException {
+    if (!(submittedValue instanceof String)) {
+      return submittedValue;
+    }
+    final Converter converter = ComponentUtils.getConverter(context, component, submittedValue);
+    if (converter != null) {
+      return converter.getAsObject(context, component, (String) submittedValue);
+    } else {
+      return submittedValue;
+    }
+  }
+
+  public void onComponentCreated(
+      final FacesContext facesContext, final UIComponent component, final UIComponent parent) {
+  }
+
+  protected TobagoResponseWriter getResponseWriter(final FacesContext facesContext) {
+    final ResponseWriter writer = facesContext.getResponseWriter();
+    if (writer instanceof TobagoResponseWriter) {
+      return (TobagoResponseWriter) writer;
+    } else {
+      return new TobagoResponseWriterWrapper(writer);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java
new file mode 100644
index 0000000..37e147c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/TobagoRenderKit.java
@@ -0,0 +1,181 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit;
+
+import org.apache.myfaces.tobago.application.ProjectStage;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.internal.webapp.DebugResponseWriterWrapper;
+import org.apache.myfaces.tobago.internal.webapp.HtmlResponseWriter;
+import org.apache.myfaces.tobago.internal.webapp.XmlResponseWriter;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.FactoryFinder;
+import javax.faces.context.FacesContext;
+import javax.faces.context.ResponseStream;
+import javax.faces.context.ResponseWriter;
+import javax.faces.render.ClientBehaviorRenderer;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.Renderer;
+import javax.faces.render.ResponseStateManager;
+import java.io.OutputStream;
+import java.io.Writer;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+public class TobagoRenderKit extends RenderKit {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoRenderKit.class);
+
+  private final RenderKit htmlBasicRenderKit;
+
+  private Map<Key, Renderer> renderers = new HashMap<Key, Renderer>();
+
+  public TobagoRenderKit() {
+    RenderKitFactory rkFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+    htmlBasicRenderKit =
+        rkFactory.getRenderKit(FacesContext.getCurrentInstance(), RenderKitFactory.HTML_BASIC_RENDER_KIT);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Creating TobagoRenderKit with base: {}", htmlBasicRenderKit);
+    }
+  }
+
+  @Override
+  public Renderer getRenderer(final String family, final String rendererType) {
+    Renderer renderer = renderers.get(new Key(family, rendererType));
+    if (renderer == null) {
+      renderer = htmlBasicRenderKit.getRenderer(family, rendererType);
+    }
+
+    if (renderer == null) {
+      LOG.error("The class which was found by the ResourceManager cannot be "
+          + "found or instantiated: classname='" + rendererType + "'");
+    }
+
+    return renderer;
+  }
+
+  @Override
+  public ResponseWriter createResponseWriter(
+      final Writer writer, final String contentTypeList, final String characterEncoding) {
+    String contentType;
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    if (facesContext.getPartialViewContext().isAjaxRequest()) {
+      contentType = "text/xml";
+    } else if (contentTypeList == null) {
+      contentType = "text/html";
+    } else {
+      contentType = "text/html";
+      LOG.warn("Content-Type '{}' not supported! Using ''{}", contentTypeList, contentType);
+    }
+
+// XXX enable xhtml here, by hand:
+//    contentType = "application/xhtml+xml";
+
+    boolean xml = false;
+    if ("application/xhtml+xml".equals(contentType)
+        || "application/xhtml".equals(contentType)
+        || "application/xml".equals(contentType)
+        || "text/xml".equals(contentType)) {
+      xml = true;
+    }
+
+    TobagoResponseWriter responseWriter;
+    if (xml) {
+      responseWriter = new XmlResponseWriter(writer, contentType, characterEncoding);
+    } else {
+      responseWriter = new HtmlResponseWriter(writer, contentType, characterEncoding);
+    }
+    if (TobagoConfig.getInstance(facesContext).getProjectStage() == ProjectStage.Development) {
+      responseWriter = new DebugResponseWriterWrapper(responseWriter);
+    }
+    return responseWriter;
+  }
+
+  @Override
+  public void addRenderer(final String family, final String rendererType, final Renderer renderer) {
+    renderers.put(new Key(family, rendererType), renderer);
+  }
+
+  @Override
+  public ResponseStateManager getResponseStateManager() {
+    return htmlBasicRenderKit.getResponseStateManager();
+  }
+
+  @Override
+  public ResponseStream createResponseStream(final OutputStream outputStream) {
+    return htmlBasicRenderKit.createResponseStream(outputStream);
+  }
+
+  @Override
+  public void addClientBehaviorRenderer(String type, ClientBehaviorRenderer renderer) {
+    htmlBasicRenderKit.addClientBehaviorRenderer(type, renderer);
+  }
+
+  @Override
+  public ClientBehaviorRenderer getClientBehaviorRenderer(String type) {
+    return htmlBasicRenderKit.getClientBehaviorRenderer(type);
+  }
+
+  @Override
+  public Iterator<String> getClientBehaviorRendererTypes() {
+    return htmlBasicRenderKit.getClientBehaviorRendererTypes();
+  }
+
+  private static final class Key {
+    private final String family;
+    private final String rendererType;
+
+    private Key(final String family, final String rendererType) {
+      this.family = family;
+      this.rendererType = rendererType;
+    }
+
+    public boolean equals(final Object o) {
+      if (this == o) {
+        return true;
+      }
+      if (o == null || getClass() != o.getClass()) {
+        return false;
+      }
+
+      final Key key = (Key) o;
+
+      if (!family.equals(key.family)) {
+        return false;
+      }
+      if (!rendererType.equals(key.rendererType)) {
+        return false;
+      }
+
+      return true;
+    }
+
+    public int hashCode() {
+      int result;
+      result = family.hashCode();
+      result = 31 * result + rendererType.hashCode();
+      return result;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
new file mode 100644
index 0000000..eee4237
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapClass.java
@@ -0,0 +1,281 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.myfaces.tobago.layout.ColumnPartition;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * CSS classes for the Bootstrap Library.
+ *
+ * @since 3.0.0
+ */
+public enum BootstrapClass implements CssItem {
+
+  ACTIVE("active"),
+  ALERT("alert"),
+  ALERT_DANGER("alert-danger"),
+  ALERT_WARNING("alert-warning"),
+  ALERT_INFO("alert-info"),
+  ALERT_DISMISSIBLE("alert-dismissible"),
+  BG_INVERSE("bg-inverse"),
+  BTN("btn"),
+  BTN_GROUP("btn-group"),
+  BTN_LINK("btn-link"),
+  BTN_PRIMARY("btn-primary"),
+  BTN_SECONDARY("btn-secondary"),
+  BTN_TOOLBAR("btn-toolbar"),
+  CARD("card"),
+  CARD_BLOCK("card-block"),
+  CARD_HEADER("card-header"),
+  CARD_TITLE("card-title"),
+  CLOSE("close"),
+  COLLAPSE("collapse"),
+  COL_FORM_LABEL("col-form-label"),
+  COL_LG_1("col-lg-1"),
+  COL_LG_2("col-lg-2"),
+  COL_LG_3("col-lg-3"),
+  COL_LG_4("col-lg-4"),
+  COL_LG_5("col-lg-5"),
+  COL_LG_6("col-lg-6"),
+  COL_LG_7("col-lg-7"),
+  COL_LG_8("col-lg-8"),
+  COL_LG_9("col-lg-9"),
+  COL_LG_10("col-lg-10"),
+  COL_LG_11("col-lg-11"),
+  COL_LG_12("col-lg-12"),
+  COL_MD_1("col-md-1"),
+  COL_MD_2("col-md-2"),
+  COL_MD_3("col-md-3"),
+  COL_MD_4("col-md-4"),
+  COL_MD_5("col-md-5"),
+  COL_MD_6("col-md-6"),
+  COL_MD_7("col-md-7"),
+  COL_MD_8("col-md-8"),
+  COL_MD_9("col-md-9"),
+  COL_MD_10("col-md-10"),
+  COL_MD_11("col-md-11"),
+  COL_MD_12("col-md-12"),
+  COL_SM_1("col-sm-1"),
+  COL_SM_2("col-sm-2"),
+  COL_SM_3("col-sm-3"),
+  COL_SM_4("col-sm-4"),
+  COL_SM_5("col-sm-5"),
+  COL_SM_6("col-sm-6"),
+  COL_SM_7("col-sm-7"),
+  COL_SM_8("col-sm-8"),
+  COL_SM_9("col-sm-9"),
+  COL_SM_10("col-sm-10"),
+  COL_SM_11("col-sm-11"),
+  COL_SM_12("col-sm-12"),
+  COL_XS_1("col-xs-1"),
+  COL_XS_2("col-xs-2"),
+  COL_XS_3("col-xs-3"),
+  COL_XS_4("col-xs-4"),
+  COL_XS_5("col-xs-5"),
+  COL_XS_6("col-xs-6"),
+  COL_XS_7("col-xs-7"),
+  COL_XS_8("col-xs-8"),
+  COL_XS_9("col-xs-9"),
+  COL_XS_10("col-xs-10"),
+  COL_XS_11("col-xs-11"),
+  COL_XS_12("col-xs-12"),
+  CONTAINER("container"),
+  CONTAINER_FLUID("container-fluid"),
+  D_INLINE("d-inline"),
+  DISABLED("disabled"),
+  DROPDOWN("dropdown"),
+  DROPDOWN_ITEM("dropdown-item"),
+  DROPDOWN_MENU("dropdown-menu"),
+  DROPDOWN_TOGGLE("dropdown-toggle"),
+  FADE("fade"),
+  FIGURE("figure"),
+  FIGURE_CAPTION("figure-caption"),
+  FIGURE_IMG("figure-img"),
+  FORM_CHECK("form-check"),
+  FORM_CHECK_INLINE("form-check-inline"),
+  FORM_CHECK_INPUT("form-check-input"),
+  FORM_CHECK_LABEL("form-check-label"),
+  FORM_CONTROL("form-control"),
+  FORM_CONTROL_STATIC("form-control-static"),
+  FORM_GROUP("form-group"),
+  FORM_INLINE("form-inline"),
+  HAS_DANGER("has-danger"),
+  HAS_SUCCESS("has-success"),
+  HAS_WARNING("has-warning"),
+  HIDDEN_SM_UP("hidden-sm-up"),
+  INPUT_GROUP("input-group"),
+  INPUT_GROUP_ADDON("input-group-addon"),
+  INPUT_GROUP_BTN("input-group-btn"),
+  INVISIBLE("invisible"),
+  MODAL("modal"),
+  MODAL_DIALOG("modal-dialog"),
+  MODAL_CONTENT("modal-content"),
+  NAV("nav"),
+  NAV_ITEM("nav-item"),
+  NAV_LINK("nav-link"),
+  NAV_TABS("nav-tabs"),
+  NAVBAR("navbar"),
+  NAVBAR_BRAND("navbar-brand"),
+  NAVBAR_DARK("navbar-dark"),
+  NAVBAR_FIXED_BOTTOM("navbar-fixed-bottom"),
+  NAVBAR_FIXED_TOP("navbar-fixed-top"),
+  NAVBAR_NAV("navbar-nav"),
+  NAVBAR_TOGGLEABLE_XS("navbar-toggleable-xs"),
+  NAVBAR_TOGGLER("navbar-toggler"),
+  OPEN("open"),
+  PAGE_ITEM("page-item"),
+  PAGE_LINK("page-link"),
+  PAGINATION("pagination"),
+  PROGRESS("progress"),
+  ROW("row"),
+  SR_ONLY("sr-only"),
+  TAB_CONTENT("tab-content"),
+  TAB_PANE("tab-pane"),
+  TABLE("table"),
+  TABLE_BORDERED("table-bordered"),
+  TABLE_HOVER("table-hover"),
+  TABLE_INFO("table-info"),
+  TABLE_INVERSE("table-inverse"),
+  TABLE_SM("table-sm"),
+  TABLE_STRIPED("table-striped");
+
+  private static final int SEVERITY_ERROR = FacesMessage.SEVERITY_ERROR.getOrdinal();
+  private static final int SEVERITY_WARN = FacesMessage.SEVERITY_WARN.getOrdinal();
+  private static final int SEVERITY_INFO = FacesMessage.SEVERITY_INFO.getOrdinal();
+
+  private final String name;
+
+  BootstrapClass(final String name) {
+    this.name = name;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  public static CssItem alert(final FacesMessage.Severity severity) {
+
+    // switch over severity.getOrdinal() doesn't work, because different implementations use different ordinals,
+    // see MYFACES-3768
+    // may be optimized with a cache...
+
+    if (severity == null) {
+      return null;
+    } else if (severity.getOrdinal() >= SEVERITY_ERROR) {
+      return ALERT_DANGER;
+    } else if (severity.getOrdinal() >= SEVERITY_WARN) {
+      return ALERT_WARNING;
+    } else if (severity.getOrdinal() >= SEVERITY_INFO) {
+      return ALERT_INFO;
+    } else {
+      return null;
+    }
+  }
+
+  public static CssItem maximumSeverity(final UIComponent input) {
+    final FacesMessage.Severity maximumSeverity = ComponentUtils.getMaximumSeverity(input);
+    if (maximumSeverity == null) {
+      return null;
+    } else if (maximumSeverity.getOrdinal() >= SEVERITY_ERROR) {
+      return HAS_DANGER;
+    } else if (maximumSeverity.getOrdinal() >= SEVERITY_WARN) {
+      return HAS_WARNING;
+    } else if (maximumSeverity.getOrdinal() >= SEVERITY_INFO) {
+      return TobagoClass.HAS__INFO;
+    } else {
+      return null;
+    }
+  }
+
+  public static class Generator {
+
+    private static final BootstrapClass[] EXTRA_SMALL = new BootstrapClass[]{
+        COL_XS_1, COL_XS_2, COL_XS_3, COL_XS_4,
+        COL_XS_5, COL_XS_6, COL_XS_7, COL_XS_8,
+        COL_XS_9, COL_XS_10, COL_XS_11, COL_XS_12,
+    };
+    private static final BootstrapClass[] SMALL = new BootstrapClass[]{
+        COL_SM_1, COL_SM_2, COL_SM_3, COL_SM_4,
+        COL_SM_5, COL_SM_6, COL_SM_7, COL_SM_8,
+        COL_SM_9, COL_SM_10, COL_SM_11, COL_SM_12,
+    };
+    private static final BootstrapClass[] MEDIUM = new BootstrapClass[]{
+        COL_MD_1, COL_MD_2, COL_MD_3, COL_MD_4,
+        COL_MD_5, COL_MD_6, COL_MD_7, COL_MD_8,
+        COL_MD_9, COL_MD_10, COL_MD_11, COL_MD_12,
+    };
+    private static final BootstrapClass[] LARGE = new BootstrapClass[]{
+        COL_LG_1, COL_LG_2, COL_LG_3, COL_LG_4,
+        COL_LG_5, COL_LG_6, COL_LG_7, COL_LG_8,
+        COL_LG_9, COL_LG_10, COL_LG_11, COL_LG_12,
+    };
+
+    private final ColumnPartition extraSmall;
+    private final ColumnPartition small;
+    private final ColumnPartition medium;
+    private final ColumnPartition large;
+
+    private int index = 0;
+
+    public Generator(
+        final ColumnPartition extraSmall, final ColumnPartition small, final ColumnPartition medium,
+        final ColumnPartition large) {
+      if (extraSmall == null && small == null && medium == null && large == null) {
+        this.extraSmall = ColumnPartition.PARTITION_12;
+      } else  {
+        this.extraSmall = extraSmall;
+      }
+      this.small = small;
+      this.medium = medium;
+      this.large = large;
+    }
+
+    public void reset() {
+      index = 0;
+    }
+
+    public void next() {
+      index++;
+    }
+
+    public BootstrapClass[] generate() {
+      ArrayList<BootstrapClass> result = new ArrayList<BootstrapClass>(4);
+      generate(result, extraSmall, EXTRA_SMALL);
+      generate(result, small, SMALL);
+      generate(result, medium, MEDIUM);
+      generate(result, large, LARGE);
+      return result.toArray(new BootstrapClass[result.size()]);
+    }
+
+    private void generate(
+        final List<BootstrapClass> result, final ColumnPartition partition, final BootstrapClass[] values) {
+      if (partition != null) {
+        result.add(values[partition.getPart(index % partition.getSize()) - 1]);
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapDateTimePickerClass.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapDateTimePickerClass.java
new file mode 100644
index 0000000..56f25f6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/BootstrapDateTimePickerClass.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+/**
+ * CSS classes for the Bootstrap-DateTimePicker-Library.
+ *
+ * @since 3.0.0
+ */
+public enum BootstrapDateTimePickerClass implements CssItem  {
+
+  DATEPICKERBUTTON("datepickerbutton");
+
+  private final String name;
+
+  BootstrapDateTimePickerClass(final String name) {
+    this.name = name;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Classes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Classes.java
new file mode 100644
index 0000000..11d1181
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Classes.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.commons.collections.map.MultiKeyMap;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.TobagoContext;
+import org.apache.myfaces.tobago.internal.util.Deprecation;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+/**
+ * <p>
+ * Builds the CSS class attribute of tags. The names will be generated in a formal way, so generic name (and
+ * abbreviation) are possible. The class works like a factory, so caching will be possible.
+ * </p>
+ * <p>
+ * The default naming conventions allow these values:
+ * </p>
+ * <ul>
+ *   <li>tobago-&lt;rendererName&gt;
+ *   <li>tobago-&lt;rendererName&gt;-markup-&lt;markupName&gt;
+ *   <li>tobago-&lt;rendererName&gt;-&lt;subElement&gt;
+ *   <li>tobago-&lt;rendererName&gt;-&lt;subElement&gt;-markup-&lt;markupName&gt;
+ * </ul>
+ * <br>
+ * where <ul> <li>&lt;rendererName&gt;, &lt;subElement&gt; and &lt;markupName&gt;
+ * must only contain ASCII-chars and -numbers</li>
+ * <li>&lt;rendererName&gt; is the rendererType with a lower case char as first char</li> <li>&lt;subElement&gt; is a
+ * sub element of the main tag in the output language (e.g. HTML)</li> <li>&lt;markupName&gt; is the name of an existing
+ * markup</li> </ul> If the markup contains more than one name, there will be generated more than one output string.
+ * E.g.: UIIn with Markup [readonly, error] will get the class "tobago-in tobago-in-markup-readonly
+ * tobago-in-markup-error".
+ *
+ * @deprecated since Tobago 3.0.0
+ */
+@Deprecated
+public final class Classes implements CssItem {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Classes.class);
+
+  /* With cache it seems to be 10 times faster */
+  private static final MultiKeyMap CACHE = new MultiKeyMap();
+
+  private final String stringValue;
+
+  public static Classes create(final UIComponent component) {
+    return create(component, true, null, null, false);
+  }
+
+  public static Classes create(final UIComponent component, final String sub) {
+    return create(component, true, sub, null, false);
+  }
+
+  public static Classes create(final UIComponent component, final Markup explicit) {
+    return create(component, true, null, explicit, false);
+  }
+
+  // TODO: clean up..., hope this is no longer needed...
+  public static Classes create(final UIComponent component, final String sub, final Markup explicit) {
+    return create(component, false, sub, explicit, false);
+  }
+
+  // XXX optimize synchronized
+  private static synchronized Classes create(
+      final UIComponent component, final boolean markupFromComponent, final String sub,
+      final Markup explicit, final boolean ignoreCheck) {
+    final String rendererName = StringUtils.uncapitalize(component.getRendererType());
+
+    Markup markup;
+    if (markupFromComponent) {
+      final Visual visual = (Visual) component;
+      markup = ComponentUtils.updateMarkup(component, visual.getMarkup());
+      if (explicit != null) {
+        markup = explicit.add(markup);
+      }
+    } else {
+      markup = explicit;
+    }
+
+//    Classes value = (Classes) CACHE.get(rendererName, markup, sub);
+//    if (value == null) {
+    final Classes value;
+    value = new Classes(rendererName, markup, sub, ignoreCheck);
+//      CACHE.put(rendererName, markup, sub, value);
+//      if (LOG.isDebugEnabled()) {
+//        LOG.debug("Element added (size={}) to cache (renderName='{}', markup='{}', sub='{}')",
+//            CACHE.size(), rendererName, markup, sub);
+//      }
+//    }
+    return value;
+  }
+  private Classes(final String rendererName, final Markup markup, final String sub, final boolean ignoreMarkupCheck) {
+
+    assert sub == null || StringUtils.isAlphanumeric(sub) : "Invalid sub element name: '" + sub + "'";
+
+    // These values are statistically tested length of the html class attribute
+    final StringBuilder builder = new StringBuilder(markup != null ? 80 : 32);
+    builder.append("tobago-");
+    builder.append(rendererName);
+    if (sub != null) {
+      builder.append('-');
+      builder.append(sub);
+    }
+    if (markup != null) {
+      final Theme theme = TobagoContext.getInstance(FacesContext.getCurrentInstance()).getTheme();
+      for (final String markupString : markup) {
+        if (ignoreMarkupCheck || theme.getRenderersConfig().isMarkupSupported(rendererName, markupString)) {
+          builder.append(' ');
+          builder.append("tobago-");
+          builder.append(rendererName);
+          if (sub != null) {
+            builder.append('-');
+            builder.append(sub);
+          }
+          builder.append("-markup-");
+          builder.append(markupString);
+        } else if ("none".equals(markupString)) {
+          Deprecation.LOG.warn("Markup 'none' is deprecated, please use a NULL pointer instead.");
+        } else {
+          LOG.warn("Ignoring unknown markup='" + markupString + "' for rendererName='" + rendererName + "'");
+        }
+      }
+    }
+    this.stringValue = builder.toString();
+  }
+
+  public String getName() {
+    return stringValue;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CssItem.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CssItem.java
new file mode 100644
index 0000000..bdb70f0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CssItem.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import java.io.Serializable;
+
+/**
+ * @since Tobago 3.0.0
+ */
+public interface CssItem extends Serializable {
+
+  String getName();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CustomClass.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CustomClass.java
new file mode 100644
index 0000000..8a82b41
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CustomClass.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Since Tobago 3.0.0
+ */
+public class CustomClass implements CssItem {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CustomClass.class);
+
+  private static final Pattern CSS_CLASS_PATTERN = Pattern.compile("[\\w-]+");
+
+  private final String[] classes;
+
+  private CustomClass(List<String> list) {
+    classes = list.toArray(new String[list.size()]);
+  }
+
+  public static CustomClass valueOf(String text) {
+
+    final StringTokenizer tokenizer = new StringTokenizer(text, " ");
+    final List<String> result = new ArrayList<String>(tokenizer.countTokens());
+    while (tokenizer.hasMoreTokens()) {
+      final String token = tokenizer.nextToken();
+      final Matcher matcher = CSS_CLASS_PATTERN.matcher(token);
+      if (matcher.matches()) {
+        if (!result.contains(token)) {
+          result.add(token);
+        } else {
+          LOG.warn("Duplicate CSS class name: '{}' which is part of '{}'", token, text);
+        }
+      } else {
+        LOG.error("Invalid CSS class name: '{}' which is part of '{}'", token, text);
+      }
+    }
+    if (result.size() > 0) {
+      return new CustomClass(result);
+    } else {
+      return null;
+    }
+
+  }
+
+  @Override
+  public String getName() {
+    switch (classes.length) {
+      case 0:
+        return "";
+      case 1:
+        return classes[0];
+      default:
+        final StringBuilder builder = new StringBuilder(classes[0]);
+        for (int i = 1; i < classes.length; i++) {
+          builder.append(' ');
+          builder.append(classes[i]);
+        }
+        return builder.toString();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CustomClassEditor.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CustomClassEditor.java
new file mode 100644
index 0000000..8ed290a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/CustomClassEditor.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import java.beans.PropertyEditorSupport;
+
+/**
+ * Converter for {@link org.apache.myfaces.tobago.renderkit.css.CustomClass}
+ *
+ * XXX preliminary
+ *
+ * @since 3.0.0
+ */
+public class CustomClassEditor extends PropertyEditorSupport {
+
+  @Override
+  public void setAsText(final String text) throws IllegalArgumentException {
+    setValue(CustomClass.valueOf(text));
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/FontAwesomeIconEncoder.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/FontAwesomeIconEncoder.java
new file mode 100644
index 0000000..6f94eed
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/FontAwesomeIconEncoder.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.EnumMap;
+import java.util.regex.Pattern;
+
+public class FontAwesomeIconEncoder implements IconEncoder {
+
+  private static final Logger LOG = LoggerFactory.getLogger(FontAwesomeIconEncoder.class);
+
+  private static final CssItem FA = new FontAwesomeCssItem("fa");
+
+  private static final Pattern PATTERN = Pattern.compile("^(fa(-[a-z]+)+)$");
+
+
+  private EnumMap<Icons, CssItem> icons;
+
+
+  public FontAwesomeIconEncoder() {
+    icons = new EnumMap<Icons, CssItem>(Icons.class);
+    for (Icons icon : Icons.values()) {
+      icons.put(icon, new FontAwesomeCssItem("fa-" + icon.name().toLowerCase().replaceAll("_", "-")));
+    }
+  }
+
+  @Override
+  public void encode(final TobagoResponseWriter writer, final Icons icon, final Style style, final CssItem... cssItems)
+      throws IOException {
+    writer.startElement(HtmlElements.I);
+    writer.writeStyleAttribute(style);
+    writer.writeClassAttribute(FA, generateClass(icon), cssItems);
+    writer.endElement(HtmlElements.I);
+  }
+
+  private CssItem generateClass(final Icons icon) {
+    if (icon == null) {
+      return null;
+    }
+    CssItem result = icons.get(icon);
+    if (result == null) {
+      LOG.warn("Missing icon: '" + icon + "'");
+    }
+    return result;
+  }
+
+  public static CssItem generateClass(final String name) {
+
+    return new CssItem() {
+
+      @Override
+      public String getName() {
+        // XXX cleanup, should be resolved with the ResourceManager... ? TBD
+        // todo: regexp check
+        if (PATTERN.matcher(name).matches()) {
+          return name;
+        } else {
+          LOG.warn("Unknown Icon: '" + name + "'");
+          return null;
+        }
+      }
+    };
+  }
+
+  private static final class FontAwesomeCssItem implements CssItem {
+
+    private String name;
+
+    public FontAwesomeCssItem(String name) {
+      this.name = name;
+    }
+
+    @Override
+    public String getName() {
+      return name;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/IconEncoder.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/IconEncoder.java
new file mode 100644
index 0000000..1edf798
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/IconEncoder.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import java.io.IOException;
+
+public interface IconEncoder {
+
+  void encode(TobagoResponseWriter writer, Icons icon, Style style, final CssItem... cssItems) throws IOException;
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Icons.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Icons.java
new file mode 100644
index 0000000..46720ec
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Icons.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+public enum Icons {
+
+  ANGLE_DOUBLE_LEFT,
+  ANGLE_DOUBLE_RIGHT,
+  ANGLE_DOWN,
+  ANGLE_LEFT,
+  ANGLE_RIGHT,
+  ANGLE_UP,
+  BACKWARD,
+  BARS,
+  CALENDAR,
+  CLOCK_O,
+  ELLIPSIS_H,
+  FOLDER_OPEN,
+  FORWARD,
+  MINUS_SQUARE_O,
+  PLUS_SQUARE_O,
+  SQUARE_O,
+  STEP_BACKWARD,
+  STEP_FORWARD;
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Style.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Style.java
new file mode 100644
index 0000000..e44fa00
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/Style.java
@@ -0,0 +1,679 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.myfaces.tobago.component.UIStyle;
+import org.apache.myfaces.tobago.layout.Display;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.Overflow;
+import org.apache.myfaces.tobago.layout.Position;
+import org.apache.myfaces.tobago.layout.TextAlign;
+
+import java.io.Serializable;
+
+/**
+ * A subset of the CSS style used by Tobago. It's more or less the layout specific part.
+ */
+public class Style implements Serializable {
+
+  private static final long serialVersionUID = 5L;
+
+  private Measure width;
+  private Measure height;
+
+  private Measure minWidth;
+  private Measure minHeight;
+  private Measure maxWidth;
+  private Measure maxHeight;
+
+  private Measure left;
+  private Measure right;
+  private Measure top;
+  private Measure bottom;
+
+  private Measure paddingLeft;
+  private Measure paddingRight;
+  private Measure paddingTop;
+  private Measure paddingBottom;
+
+  private Measure marginLeft;
+  private Measure marginRight;
+  private Measure marginTop;
+  private Measure marginBottom;
+
+  private Overflow overflowX;
+  private Overflow overflowY;
+  private Display display;
+  private Position position;
+
+  private String backgroundImage;
+  private String backgroundPosition;
+  private Integer zIndex; // TBD
+  private TextAlign textAlign;
+
+  private Boolean empty;
+
+  public Style() {
+  }
+
+  public Style(final UIStyle style) {
+
+    width = style.getWidth();
+    height = style.getHeight();
+
+    minWidth = style.getMinWidth();
+    minHeight = style.getMinHeight();
+    maxWidth = style.getMaxWidth();
+    maxHeight = style.getMaxHeight();
+
+    left = style.getLeft();
+    right = style.getRight();
+    top = style.getTop();
+    bottom = style.getBottom();
+
+    paddingLeft = style.getPaddingLeft();
+    paddingRight = style.getPaddingRight();
+    paddingTop = style.getPaddingTop();
+    paddingBottom = style.getPaddingBottom();
+
+    marginLeft = style.getMarginLeft();
+    marginRight = style.getMarginRight();
+    marginTop = style.getMarginTop();
+    marginBottom = style.getMarginBottom();
+
+    overflowX = style.getOverflowX();
+    overflowY = style.getOverflowY();
+    display = style.getDisplay();
+    position = style.getPosition();
+
+    // tbd: backgroundImage from UIStyle?
+    // tbd: backgroundPosition from UIStyle?
+    // tbd: zIndex from UIStyle?
+    textAlign = style.getTextAlign();
+
+    checkEmptiness();
+  }
+
+  /**
+   * Checks if the encode string holds free text, which must be escaped.
+   * This is the case for image URLs.
+   * For {@link Measure}, and enum types like {@link Display} no escaping is needed.
+   */
+  public boolean needsToBeEscaped() {
+    return backgroundImage != null;
+  }
+
+  public boolean isEmpty() {
+    if (empty == null) {
+      checkEmptiness();
+    }
+    return empty;
+  }
+
+  public void checkEmptiness() {
+    empty
+        = width == null
+        && height == null
+
+        && minWidth == null
+        && minHeight == null
+        && maxWidth == null
+        && maxHeight == null
+
+        && left == null
+        && right == null
+        && top == null
+        && bottom == null
+
+        && marginLeft == null
+        && marginRight == null
+        && marginTop == null
+        && marginBottom == null
+
+        && paddingLeft == null
+        && paddingRight == null
+        && paddingTop == null
+        && paddingBottom == null
+
+        && display == null
+        && position == null
+        && overflowX == null
+        && overflowY == null
+
+        && backgroundImage == null
+        && backgroundPosition == null
+        && zIndex == null
+        && textAlign == null;
+  }
+
+  public String encode() {
+    final StringBuilder buf = new StringBuilder();
+    if (width != null) {
+      buf.append("width:");
+      buf.append(width.serialize());
+      buf.append(';');
+    }
+    if (height != null) {
+      buf.append("height:");
+      buf.append(height.serialize());
+      buf.append(';');
+    }
+    if (minWidth != null) {
+      buf.append("min-width:");
+      buf.append(minWidth.serialize());
+      buf.append(';');
+    }
+    if (minHeight != null) {
+      buf.append("min-height:");
+      buf.append(minHeight.serialize());
+      buf.append(';');
+    }
+    if (maxWidth != null) {
+      buf.append("max-width:");
+      buf.append(maxWidth.serialize());
+      buf.append(';');
+    }
+    if (maxHeight != null) {
+      buf.append("max-height:");
+      buf.append(maxHeight.serialize());
+      buf.append(';');
+    }
+    if (left != null) {
+      buf.append("left:");
+      buf.append(left.serialize());
+      buf.append(';');
+    }
+    if (right != null) {
+      buf.append("right:");
+      buf.append(right.serialize());
+      buf.append(';');
+    }
+    if (top != null) {
+      buf.append("top:");
+      buf.append(top.serialize());
+      buf.append(';');
+    }
+    if (bottom != null) {
+      buf.append("bottom:");
+      buf.append(bottom.serialize());
+      buf.append(';');
+    }
+    if (paddingLeft != null) {
+      buf.append("padding-left:");
+      buf.append(paddingLeft.serialize());
+      buf.append(';');
+    }
+    if (paddingRight != null) {
+      buf.append("padding-right:");
+      buf.append(paddingRight.serialize());
+      buf.append(';');
+    }
+    if (paddingTop != null) {
+      buf.append("padding-top:");
+      buf.append(paddingTop.serialize());
+      buf.append(';');
+    }
+    if (paddingBottom != null) {
+      buf.append("padding-bottom:");
+      buf.append(paddingBottom.serialize());
+      buf.append(';');
+    }
+    if (marginLeft != null) {
+      buf.append("margin-left:");
+      buf.append(marginLeft.serialize());
+      buf.append(';');
+    }
+    if (marginRight != null) {
+      buf.append("margin-right:");
+      buf.append(marginRight.serialize());
+      buf.append(';');
+    }
+    if (marginTop != null) {
+      buf.append("margin-top:");
+      buf.append(marginTop.serialize());
+      buf.append(';');
+    }
+    if (marginBottom != null) {
+      buf.append("margin-bottom:");
+      buf.append(marginBottom.serialize());
+      buf.append(';');
+    }
+    if (overflowX != null) {
+      buf.append("overflow-x:");
+      buf.append(overflowX.name());
+      buf.append(';');
+    }
+    if (overflowY != null) {
+      buf.append("overflow-y:");
+      buf.append(overflowY.name());
+      buf.append(';');
+    }
+    if (display != null) {
+      buf.append("display:");
+      buf.append(display.name());
+      buf.append(';');
+    }
+    if (position != null) {
+      buf.append("position:");
+      buf.append(position.name());
+      buf.append(';');
+    }
+    if (backgroundImage != null) {
+      buf.append("background-image:");
+      buf.append(backgroundImage);
+      buf.append(';');
+    }
+    if (backgroundPosition != null) {
+      buf.append("background-position:");
+      buf.append(backgroundPosition);
+      buf.append(';');
+    }
+    if (zIndex != null) {
+      buf.append("z-index:");
+      buf.append(zIndex);
+      buf.append(';');
+    }
+    if (textAlign != null) {
+      buf.append("text-align:");
+      buf.append(textAlign.name());
+      buf.append(';');
+    }
+
+    return buf.toString();
+  }
+
+  public String encodeJson() {
+    final StringBuilder buf = new StringBuilder("{");
+    if (width != null) {
+      buf.append("\"width\":\"");
+      buf.append(width.serialize());
+      buf.append("\",");
+    }
+    if (height != null) {
+      buf.append("\"height\":\"");
+      buf.append(height.serialize());
+      buf.append("\",");
+    }
+    if (minWidth != null) {
+      buf.append("\"minWidth\":\"");
+      buf.append(minWidth.serialize());
+      buf.append("\",");
+    }
+    if (minHeight != null) {
+      buf.append("\"minHeight\":\"");
+      buf.append(minHeight.serialize());
+      buf.append("\",");
+    }
+    if (maxWidth != null) {
+      buf.append("\"maxWidth\":\"");
+      buf.append(maxWidth.serialize());
+      buf.append("\",");
+    }
+    if (maxHeight != null) {
+      buf.append("\"maxHeight\":\"");
+      buf.append(maxHeight.serialize());
+      buf.append("\",");
+    }
+    if (left != null) {
+      buf.append("\"left\":\"");
+      buf.append(left.serialize());
+      buf.append("\",");
+    }
+    if (right != null) {
+      buf.append("\"right\":\"");
+      buf.append(right.serialize());
+      buf.append("\",");
+    }
+    if (top != null) {
+      buf.append("\"top\":\"");
+      buf.append(top.serialize());
+      buf.append("\",");
+    }
+    if (bottom != null) {
+      buf.append("\"bottom\":\"");
+      buf.append(bottom.serialize());
+      buf.append("\",");
+    }
+    if (paddingLeft != null) {
+      buf.append("\"paddingLeft\":\"");
+      buf.append(paddingLeft.serialize());
+      buf.append("\",");
+    }
+    if (paddingRight != null) {
+      buf.append("\"paddingRight\":\"");
+      buf.append(paddingRight.serialize());
+      buf.append("\",");
+    }
+    if (paddingTop != null) {
+      buf.append("\"paddingTop\":\"");
+      buf.append(paddingTop.serialize());
+      buf.append("\",");
+    }
+    if (paddingBottom != null) {
+      buf.append("\"paddingBottom\":\"");
+      buf.append(paddingBottom.serialize());
+      buf.append("\",");
+    }
+    if (marginLeft != null) {
+      buf.append("\"marginLeft\":\"");
+      buf.append(marginLeft.serialize());
+      buf.append("\",");
+    }
+    if (marginRight != null) {
+      buf.append("\"marginRight\":\"");
+      buf.append(marginRight.serialize());
+      buf.append("\",");
+    }
+    if (marginTop != null) {
+      buf.append("\"marginTop\":\"");
+      buf.append(marginTop.serialize());
+      buf.append("\",");
+    }
+    if (marginBottom != null) {
+      buf.append("\"marginBottom\":\"");
+      buf.append(marginBottom.serialize());
+      buf.append("\",");
+    }
+    if (overflowX != null) {
+      buf.append("\"overflowX\":\"");
+      buf.append(overflowX.name());
+      buf.append("\",");
+    }
+    if (overflowY != null) {
+      buf.append("\"overflowY\":\"");
+      buf.append(overflowY.name());
+      buf.append("\",");
+    }
+    if (display != null) {
+      buf.append("\"display\":\"");
+      buf.append(display.name());
+      buf.append("\",");
+    }
+    if (position != null) {
+      buf.append("\"position\":\"");
+      buf.append(position.name());
+      buf.append("\",");
+    }
+    if (backgroundImage != null) {
+      buf.append("\"backgroundImage\":\"");
+      buf.append(backgroundImage);
+      buf.append("\",");
+    }
+    if (backgroundPosition != null) {
+      buf.append("\"backgroundPosition\":\"");
+      buf.append(backgroundPosition);
+      buf.append("\",");
+    }
+    if (zIndex != null) {
+      buf.append("\"zIndex\":");
+      buf.append(zIndex);
+      buf.append(",");
+    }
+    if (textAlign != null) {
+      buf.append("\"textAlign\":\"");
+      buf.append(textAlign.name());
+      buf.append("\",");
+    }
+
+    if (buf.length() > 1) {
+      buf.deleteCharAt(buf.length() - 1);
+    }
+
+    buf.append('}');
+    return buf.toString();
+  }
+
+  public Measure getWidth() {
+    return width;
+  }
+
+  public void setWidth(final Measure width) {
+    empty = null;
+    this.width = width;
+  }
+
+  public Measure getHeight() {
+    return height;
+  }
+
+  public void setHeight(final Measure height) {
+    empty = null;
+    this.height = height;
+  }
+
+  public Measure getMinWidth() {
+    return minWidth;
+  }
+
+  public void setMinWidth(Measure minWidth) {
+    empty = null;
+    this.minWidth = minWidth;
+  }
+
+  public Measure getMinHeight() {
+    return minHeight;
+  }
+
+  public void setMinHeight(Measure minHeight) {
+    empty = null;
+    this.minHeight = minHeight;
+  }
+
+  public Measure getMaxWidth() {
+    return maxWidth;
+  }
+
+  public void setMaxWidth(Measure maxWidth) {
+    empty = null;
+    this.maxWidth = maxWidth;
+  }
+
+  public Measure getMaxHeight() {
+    return maxHeight;
+  }
+
+  public void setMaxHeight(Measure maxHeight) {
+    empty = null;
+    this.maxHeight = maxHeight;
+  }
+
+  public Measure getLeft() {
+    return left;
+  }
+
+  public void setLeft(final Measure left) {
+    empty = null;
+    this.left = left;
+  }
+
+  public Measure getRight() {
+    return right;
+  }
+
+  public void setRight(Measure right) {
+    empty = null;
+    this.right = right;
+  }
+
+  public Measure getTop() {
+    return top;
+  }
+
+  public void setTop(final Measure top) {
+    empty = null;
+    this.top = top;
+  }
+
+  public Measure getBottom() {
+    return bottom;
+  }
+
+  public void setBottom(Measure bottom) {
+    empty = null;
+    this.bottom = bottom;
+  }
+
+  public Display getDisplay() {
+    return display;
+  }
+
+  public void setDisplay(final Display display) {
+    empty = null;
+    this.display = display;
+  }
+
+  public Position getPosition() {
+    return position;
+  }
+
+  public void setPosition(final Position position) {
+    empty = null;
+    this.position = position;
+  }
+
+  public Overflow getOverflowX() {
+    return overflowX;
+  }
+
+  public void setOverflowX(final Overflow overflowX) {
+    empty = null;
+    this.overflowX = overflowX;
+  }
+
+  public Overflow getOverflowY() {
+    return overflowY;
+  }
+
+  public void setOverflowY(final Overflow overflowY) {
+    empty = null;
+    this.overflowY = overflowY;
+  }
+
+  public Measure getMarginLeft() {
+    return marginLeft;
+  }
+
+  public void setMarginLeft(final Measure marginLeft) {
+    empty = null;
+    this.marginLeft = marginLeft;
+  }
+
+  public Measure getMarginRight() {
+    return marginRight;
+  }
+
+  public void setMarginRight(final Measure marginRight) {
+    empty = null;
+    this.marginRight = marginRight;
+  }
+
+  public Measure getMarginTop() {
+    return marginTop;
+  }
+
+  public void setMarginTop(final Measure marginTop) {
+    empty = null;
+    this.marginTop = marginTop;
+  }
+
+  public Measure getMarginBottom() {
+    return marginBottom;
+  }
+
+  public void setMarginBottom(final Measure marginBottom) {
+    empty = null;
+    this.marginBottom = marginBottom;
+  }
+
+  public Measure getPaddingLeft() {
+    return paddingLeft;
+  }
+
+  public void setPaddingLeft(final Measure paddingLeft) {
+    empty = null;
+    this.paddingLeft = paddingLeft;
+  }
+
+  public Measure getPaddingRight() {
+    return paddingRight;
+  }
+
+  public void setPaddingRight(final Measure paddingRight) {
+    empty = null;
+    this.paddingRight = paddingRight;
+  }
+
+  public Measure getPaddingTop() {
+    return paddingTop;
+  }
+
+  public void setPaddingTop(final Measure paddingTop) {
+    empty = null;
+    this.paddingTop = paddingTop;
+  }
+
+  public Measure getPaddingBottom() {
+    return paddingBottom;
+  }
+
+  public void setPaddingBottom(final Measure paddingBottom) {
+    empty = null;
+    this.paddingBottom = paddingBottom;
+  }
+
+  public String getBackgroundImage() {
+    return backgroundImage;
+  }
+
+  public void setBackgroundImage(String backgroundImage) {
+    this.backgroundImage = backgroundImage;
+  }
+
+  public String getBackgroundPosition() {
+    return backgroundPosition;
+  }
+
+  public void setBackgroundPosition(String backgroundPosition) {
+    this.backgroundPosition = backgroundPosition;
+  }
+
+  public Integer getZIndex() {
+    return zIndex;
+  }
+
+  public void setZIndex(final Integer zIndex) {
+    empty = null;
+    this.zIndex = zIndex;
+  }
+
+  public TextAlign getTextAlign() {
+    return textAlign;
+  }
+
+  public void setTextAlign(final TextAlign textAlign) {
+    empty = null;
+    this.textAlign = textAlign;
+  }
+
+  @Override
+  public String toString() {
+    return encode();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
new file mode 100644
index 0000000..46b2c29
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/css/TobagoClass.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.myfaces.tobago.layout.AlignItems;
+import org.apache.myfaces.tobago.layout.JustifyContent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Declaration of the Tobago CSS classes.
+ *
+ * @since 3.0.0
+ */
+public enum TobagoClass implements CssItem {
+
+  // general classes
+
+  ALIGN_ITEMS__BASELINE("tobago-alignItems-baseline"),
+  ALIGN_ITEMS__CENTER("tobago-alignItems-center"),
+  ALIGN_ITEMS__FLEX_END("tobago-alignItems-flexEnd"),
+  ALIGN_ITEMS__FLEX_START("tobago-alignItems-flexStart"),
+  ALIGN_ITEMS__STRETCH("tobago-alignItems-stretch"),
+
+  JUSTIFY_CONTENT__CENTER("tobago-justifyContent-center"),
+  JUSTIFY_CONTENT__FLEX_START("tobago-justifyContent-flexStart"),
+  JUSTIFY_CONTENT__FLEX_END("tobago-justifyContent-flexEnd"),
+  JUSTIFY_CONTENT__SPACE_BETWEEN("tobago-justifyContent-spaceBetween"),
+  JUSTIFY_CONTENT__SPACE_AROUND("tobago-justifyContent-spaceAround"),
+
+  DROPDOWN__SUBMENU("tobago-dropdown-submenu"),
+  /** @deprecated Since 3.0.1. Please use {@link TobagoClass#DROPDOWN__SUBMENU} */
+  @Deprecated
+  DROPDOWN_SUBMENU(DROPDOWN__SUBMENU.getName()),
+  TABLE_LAYOUT__FIXED("tobago-tableLayout-fixed"),
+
+  HAS__INFO("tobago-has-info"),
+  /** @deprecated Since 3.0.1. Please use {@link TobagoClass#HAS__INFO} */
+  @Deprecated
+  HAS_INFO(HAS__INFO.getName()),
+  REQUIRED("tobago-required"),
+  SPREAD("tobago-spread"),
+
+  // component based classes
+
+  BOX__HEADER("tobago-box-header"),
+  COLLAPSED("tobago-collapsed"),
+  FLEX_LAYOUT("tobago-flexLayout"),
+  FIGURE("tobago-figure"),
+  FORM("tobago-form"),
+  INPUT__GROUP__OUTER("tobago-input-group-outer"),
+  /** @deprecated Since 3.0.1. Please use {@link TobagoClass#INPUT__GROUP__OUTER} */
+  @Deprecated
+  INPUT_GROUP_OUTER(INPUT__GROUP__OUTER.getName()),
+  LABEL("tobago-label"),
+  MESSAGES("tobago-messages"),
+  PAGE__MENU_STORE("tobago-page-menuStore"),
+  PANEL("tobago-panel"),
+  POPUP("tobago-popup"),
+  SECTION__HEADER("tobago-section-header"),
+  SECTION__CONTENT("tobago-section-content"),
+  SELECT_MANY_CHECKBOX__INLINE("tobago-selectManyCheckbox-inline"),
+  SELECT_ONE_RADIO__INLINE("tobago-selectOneRadio-inline"),
+  SHEET__HEADER("tobago-sheet-header"),
+  SHEET__BODY_TABLE("tobago-sheet-bodyTable"),
+  SHEET__HEADER_TABLE("tobago-sheet-headerTable"),
+  SHEET__PAGING_INPUT("tobago-sheet-pagingInput"),
+  SHEET__PAGING_OUTPUT("tobago-sheet-pagingOutput"),
+  SHEET__CELL__MARKUP__RIGHT("tobago-sheet-cell-markup-right"),
+  SHEET__CELL__MARKUP__CENTER("tobago-sheet-cell-markup-center"),
+  SHEET__CELL__MARKUP__JUSTIFY("tobago-sheet-cell-markup-justify"),
+  SUGGEST("tobago-suggest");
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoClass.class);
+
+  private final String name;
+
+  TobagoClass(final String name) {
+    this.name = name;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  public static TobagoClass valueOf(AlignItems alignItems) {
+    if (alignItems == null) {
+      return null;
+    } else {
+      switch (alignItems) {
+        case baseline:
+          return ALIGN_ITEMS__BASELINE;
+        case center:
+          return ALIGN_ITEMS__CENTER;
+        case flexEnd:
+          return ALIGN_ITEMS__FLEX_END;
+        case flexStart:
+          return ALIGN_ITEMS__FLEX_START;
+        case stretch:
+          return ALIGN_ITEMS__STRETCH;
+        default:
+          LOG.warn("Undefined alignItems: '{}'.", alignItems);
+          return null;
+      }
+    }
+  }
+
+  public static TobagoClass valueOf(JustifyContent justifyContent) {
+    if (justifyContent == null) {
+      return null;
+    } else {
+      switch (justifyContent) {
+        case center:
+          return JUSTIFY_CONTENT__CENTER;
+        case flexEnd:
+          return JUSTIFY_CONTENT__FLEX_END;
+        case flexStart:
+          return JUSTIFY_CONTENT__FLEX_START;
+        case spaceBetween:
+          return JUSTIFY_CONTENT__SPACE_BETWEEN;
+        case spaceAround:
+          return JUSTIFY_CONTENT__SPACE_AROUND;
+        default:
+          LOG.warn("Undefined justifyContent: '{}'.", justifyContent);
+          return null;
+      }
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/Arias.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/Arias.java
new file mode 100644
index 0000000..95d2565
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/Arias.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+public enum Arias implements MarkupLanguageAttributes {
+
+  ACTIVEDESCENDANT("aria-activedescendant"),
+  ATOMIC("aria-atomic"),
+  BUSY("aria-busy"),
+  CONTROLS("aria-controls"),
+  DESCRIBEDBY("aria-describedby"),
+  DROPEFFECT("aria-dropeffect"),
+  EXPANDED("aria-expanded"),
+  FLOWTO("aria-flowto"),
+  GRABBED("aria-grabbed"),
+  HASPOPUP("aria-haspopup"),
+  HIDDEN("aria-hidden"),
+  LABEL("aria-label"),
+  LABELLEDBY("aria-labelledby"),
+  LEVEL("aria-level"),
+  LIVE("aria-live"),
+  ORIENTATION("aria-orientation"),
+  OWNS("aria-owns"),
+  POSINSET("aria-posinset"),
+  PRESSED("aria-pressed"),
+  RELEVANT("aria-relevant"),
+  SETSIZE("aria-setsize"),
+  SORT("aria-sort");
+
+  private final String value;
+
+  Arias(final String value) {
+    this.value = value;
+  }
+
+  @Override
+  public String getValue() {
+    return value;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/DataAttributes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/DataAttributes.java
new file mode 100644
index 0000000..283be9b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/DataAttributes.java
@@ -0,0 +1,224 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+/**
+ * Custom data attributes.
+ * These attributes may transport data to DOM which are not standardized.
+ * The format is "data-tobago-*" which is conform to HTML 5, but also works in older browsers.
+ */
+public enum DataAttributes implements MarkupLanguageAttributes {
+
+  /**
+   * Ajax behaviors execute and render attributes for TabGroup and Sheet reload
+   * @deprecated please use COMMANDS
+   */
+  BEHAVIOR_COMMANDS("data-tobago-behavior-commands"),
+
+  /**
+   * The index of the column of a sheet. This index means the position of the rendered column. It can differ, if there
+   * are tc:column with rendered=false.
+   */
+  COLUMN_INDEX("data-tobago-column-index"),
+
+  /**
+   * Custom command attribute. Is used to mark different client side JavaScript buttons.
+   * Should only contain the command name as a keyword, for security reasons.
+   */
+  COMMAND("data-tobago-command"),
+
+  /**
+   * The list of commands attached to an element.
+   */
+  COMMANDS("data-tobago-commands"),
+
+  /**
+   * The context path of the application, may be needed in the Client.
+   */
+  CONTEXT_PATH("data-tobago-context-path"),
+
+  DATE_TIME_I18N("data-tobago-date-time-i18n"),
+
+  /**
+   * Holds the day of a calendar control.
+   */
+  DAY("data-tobago-day"),
+
+  /**
+   * Custom disabled attribute. Use for element, that don't have the disabled attribute.
+   */
+  DISABLED("data-tobago-disabled"),
+
+  DISMISS("data-dismiss"),
+
+  /**
+   * Custom form attribute. Used to show the virtual form of the component.
+   */
+  DEFAULT("data-tobago-default"),
+
+  DELAY("data-tobago-delay"),
+
+  FOR("data-tobago-for"),
+
+  /**
+   * Holds the id of the first row in a sheet.
+   */
+  FIRST("data-tobago-first"),
+
+  /*
+   * Holds the index of the row in a sheet, if the sheed has a rowRendered attribute.
+   */
+  ROW_INDEX("data-tobago-row-index"),
+
+  /**
+   * Holds the first day of a week of a calendar control.
+   */
+  FIRST_DAY_OF_WEEK("data-tobago-first-day-of-week"),
+
+  /**
+   * Defines a maximum value.
+   */
+  LAYOUT("data-tobago-layout"),
+
+  /**
+   * Defines a maximum value.
+   */
+  MAX("data-tobago-max"),
+
+  /**
+   * Holds the month of a calendar control.
+   */
+  MONTH("data-tobago-month"),
+
+  /**
+   * Holds the names of the months of a calendar control.
+   */
+  MONTH_NAMES("data-tobago-month-names"),
+
+  PARTIAL_IDS("data-tobago-partial-ids"),
+
+  PARTIAL_ACTION("data-tobago-partial-action"),
+
+  /**
+   * Custom attribute to describe a pattern, e. g. for an date input field.
+   */
+  PATTERN("data-tobago-pattern"),
+
+  /**
+   * Custom reload attribute. Used to reload a panel.
+   */
+  RELOAD("data-tobago-reload"),
+
+  ROW_ACTION("data-tobago-row-action"),
+
+  SELECTION_MODE("data-tobago-selection-mode"),
+
+  /**
+   * The selectable attribute e. g. for trees.
+   */
+  SELECTABLE("data-tobago-selectable"),
+
+  /**
+   * Reference to a sheet.
+   */
+  SHEET_ID("data-tobago-sheet-id"),
+
+  /**
+   * Alternate to the src attribute, icon open and close.
+   */
+  SRC_CLOSED("data-tobago-src-closed"),
+
+  /**
+   * Alternate to the src attribute, icon open and close.
+   */
+  SRC_OPEN("data-tobago-src-open"),
+
+  /**
+   * A way to transport style data in JSON format to the browser. With CSP the normal style attribute isn't allowed.
+   */
+  STYLE("data-tobago-style"),
+
+  SCROLL_PANEL("data-tobago-scroll-panel"),
+
+  SCROLL_POSITION("data-tobago-scroll-position"),
+
+  SUGGEST_DATA("data-tobago-suggest-data"),
+
+  SUGGEST_DELAY("data-tobago-suggest-delay"),
+
+  SUGGEST_FOR("data-tobago-suggest-for"),
+
+  SUGGEST_MAX_ITEMS("data-tobago-suggest-max-items"),
+
+  SUGGEST_MIN_CHARS("data-tobago-suggest-min-chars"),
+
+  SUGGEST_TOTAL_COUNT("data-tobago-suggest-total-count"),
+
+  SUGGEST_UPDATE("data-tobago-suggest-update"),
+
+  TARGET("data-target"),
+
+  TO_PAGE("data-tobago-to-page"),
+
+  TOGGLE("data-toggle"),
+
+  TRANSITION("data-tobago-transition"),
+
+  /**
+   * Id of the parent node in a tree node.
+   */
+  TREE_PARENT("data-tobago-tree-parent"),
+
+  /**
+   * Defines the unit, e. g. to differ between hours, minutes and seconds in a time control.
+   */
+  UNIT("data-tobago-unit"),
+
+  /**
+   * Holds the value (for tags, that don't have a value in HTML).
+   */
+  VALUE("data-tobago-value"),
+
+  /**
+   * Holds the year of a calendar control.
+   */
+  YEAR("data-tobago-year");
+
+  private final String value;
+
+  DataAttributes(String value) {
+    this.value = value;
+  }
+
+  @Override
+  public String getValue() {
+    return value;
+  }
+
+  public static MarkupLanguageAttributes dynamic(final String withoutPrefix) {
+    return new MarkupLanguageAttributes() {
+      @Override
+      public String getValue() {
+        return "data-" + withoutPrefix;
+      }
+    };
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlAttributes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlAttributes.java
new file mode 100644
index 0000000..830a720
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlAttributes.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+public enum HtmlAttributes implements MarkupLanguageAttributes {
+
+  ACCEPT_CHARSET("accept-charset"),
+  ACCEPT("accept"),
+  ACCESSKEY("accesskey"),
+  ACTION("action"),
+  ALIGN("align"),
+  ALT("alt"),
+  AUTOCOMPLETE("autocomplete"),
+  AUTOFOCUS("autofocus"),
+  BORDER("border"),
+  CELLPADDING("cellpadding"),
+  CELLSPACING("cellspacing"),
+  CHECKED("checked"),
+  CLASS("class"),
+  COLSPAN("colspan"),
+  CONTENT("content"),
+  DEFER("defer"),
+  DISABLED("disabled"),
+  ENCTYPE("enctype"),
+  FOR("for"),
+  FRAMEBORDER("frameborder"),
+  HEIGHT("height"),
+  HREF("href"),
+  HTTP_EQUIV("http-equiv"),
+  ID("id"),
+  LABEL("label"),
+  LANG("lang"),
+  MAX("max"),
+  MAXLENGTH("maxlength"),
+  MEDIA("media"),
+  METHOD("method"),
+  MULTIPLE("multiple"),
+  NAME("name"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONBLUR("onblur"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONCHANGE("onchange"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONCLICK("onclick"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONDBLCLICK("ondblclick"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONFOCUS("onfocus"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONFOCUSIN("onfocusin"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONKEYDOWN("onkeydown"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONKEYPRESS("onkeypress"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONKEYUP("onkeyup"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONLOAD("onload"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONMOUSEOVER("onmouseover"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  ONMOUSEOUT("onmouseout"),
+  PATTERN("pattern"),
+  PLACEHOLDER("placeholder"),
+  READONLY("readonly"),
+  REL("rel"),
+  REQUIRED("required"),
+  ROLE("role"),
+  ROWS("rows"),
+  ROWSPAN("rowspan"),
+  SCROLL("scroll"),
+  SELECTED("selected"),
+  SIZE("size"),
+  SRC("src"),
+  /** @deprecated Since 2.0.0. This attribute work not with SCP */
+  @Deprecated
+  STYLE("style"),
+  SUMMARY("summary"),
+  TABINDEX("tabindex"),
+  TARGET("target"),
+  TITLE("title"),
+  TYPE("type"),
+  VALIGN("valign"),
+  VALUE("value"),
+  WIDTH("width"),
+  XMLNS("xmlns"),
+
+  // Non standard attributes ///////////////////////////////////////////////////////////
+
+  /**
+   * The index of the tab inside the tab group.
+   */
+  TABGROUPINDEX("tabgroupindex"),
+  /**
+   * The mode of the tab switch: client, reloadTab, reloadPage.
+   */
+  SWITCHTYPE("switchtype");
+
+
+  private final String value;
+
+  HtmlAttributes(String value) {
+    this.value = value;
+  }
+
+  @Override
+  public String getValue() {
+    return value;
+  }
+
+}
+
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlButtonTypes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlButtonTypes.java
new file mode 100644
index 0000000..992ec1a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlButtonTypes.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+public enum HtmlButtonTypes implements HtmlTypes {
+
+  BUTTON("button"),
+  RESET("reset"),
+  SUBMIT("submit");
+
+  private final String value;
+
+  HtmlButtonTypes(String value) {
+    this.value = value;
+  }
+
+  @Override
+  public String getValue() {
+    return value;
+  }
+  }
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
new file mode 100644
index 0000000..bf5ee12
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlElements.java
@@ -0,0 +1,186 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+public enum HtmlElements {
+
+  A("a", Qualifier.INLINE),
+  ABBR("abbr", Qualifier.INLINE),
+  ADDRESS("address"),
+  AREA("area", Qualifier.VOID),
+  ARTICLE("article"),
+  ASIDE("aside"),
+  AUDIO("audio"),
+  B("b", Qualifier.INLINE),
+  BASE("base", Qualifier.VOID),
+  BDI("bdi"),
+  BDO("bdo"),
+  BLOCKQUOTE("blockquote"),
+  BODY("body"),
+  BR("br", Qualifier.VOID),
+  BUTTON("button", Qualifier.INLINE),
+  CANVAS("canvas"),
+  CAPTION("caption"),
+  CITE("cite", Qualifier.INLINE),
+  CODE("code", Qualifier.INLINE),
+  COL("col", Qualifier.VOID),
+  COLGROUP("colgroup"),
+  COMMAND("command", Qualifier.VOID),
+  DATALIST("datalist"),
+  DD("dd"),
+  DEL("del"),
+  DETAILS("details"),
+  DFN("dfn"),
+  DIV("div"),
+  DL("dl"),
+  DT("dt"),
+  EM("em", Qualifier.INLINE),
+  EMBED("embed", Qualifier.VOID),
+  FIELDSET("fieldset"),
+  FIGCAPTION("figcaption"),
+  FIGURE("figure"),
+  FOOTER("footer"),
+  FORM("form"),
+  H1("h1"),
+  H2("h2"),
+  H3("h3"),
+  H4("h4"),
+  H5("h5"),
+  H6("h6"),
+  HEAD("head"),
+  HEADER("header"),
+  HGROUP("hgroup"),
+  HR("hr", Qualifier.VOID),
+  HTML("html"),
+  I("i", Qualifier.INLINE),
+  IFRAME("iframe"),
+  IMG("img", Qualifier.VOID, Qualifier.INLINE),
+  INPUT("input", Qualifier.VOID, Qualifier.INLINE),
+  INS("ins"),
+  KBD("kbd"),
+  KEYGEN("keygen", Qualifier.VOID),
+  LABEL("label", Qualifier.INLINE),
+  LEGEND("legend"),
+  LI("li"),
+  LINK("link", Qualifier.VOID),
+  MAP("map"),
+  MARK("mark"),
+  MENU("menu"),
+  META("meta", Qualifier.VOID),
+  METER("meter"),
+  NAV("nav"),
+  NOSCRIPT("noscript"),
+  OBJECT("object"),
+  OL("ol"),
+  OPTGROUP("optgroup"),
+  OPTION("option"),
+  P("p"),
+  PARAM("param", Qualifier.VOID),
+  PRE("pre", Qualifier.INLINE),
+  PROGRESS("progress"),
+  Q("q"),
+  RP("rp"),
+  RT("rt"),
+  RUBY("ruby"),
+  S("s"),
+  SAMP("samp"),
+  SCRIPT("script", Qualifier.INLINE),
+  SECTION("section"),
+  SELECT("select", Qualifier.INLINE),
+  SMALL("small"),
+  SOURCE("source", Qualifier.VOID),
+  SPAN("span", Qualifier.INLINE),
+  STRONG("strong"),
+  STYLE("style"),
+  SUB("sub", Qualifier.INLINE),
+  SUMMARY("summary"),
+  SUP("sup", Qualifier.INLINE),
+  TABLE("table"),
+  TBODY("tbody"),
+  TD("td"),
+  TEXTAREA("textarea", Qualifier.INLINE),
+  TFOOT("tfoot"),
+  TH("th"),
+  THEAD("thead"),
+  TIME("time"),
+  TITLE("title"),
+  TR("tr"),
+  TRACK("track", Qualifier.VOID),
+  U("u", Qualifier.INLINE),
+  UL("ul"),
+  VAR("var"),
+  VIDEO("video"),
+  WBR("wbr", Qualifier.VOID);
+
+  private final String value;
+  private final boolean voidElement;
+  private final boolean inlineElement;
+
+  private static final Set<String> VOIDS = new HashSet<String>();
+  private static final Set<String> INLINES = new HashSet<String>();
+
+  HtmlElements(final String value, final Qualifier... qualifiers) {
+    this.value = value;
+    this.voidElement = Arrays.asList(qualifiers).contains(Qualifier.VOID);
+    this.inlineElement = Arrays.asList(qualifiers).contains(Qualifier.INLINE);
+  }
+
+  static {
+    for (final HtmlElements htmlElement : values()) {
+      if (htmlElement.isVoid()) {
+        VOIDS.add(htmlElement.getValue());
+      }
+      if (htmlElement.isInline()) {
+        INLINES.add(htmlElement.getValue());
+      }
+    }
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  /**
+   * A void HTML elements is an element whose content model never allows it to have contents under any circumstances.
+   * See <a href="http://www.w3.org/TR/html-markup/syntax.html#void-element">
+   * http://www.w3.org/TR/html-markup/syntax.html#void-element</a>
+   */
+  public boolean isVoid() {
+    return voidElement;
+  }
+
+  public boolean isInline() {
+    return inlineElement;
+  }
+
+  public static boolean isVoid(final String name) {
+    return VOIDS.contains(name);
+  }
+
+  public static boolean isInline(final String name) {
+    return INLINES.contains(name);
+  }
+
+  private enum Qualifier {VOID, INLINE}
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlInputTypes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlInputTypes.java
new file mode 100644
index 0000000..2af1b28
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlInputTypes.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+public enum HtmlInputTypes implements HtmlTypes {
+
+  TEXT("text"),
+  PASSWORD("password"),
+  CHECKBOX("checkbox"),
+  RADIO("radio"),
+  SUBMIT("submit"),
+  RESET("reset"),
+  FILE("file"),
+  HIDDEN("hidden"),
+  IMAGE("image"),
+  BUTTON("button");
+
+  private final String value;
+
+  HtmlInputTypes(String value) {
+    this.value = value;
+  }
+
+  @Override
+  public String getValue() {
+    return value;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlRoleValues.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlRoleValues.java
new file mode 100644
index 0000000..ff0cb6b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlRoleValues.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+public enum HtmlRoleValues {
+
+  ALERT("alert"),
+  DIALOG("dialog"),
+  DOCUMENT("document"),
+  GROUP("group"),
+  MENU("menu"),
+  NAVIGATION("navigation"),
+  PRESENTATION("presentation"),
+  TAB("tab"),
+  TABLIST("tablist"),
+  TABPANEL("tabpanel");
+
+  private String value;
+
+  HtmlRoleValues(final String value) {
+    this.value = value;
+  }
+
+  public String toString() {
+    return value;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlTypes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlTypes.java
new file mode 100644
index 0000000..af9abac
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/HtmlTypes.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+public interface HtmlTypes {
+
+  String getValue();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/MarkupLanguageAttributes.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/MarkupLanguageAttributes.java
new file mode 100644
index 0000000..0f3962c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/renderkit/html/MarkupLanguageAttributes.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+public interface MarkupLanguageAttributes {
+
+  String getValue();
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/IgnoringSanitizer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/IgnoringSanitizer.java
new file mode 100644
index 0000000..ff9a9e1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/IgnoringSanitizer.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.sanitizer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Properties;
+
+/**
+ * The IgnoringSanitizer doesn't protect you against malicious code. Use it with care, or better not use it.
+ */
+public class IgnoringSanitizer implements Sanitizer {
+
+  private static final Logger LOG = LoggerFactory.getLogger(IgnoringSanitizer.class);
+
+  @Override
+  public String sanitize(String html) {
+    return html;
+  }
+
+  @Override
+  public void setProperties(Properties configuration) {
+    LOG.warn("No configuration needed! Got: '{}'", configuration);
+  }
+
+  @Override
+  public String toString() {
+    return getClass().getSimpleName();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/JsoupSanitizer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/JsoupSanitizer.java
new file mode 100644
index 0000000..a57fada
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/JsoupSanitizer.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.sanitizer;
+
+import org.jsoup.Jsoup;
+import org.jsoup.safety.Whitelist;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Properties;
+
+/**
+ * The JsoupSanitizer uses the jsoup library http://jsoup.org/ to check against malicious code.
+ */
+public class JsoupSanitizer implements Sanitizer {
+
+  private static final Logger LOG = LoggerFactory.getLogger(JsoupSanitizer.class);
+
+  private Whitelist whitelist;
+  private String whitelistName;
+
+  private boolean unmodifiable = false;
+
+  @Override
+  public String sanitize(final String html) {
+
+    final String safe = Jsoup.clean(html, whitelist);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Sanitized: " + safe);
+    }
+    return safe;
+  }
+
+  @Override
+  public void setProperties(final Properties configuration) {
+    checkLocked();
+
+    unmodifiable = true;
+
+    for (final String key : configuration.stringPropertyNames()) {
+      if ("whitelist".equals(key)) {
+        whitelistName = configuration.getProperty(key);
+        if ("basic".equals(whitelistName)) {
+          whitelist = Whitelist.basic();
+        } else if ("basicWithImages".equals(whitelistName)) {
+          whitelist = Whitelist.basicWithImages();
+        } else if ("none".equals(whitelistName)) {
+          whitelist = Whitelist.none();
+        } else if ("relaxed".equals(whitelistName)) {
+          whitelist = Whitelist.relaxed();
+        } else if ("simpleText".equals(whitelistName)) {
+          whitelist = Whitelist.simpleText();
+        } else {
+          throw new RuntimeException(
+              "Unknown configuration value for 'whitelist' in tobago-config.xml found! value='" + whitelistName + "'");
+        }
+      } else {
+        throw new RuntimeException("Unknown configuration key in tobago-config.xml found! key='" + key + "'");
+      }
+    }
+
+    if (LOG.isInfoEnabled()) {
+      LOG.warn("Using whitelist '" + whitelistName + "' for sanitizing!");
+    }
+  }
+
+  private void checkLocked() throws IllegalStateException {
+    if (unmodifiable) {
+      throw new RuntimeException("The configuration must not be changed after initialization!");
+    }
+  }
+
+  @Override
+  public String toString() {
+    return getClass().getSimpleName() + " whitelist='" + whitelistName + "'";
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/SanitizeMode.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/SanitizeMode.java
new file mode 100644
index 0000000..cfd1ba9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/SanitizeMode.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.sanitizer;
+
+public enum SanitizeMode {
+  auto,
+  never;
+
+  public static final String AUTO = "auto";
+  public static final String NEVER = "never";
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/Sanitizer.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/Sanitizer.java
new file mode 100644
index 0000000..14bc019
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/sanitizer/Sanitizer.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.sanitizer;
+
+import java.util.Properties;
+
+public interface Sanitizer {
+
+  String sanitize(String html);
+
+  void setProperties(Properties configuration);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/servlet/NonFacesRequestServlet.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/servlet/NonFacesRequestServlet.java
new file mode 100644
index 0000000..6c7b40c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/servlet/NonFacesRequestServlet.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.servlet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.FactoryFinder;
+import javax.faces.application.Application;
+import javax.faces.application.NavigationHandler;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.context.FacesContextFactory;
+import javax.faces.lifecycle.Lifecycle;
+import javax.faces.lifecycle.LifecycleFactory;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * @deprecated since Tobago 2.0.8 - Please use &lt;f:initParam&gt; instead - see also TOBAGO-1456
+ */
+@Deprecated
+public abstract class NonFacesRequestServlet extends HttpServlet {
+
+  private static final long serialVersionUID = -7448621953821447997L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(NonFacesRequestServlet.class);
+
+  @Override
+  protected void service(final HttpServletRequest request, final HttpServletResponse response)
+      throws ServletException, IOException {
+
+    final LifecycleFactory lFactory = (LifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
+    final Lifecycle lifecycle = lFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
+    final FacesContextFactory fcFactory
+        = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
+    final FacesContext facesContext = fcFactory.getFacesContext(getServletContext(), request, response, lifecycle);
+    try {
+
+      // invoke application
+      final String outcome = invokeApplication(facesContext);
+
+      if (facesContext.getResponseComplete()) {
+        return;
+      }
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("outcome = '" + outcome + "'");
+      }
+
+      final Application application = facesContext.getApplication();
+      if (facesContext.getViewRoot() == null) {
+        facesContext.setViewRoot(createViewRoot(facesContext));
+      }
+
+      final NavigationHandler navigationHandler = application.getNavigationHandler();
+      navigationHandler.handleNavigation(facesContext, null, outcome);
+
+
+      lifecycle.render(facesContext);
+    } finally {
+      facesContext.release();
+    }
+  }
+
+  protected UIViewRoot createViewRoot(final FacesContext facesContext) {
+    return facesContext.getApplication().getViewHandler().createView(facesContext, getFromViewId());
+  }
+
+  public abstract String invokeApplication(FacesContext facesContext);
+
+  /**
+   * will be called to initialize the first ViewRoot,
+   * may be overwritten by extended classes
+   */
+  public String getFromViewId() {
+    return "";
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/servlet/ResourceServlet.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/servlet/ResourceServlet.java
new file mode 100644
index 0000000..15b0549
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/servlet/ResourceServlet.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.servlet;
+
+import org.apache.myfaces.tobago.application.ProjectStage;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.internal.util.IoUtils;
+import org.apache.myfaces.tobago.internal.util.MimeTypeUtils;
+import org.apache.myfaces.tobago.internal.util.ResponseUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * <pre>
+ * &lt;servlet&gt;
+ *   &lt;servlet-name&gt;ResourceServlet&lt;/servlet-name&gt;
+ *   &lt;servlet-class&gt;org.apache.myfaces.tobago.servlet.ResourceServlet&lt;/servlet-class&gt;
+ *   &lt;init-param&gt;
+ *     &lt;description&gt;The value for the expires header in seconds.
+ *       The default for ProjectStage.Production is 86400 sec (24 h) otherwise no expires header.&lt;/description&gt;
+ *     &lt;param-name&gt;expires&lt;/param-name&gt;
+ *     &lt;param-value&gt;14400&lt;/param-value&gt;
+ *   &lt;/init-param&gt;
+ *   &lt;init-param&gt;
+ *     &lt;description&gt;The value for the copy buffer size.
+ *            Default is 4096.&lt;/description&gt;
+ *     &lt;param-name&gt;bufferSize&lt;/param-name&gt;
+ *     &lt;param-value&gt;4096&lt;/param-value&gt;
+ *   &lt;/init-param&gt;
+ * &lt;/servlet&gt;
+ * &lt;servlet-mapping&gt;
+ *   &lt;servlet-name&gt;ResourceServlet&lt;/servlet-name&gt;
+ *   &lt;url-pattern&gt;/org/apache/myfaces/tobago/renderkit/*&lt;/url-pattern&gt;
+ * &lt;/servlet-mapping&gt;
+ * </pre>
+ *
+ * @since 1.0.7
+ * @deprecated since Tobago 3.0.x this is no longer needed
+ */
+@Deprecated
+public class ResourceServlet extends HttpServlet {
+
+  private static final long serialVersionUID = -4491419290205206466L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(ResourceServlet.class);
+
+  private Long expires;
+  private int bufferSize;
+  private boolean nosniffHeader;
+
+  @Override
+  public void init(final ServletConfig servletConfig) throws ServletException {
+    super.init(servletConfig);
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(servletConfig.getServletContext());
+    if (tobagoConfig.getProjectStage() == ProjectStage.Production) {
+       expires = 24 * 60 * 60 * 1000L;
+    }
+
+    final String expiresString = servletConfig.getInitParameter("expires");
+    if (expiresString != null) {
+      try {
+        expires = new Long(expiresString) * 1000;
+      } catch (final NumberFormatException e) {
+        LOG.error("Caught: " + e.getMessage(), e);
+      }
+    }
+    final String bufferSizeString = servletConfig.getInitParameter("bufferSize");
+    bufferSize = 1024 * 4;
+    if (bufferSizeString != null) {
+      try {
+        bufferSize = Integer.parseInt(bufferSizeString);
+      } catch (final NumberFormatException e) {
+        LOG.error("Caught: " + e.getMessage(), e);
+      }
+    }
+    nosniffHeader = tobagoConfig.isSetNosniffHeader();
+  }
+
+    @Override
+  protected void doGet(
+      final HttpServletRequest request, final HttpServletResponse response)
+      throws ServletException, IOException {
+
+    final String requestURI = request.getRequestURI();
+    String resource = requestURI.substring(request.getContextPath().length() + 1);
+    if (expires != null) {
+      response.setDateHeader("Last-Modified", 0);
+      response.setHeader("Cache-Control", "Public, max-age=" + expires);
+      response.setDateHeader("Expires", System.currentTimeMillis() + expires);
+    }
+    final String contentType = MimeTypeUtils.getMimeTypeForFile(requestURI);
+    if (contentType != null) {
+      response.setContentType(contentType);
+      if (nosniffHeader) {
+        ResponseUtils.ensureNosniffHeader(response);
+      }
+    } else {
+      final String message = "Unsupported mime type of resource='" + resource + "'";
+      LOG.warn(message + " (because of security reasons)");
+      response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+      return;
+    }
+
+    InputStream inputStream = null;
+    try {
+      final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+      // meta inf (like in servlet 3.0)
+      inputStream = classLoader.getResourceAsStream("META-INF/resources/" + resource);
+
+      // "normal" classpath
+      if (inputStream == null) {
+        inputStream = classLoader.getResourceAsStream(resource);
+      }
+
+      if (inputStream != null) {
+        copy(inputStream, response.getOutputStream());
+      } else {
+        final String message = "Resource '" + resource + "' not found!";
+        LOG.warn(message);
+        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
+      }
+    } finally {
+      IoUtils.closeQuietly(inputStream);
+    }
+  }
+
+  @Override
+  protected long getLastModified(final HttpServletRequest request) {
+    if (expires != null) {
+      return 0;
+    } else {
+      return super.getLastModified(request);
+    }
+  }
+
+  private void copy(final InputStream inputStream, final OutputStream outputStream) throws IOException {
+    final byte[] buffer = new byte[bufferSize];
+    int count;
+    while (-1 != (count = inputStream.read(buffer))) {
+      outputStream.write(buffer, 0, count);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/AjaxUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/AjaxUtils.java
new file mode 100644
index 0000000..de2aa91
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/AjaxUtils.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import javax.faces.application.Application;
+import javax.faces.application.NavigationHandler;
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class AjaxUtils {
+
+  public static boolean isAjaxRequest(final FacesContext facesContext) {
+    return facesContext.getPartialViewContext().isAjaxRequest();
+  }
+
+  public static boolean isAjaxRequest(final ServletRequest request) {
+    String requestType = null;
+    if (request instanceof HttpServletRequest) {
+      final HttpServletRequest httpServletRequest = (HttpServletRequest) request;
+      requestType = httpServletRequest.getHeader("Faces-Request");
+    }
+    return "partial/ajax".equalsIgnoreCase(requestType)
+        || "true".equalsIgnoreCase(request.getParameter("javax.faces.partial.ajax"));
+  }
+
+  public static void addRenderIds(final String... renderIds) {
+    addRenderIds(FacesContext.getCurrentInstance(), renderIds);
+  }
+
+  public static void addRenderIds(final FacesContext facesContext, final String... renderIds) {
+    Collections.addAll(facesContext.getPartialViewContext().getRenderIds(), renderIds);
+  }
+
+  public static void removeRenderIds(final String... renderIds) {
+    removeRenderIds(FacesContext.getCurrentInstance(), renderIds);
+  }
+
+  public static void removeRenderIds(final FacesContext facesContext, final String... renderIds) {
+    final Collection<String> collection = facesContext.getPartialViewContext().getRenderIds();
+    for (String renderId : renderIds) {
+      collection.remove(renderId);
+    }
+  }
+
+  public static Set<String> getRenderIds(final FacesContext facesContext) {
+    return new HashSet<String>(facesContext.getPartialViewContext().getRenderIds());
+  }
+
+  public static void navigate(FacesContext facesContext, Object outcome) {
+    final Application application = facesContext.getApplication();
+    NavigationHandler navigationHandler = application.getNavigationHandler();
+    navigationHandler.handleNavigation(facesContext, null, outcome.toString());
+    facesContext.renderResponse();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/BeanComparator.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/BeanComparator.java
new file mode 100644
index 0000000..a9231e6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/BeanComparator.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Comparator;
+import java.io.Serializable;
+
+public class BeanComparator extends ComparatorBase implements Serializable {
+
+  private static final long serialVersionUID = -7450094725566090886L;
+
+  private static final Logger LOG = LoggerFactory.getLogger(BeanComparator.class);
+
+  private String property;
+
+  public BeanComparator(final String property) {
+    this.property = property;
+  }
+
+  public BeanComparator(final String property, final boolean reverse) {
+    super(reverse);
+    this.property = property;
+  }
+
+  public BeanComparator(final String property, final Comparator comparator) {
+    super(comparator);
+    this.property = property;
+  }
+
+  public BeanComparator(final String property, final Comparator comparator, final boolean reverse) {
+    super(reverse, comparator);
+    this.property = property;
+  }
+
+  public boolean equals(final Object param1) {
+    if (this == param1) {
+      return true;
+    }
+    if (param1 instanceof BeanComparator) {
+      return ((BeanComparator) param1).getProperty().equals(property)
+          && super.equals(param1);
+    }
+    return false;
+  }
+
+  public int hashCode() {
+    int result;
+    result = (property != null ? property.hashCode() : 0);
+    result = 29 * result + super.hashCode();
+    return result;
+  }
+
+  // implementation of java.util.Comparator interface
+
+  @Override
+  public int compare(final Object param1, final Object param2) {
+    final Object obj1;
+    final Object obj2;
+    try {
+      obj1 = PropertyUtils.getProperty(param1, property);
+      obj2 = PropertyUtils.getProperty(param2, property);
+
+    } catch (final Exception e) {
+      LOG.error(e.getMessage(), e);
+      return 0;
+    }
+
+    return internalCompare(obj1, obj2);
+  }
+
+  public String getProperty() {
+    return this.property;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComparatorBase.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComparatorBase.java
new file mode 100644
index 0000000..451d4c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComparatorBase.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import java.text.CollationKey;
+import java.text.Collator;
+import java.util.Comparator;
+
+
+public abstract class ComparatorBase implements Comparator {
+
+  private Comparator comparator;
+
+  private boolean reverse;
+
+  protected ComparatorBase() {
+  }
+
+  protected ComparatorBase(final boolean reverse, final Comparator comparator) {
+    this.comparator = comparator;
+    this.reverse = reverse;
+  }
+
+  protected ComparatorBase(final boolean reverse) {
+    this.reverse = reverse;
+  }
+
+  protected ComparatorBase(final Comparator comparator) {
+    this.comparator = comparator;
+  }
+
+  protected int internalCompare(final Object obj1, final Object obj2) {
+
+    if (obj1 == null || obj2 == null) {
+      if (obj1 == null && obj2 == null) {
+        return 0;
+      }
+      if (obj1 == null) {
+        return reverse ? 1 : -1;
+      } else {
+        return reverse ? -1 : 1;
+      }
+    }
+
+    if (!obj1.getClass().isInstance(obj2)) {
+      throw new ClassCastException(obj1.getClass().getName() + " != "
+          + obj2.getClass().getName());
+    }
+
+    final int result;
+
+
+    if (comparator instanceof Collator) {
+      final CollationKey collationKey1
+          = ((Collator) comparator).getCollationKey(obj1.toString());
+      final CollationKey collationKey2
+          = ((Collator) comparator).getCollationKey(obj2.toString());
+      result = collationKey1.compareTo(collationKey2);
+
+    } else if (comparator != null) {
+      result = comparator.compare(obj1, obj2);
+    } else {
+      if (obj1 instanceof String) {
+        result = ((String) obj1).compareToIgnoreCase((String) obj2);
+      } else if (obj1 instanceof Comparable) {
+        result = ((Comparable) obj1).compareTo(obj2);
+      } else {
+        result = obj1.toString().compareTo(obj2.toString());
+      }
+    }
+    return reverse ? -result : result;
+  }
+
+  /*
+
+  // TODO use this??
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final ComparatorBase that = (ComparatorBase) o;
+
+    return !(comparator != null ? !comparator.equals(that.comparator) : that.comparator != null);
+
+  }
+
+  public int hashCode() {
+    return (comparator != null ? comparator.hashCode() : 0);
+  } */
+
+  public boolean equals(final Object o) {
+    if (o == null) {
+      return false;
+    }
+    return ((ComparatorBase) o).getComparator().equals(comparator);
+  }
+
+  public int hashCode() {
+    return (comparator != null ? comparator.hashCode() : 0);
+  }
+
+  public Comparator getComparator() {
+    return comparator;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java
new file mode 100644
index 0000000..003bc0f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ComponentUtils.java
@@ -0,0 +1,859 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.Facets;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.context.TransientStateHolder;
+import org.apache.myfaces.tobago.internal.component.AbstractUIForm;
+import org.apache.myfaces.tobago.internal.component.AbstractUIFormBase;
+import org.apache.myfaces.tobago.internal.component.AbstractUIInput;
+import org.apache.myfaces.tobago.internal.component.AbstractUIPage;
+import org.apache.myfaces.tobago.internal.component.AbstractUIPopup;
+import org.apache.myfaces.tobago.internal.component.AbstractUISheet;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.FactoryFinder;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.NamingContainer;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.component.UINamingContainer;
+import javax.faces.component.UIParameter;
+import javax.faces.component.UISelectMany;
+import javax.faces.component.UIViewRoot;
+import javax.faces.component.ValueHolder;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.el.ValueBinding;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.ValueChangeEvent;
+import javax.faces.render.RenderKit;
+import javax.faces.render.RenderKitFactory;
+import javax.faces.render.Renderer;
+import javax.faces.view.facelets.FaceletContext;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+public final class ComponentUtils {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ComponentUtils.class);
+
+  public static final String SUB_SEPARATOR = "::";
+
+  private static final String RENDER_KEY_PREFIX
+      = "org.apache.myfaces.tobago.util.ComponentUtils.RendererKeyPrefix_";
+
+  private static final String PAGE_KEY = "org.apache.myfaces.tobago.Page.Key";
+
+  public static final Class[] ACTION_ARGS = {};
+  public static final Class[] ACTION_LISTENER_ARGS = {ActionEvent.class};
+  public static final Class[] VALUE_CHANGE_LISTENER_ARGS = {ValueChangeEvent.class};
+  public static final Class[] VALIDATOR_ARGS = {FacesContext.class, UIComponent.class, Object.class};
+  public static final String LIST_SEPARATOR_CHARS = ", ";
+
+  /**
+   * Name of the map for data attributes in components. New in JSF 2.2.
+   *
+   * @since 2.0.0
+   */
+  public static final String DATA_ATTRIBUTES_KEY = "javax.faces.component.DATA_ATTRIBUTES_KEY";
+
+  private ComponentUtils() {
+  }
+
+  public static boolean hasErrorMessages(final FacesContext context) {
+    for (final Iterator iter = context.getMessages(); iter.hasNext();) {
+      final FacesMessage message = (FacesMessage) iter.next();
+      if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static String getFacesMessageAsString(final FacesContext facesContext, final UIComponent component) {
+    final Iterator messages = facesContext.getMessages(
+        component.getClientId(facesContext));
+    final StringBuilder stringBuffer = new StringBuilder();
+    while (messages.hasNext()) {
+      final FacesMessage message = (FacesMessage) messages.next();
+      stringBuffer.append(message.getDetail());
+    }
+    if (stringBuffer.length() > 0) {
+      return stringBuffer.toString();
+    } else {
+      return null;
+    }
+  }
+
+  public static boolean isInPopup(UIComponent component) {
+    while (component != null) {
+      if (component instanceof AbstractUIPopup) {
+        return true;
+      }
+      component = component.getParent();
+    }
+    return false;
+  }
+
+  public static void resetPage(final FacesContext context) {
+    final UIViewRoot view = context.getViewRoot();
+    if (view != null) {
+      view.getAttributes().remove(PAGE_KEY);
+    }
+  }
+
+  /**
+   * Tries to walk up the parents to find the UIViewRoot, if not found, then go to FaceletContext's FacesContext for
+   * the view root.
+   */
+  public static UIViewRoot findViewRoot(final FaceletContext faceletContext, final UIComponent component) {
+    final UIViewRoot viewRoot = findAncestor(component, UIViewRoot.class);
+    if (viewRoot != null) {
+      return viewRoot;
+    } else {
+      return faceletContext.getFacesContext().getViewRoot();
+    }
+  }
+
+  public static AbstractUIPage findPage(final FacesContext context, final UIComponent component) {
+    final UIViewRoot view = context.getViewRoot();
+    if (view != null) {
+      TransientStateHolder stateHolder = (TransientStateHolder) view.getAttributes().get(PAGE_KEY);
+      if (stateHolder == null || stateHolder.isEmpty()) {
+        final AbstractUIPage page = findPage(component);
+        stateHolder = new TransientStateHolder(page);
+        context.getViewRoot().getAttributes().put(PAGE_KEY, stateHolder);
+      }
+      return (AbstractUIPage) stateHolder.get();
+    } else {
+      return findPage(component);
+    }
+  }
+
+  public static AbstractUIPage findPage(UIComponent component) {
+    if (component instanceof UIViewRoot) {
+      return findPageBreadthFirst(component);
+    } else {
+      while (component != null) {
+        if (component instanceof AbstractUIPage) {
+          return (AbstractUIPage) component;
+        }
+        component = component.getParent();
+      }
+      return null;
+    }
+  }
+
+  public static AbstractUIPage findPage(final FacesContext facesContext) {
+    return findPageBreadthFirst(facesContext.getViewRoot());
+  }
+
+  private static AbstractUIPage findPageBreadthFirst(final UIComponent component) {
+    for (final UIComponent child : component.getChildren()) {
+      if (child instanceof AbstractUIPage) {
+        return (AbstractUIPage) child;
+      }
+    }
+    for (final UIComponent child : component.getChildren()) {
+      final AbstractUIPage result = findPageBreadthFirst(child);
+      if (result != null) {
+        return result;
+      }
+    }
+    return null;
+  }
+
+
+  public static AbstractUIFormBase findForm(UIComponent component) {
+    while (component != null) {
+      if (component instanceof AbstractUIFormBase) {
+        return (AbstractUIFormBase) component;
+      }
+      component = component.getParent();
+    }
+    return null;
+  }
+
+  public static <T> T findAncestor(UIComponent component, final Class<T> type) {
+
+    while (component != null) {
+      if (type.isAssignableFrom(component.getClass())) {
+        return (T) component;
+      }
+      component = component.getParent();
+    }
+    return null;
+  }
+
+  /**
+   * Find all sub forms of a component, and collects it.
+   * It does not find sub forms of sub forms.
+   */
+  public static List<AbstractUIForm> findSubForms(final UIComponent component) {
+    final List<AbstractUIForm> collect = new ArrayList<AbstractUIForm>();
+    findSubForms(collect, component);
+    return collect;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static void findSubForms(final List<AbstractUIForm> collect, final UIComponent component) {
+    final Iterator<UIComponent> kids = component.getFacetsAndChildren();
+    while (kids.hasNext()) {
+      final UIComponent child = kids.next();
+      if (child instanceof AbstractUIForm) {
+        collect.add((AbstractUIForm) child);
+      } else {
+        findSubForms(collect, child);
+      }
+    }
+  }
+
+  /**
+   * Searches the component tree beneath the component and return the first component matching the type.
+   */
+  public static <T extends UIComponent> T findDescendant(final UIComponent component, final Class<T> type) {
+
+    for (final UIComponent child : component.getChildren()) {
+      if (type.isAssignableFrom(child.getClass())) {
+        return (T) child;
+      }
+      final T descendant = findDescendant(child, type);
+      if (descendant != null) {
+        return descendant;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Searches the component tree beneath the component and return the first component matching the type.
+   */
+  public static <T extends UIComponent> T findFacetDescendant(
+      final UIComponent component, final Facets facet, final Class<T> type) {
+
+    final UIComponent facetComponent = component.getFacet(facet.name());
+    if (facetComponent != null) {
+      if (type.isAssignableFrom(facetComponent.getClass())) {
+        return (T) facetComponent;
+      } else {
+        return findDescendant(facetComponent, type);
+      }
+    } else {
+      return null;
+    }
+  }
+
+  /**
+   * Searches the children beneath the component and return the first component matching the type.
+   */
+  public static <T extends UIComponent> T findChild(final UIComponent component, final Class<T> type) {
+
+    for (final UIComponent child : component.getChildren()) {
+      if (type.isAssignableFrom(child.getClass())) {
+        return (T) child;
+      }
+    }
+    return null;
+  }
+
+  /**
+   * Searches the component tree beneath the component and return all component matching the type.
+   */
+  public static <T extends UIComponent> List<T> findDescendantList(final UIComponent component, final Class<T> type) {
+
+    final List<T> result = new ArrayList<T>();
+
+    for (final UIComponent child : component.getChildren()) {
+      if (type.isAssignableFrom(child.getClass())) {
+        result.add((T) child);
+      }
+      result.addAll(findDescendantList(child, type));
+    }
+    return result;
+  }
+
+  /**
+   * Looks for the attribute "for" in the component. If there is any
+   * search for the component which is referenced by the "for" attribute,
+   * and return their clientId.
+   * If there is no "for" attribute, return the "clientId" of the parent
+   * (if it has a parent). This is useful for labels.
+   */
+  public static String findClientIdFor(final UIComponent component, final FacesContext facesContext) {
+    final UIComponent forComponent = findFor(component);
+    if (forComponent != null) {
+      final String clientId = forComponent.getClientId(facesContext);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("found clientId: '" + clientId + "'");
+      }
+      return clientId;
+    }
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("found no clientId");
+    }
+    return null;
+  }
+
+  public static UIComponent findFor(final UIComponent component) {
+    final String forValue = getStringAttribute(component, Attributes.forValue);
+    if (forValue == null) {
+      return component.getParent();
+    }
+    return ComponentUtils.findComponent(component, forValue);
+  }
+
+  /**
+   * Looks for the attribute "for" of the component.
+   * In case that the value is equals to "@auto" the children of the parent will be
+   * checked if they are of the type of the parameter clazz. The "id" of the first one will be used to reset the "for"
+   * attribute of the component.
+   */
+  public static void evaluateAutoFor(final UIComponent component, final Class<? extends UIComponent> clazz) {
+    final String forComponent = getStringAttribute(component, Attributes.forValue);
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("for = '" + forComponent + "'");
+    }
+    if ("@auto".equals(forComponent)) {
+      // parent
+      for (final UIComponent child : component.getParent().getChildren()) {
+        if (setForToInput(component, child, clazz, component instanceof NamingContainer)) {
+          return;
+        }
+      }
+      // grand parent
+      for (final UIComponent child : component.getParent().getParent().getChildren()) {
+        if (setForToInput(component, child, clazz, component.getParent() instanceof NamingContainer)) {
+          return;
+        }
+      }
+    }
+  }
+
+  private static boolean setForToInput(
+      final UIComponent component, final UIComponent child, final Class<? extends UIComponent> clazz,
+      final boolean namingContainer) {
+    if (clazz.isAssignableFrom(child.getClass())) { // find the matching component
+      final String forComponent;
+      if (namingContainer) {
+        forComponent = ":::" + child.getId();
+      } else {
+        forComponent = child.getId();
+      }
+      ComponentUtils.setAttribute(component, Attributes.forValue, forComponent);
+      return true;
+    }
+    return false;
+  }
+
+  public static boolean isInActiveForm(UIComponent component) {
+    while (component != null) {
+      if (component instanceof AbstractUIFormBase) {
+        final AbstractUIFormBase form = (AbstractUIFormBase) component;
+        if (form.isSubmitted()) {
+          return true;
+        }
+      }
+      component = component.getParent();
+    }
+    return false;
+  }
+
+  public static FacesMessage.Severity getMaximumSeverity(final UIComponent component) {
+    final boolean invalid = component instanceof UIInput && !((UIInput) component).isValid();
+    FacesMessage.Severity max = invalid ? FacesMessage.SEVERITY_ERROR : null;
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final Iterator messages = facesContext.getMessages(component.getClientId(facesContext));
+    while (messages.hasNext()) {
+      final FacesMessage message = (FacesMessage) messages.next();
+      if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) {
+        max = message.getSeverity();
+      }
+    }
+    return max;
+  }
+
+  public static boolean isError(final UIInput uiInput) {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    return !uiInput.isValid()
+        || facesContext.getMessages(uiInput.getClientId(facesContext)).hasNext();
+  }
+
+  public static boolean isError(final UIComponent component) {
+    if (component instanceof AbstractUIInput) {
+      return isError((AbstractUIInput) component);
+    }
+    return false;
+  }
+
+  public static boolean isOutputOnly(final UIComponent component) {
+    return getBooleanAttribute(component, Attributes.disabled)
+        || getBooleanAttribute(component, Attributes.readonly);
+  }
+
+  public static Object getAttribute(final UIComponent component, final Attributes name) {
+    return component.getAttributes().get(name.getName());
+  }
+
+  public static boolean getBooleanAttribute(final UIComponent component, final Attributes name) {
+    return getBooleanAttribute(component, name, false);
+  }
+
+  public static boolean getBooleanAttribute(
+      final UIComponent component, final Attributes name, final boolean defaultValue) {
+
+    Object bool = component.getAttributes().get(name.getName());
+    if (bool == null) {
+      return defaultValue;
+    } else if (bool instanceof Boolean) {
+      return (Boolean) bool;
+    } else {
+      return Boolean.valueOf(bool.toString());
+    }
+  }
+
+  public static String getStringAttribute(final UIComponent component, final Attributes name) {
+    return getStringAttribute(component, name, null);
+  }
+
+  public static String getStringAttribute(
+      final UIComponent component, final Attributes name, final String defaultValue) {
+    final String result = (String) getAttribute(component, name);
+    return result != null ? result : defaultValue;
+  }
+
+  public static int getIntAttribute(final UIComponent component, final Attributes name) {
+    return getIntAttribute(component, name, 0);
+  }
+
+  public static int getIntAttribute(final UIComponent component, final Attributes name, final int defaultValue) {
+    final Object integer = component.getAttributes().get(name.getName());
+    if (integer instanceof Number) {
+      return ((Number) integer).intValue();
+    } else if (integer instanceof String) {
+      try {
+        return Integer.parseInt((String) integer);
+      } catch (final NumberFormatException e) {
+        LOG.warn("Can't parse number from string : \"" + integer + "\"!");
+        return defaultValue;
+      }
+    } else if (integer == null) {
+      return defaultValue;
+    } else {
+      LOG.warn("Unknown type '" + integer.getClass().getName()
+          + "' for integer attribute: " + name + " comp: " + component);
+      return defaultValue;
+    }
+  }
+
+  public static Character getCharacterAttribute(final UIComponent component, final Attributes name) {
+    final Object character = getAttribute(component, name);
+    if (character == null) {
+      return null;
+    } else if (character instanceof Character) {
+      return ((Character) character);
+    } else if (character instanceof String) {
+      final String asString = ((String) character);
+      return asString.length() > 0 ? asString.charAt(0) : null;
+    } else {
+      LOG.warn("Unknown type '" + character.getClass().getName()
+          + "' for integer attribute: " + name + " comp: " + component);
+      return null;
+    }
+  }
+
+  public static void setAttribute(final UIComponent component, final Attributes name, final Object value) {
+    component.getAttributes().put(name.getName(), value);
+  }
+
+  public static void removeAttribute(final UIComponent component, final Attributes name) {
+    component.getAttributes().remove(name.getName());
+  }
+
+  public static UIComponent getFacet(final UIComponent component, final Facets facet) {
+    return component.getFacet(facet.name());
+  }
+
+  public static void setFacet(final UIComponent component, final Facets facet, final UIComponent child) {
+    component.getFacets().put(facet.name(), child);
+  }
+
+  public static boolean isFacetOf(final UIComponent component, final UIComponent parent) {
+    for (final Object o : parent.getFacets().keySet()) {
+      final UIComponent facet = parent.getFacet((String) o);
+      if (component.equals(facet)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  public static RendererBase getRenderer(final FacesContext facesContext, final UIComponent component) {
+    return getRenderer(facesContext, component.getFamily(), component.getRendererType());
+  }
+
+  public static RendererBase getRenderer(final FacesContext facesContext, final String family,
+                                         final String rendererType) {
+    if (rendererType == null) {
+      return null;
+    }
+
+    final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
+    final StringBuilder key = new StringBuilder(RENDER_KEY_PREFIX);
+    key.append(rendererType);
+    RendererBase renderer = (RendererBase) requestMap.get(key.toString());
+
+    if (renderer == null) {
+      final Renderer myRenderer = getRendererInternal(facesContext, family, rendererType);
+      if (myRenderer instanceof RendererBase) {
+        requestMap.put(key.toString(), myRenderer);
+        renderer = (RendererBase) myRenderer;
+      } else {
+        return null;
+      }
+    }
+    return renderer;
+  }
+
+
+  private static Renderer getRendererInternal(
+      final FacesContext facesContext, final String family, final String rendererType) {
+    final RenderKitFactory rkFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
+    final RenderKit renderKit = rkFactory.getRenderKit(facesContext, facesContext.getViewRoot().getRenderKitId());
+    final Renderer myRenderer = renderKit.getRenderer(family, rendererType);
+    return myRenderer;
+  }
+
+  public static Object findParameter(final UIComponent component, final String name) {
+    for (final UIComponent child : component.getChildren()) {
+      if (child instanceof UIParameter) {
+        final UIParameter parameter = (UIParameter) child;
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Select name='" + parameter.getName() + "'");
+          LOG.debug("Select value='" + parameter.getValue() + "'");
+        }
+        if (name.equals(parameter.getName())) {
+          return parameter.getValue();
+        }
+      }
+    }
+    return null;
+  }
+
+  /**
+   * <p>
+   * The search depends on the number of prefixed colons in the relativeId:
+   * </p>
+   * <dl>
+   * <dd>number of prefixed colons == 0</dd>
+   * <dt>fully relative</dt>
+   * <dd>number of prefixed colons == 1</dd>
+   * <dt>absolute (still normal findComponent syntax)</dt>
+   * <dd>number of prefixed colons == 2</dd>
+   * <dt>search in the current naming container (same as 0 colons)</dt>
+   * <dd>number of prefixed colons == 3</dd>
+   * <dt>search in the parent naming container of the current naming container</dt>
+   * <dd>number of prefixed colons &gt; 3</dd>
+   * <dt>go to the next parent naming container for each additional colon</dt>
+   * </dl>
+   * <p>
+   * If a literal is specified: to use more than one identifier the identifiers must be space delimited.
+   * </p>
+   */
+  public static UIComponent findComponent(final UIComponent from, final String relativeId) {
+    UIComponent from1 = from;
+    String relativeId1 = relativeId;
+    final int idLength = relativeId1.length();
+    if (idLength > 0 && relativeId1.charAt(0) == '@') {
+      if (relativeId1.equals("@this")) {
+        return from1;
+      }
+    }
+
+    // Figure out how many colons
+    int colonCount = 0;
+    while (colonCount < idLength) {
+      if (relativeId1.charAt(colonCount) != UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance())) {
+        break;
+      }
+      colonCount++;
+    }
+
+    // colonCount == 0: fully relative
+    // colonCount == 1: absolute (still normal findComponent syntax)
+    // colonCount > 1: for each extra colon after 1, go up a naming container
+    // (to the view root, if naming containers run out)
+    if (colonCount > 1) {
+      relativeId1 = relativeId1.substring(colonCount);
+      for (int j = 1; j < colonCount; j++) {
+        while (from1.getParent() != null) {
+          from1 = from1.getParent();
+          if (from1 instanceof NamingContainer) {
+            break;
+          }
+        }
+      }
+    }
+    return from1.findComponent(relativeId1);
+  }
+
+  /**
+   * Resolves the real clientIds.
+   */
+  public static String evaluateClientIds(
+      final FacesContext context, final UIComponent component, final String[] componentIds) {
+    final List<String> result = new ArrayList<String>(componentIds.length);
+    for (final String id : componentIds) {
+      if (!StringUtils.isBlank(id)) {
+        final String clientId = evaluateClientId(context, component, id);
+        if (clientId != null) {
+          result.add(clientId);
+        }
+      }
+    }
+    if (result.isEmpty()) {
+      return null;
+    } else {
+      return StringUtils.join(result, ' ');
+    }
+  }
+
+  /**
+   * Resolves the real clientId.
+   */
+  public static String evaluateClientId(
+      final FacesContext context, final UIComponent component, final String componentId) {
+    final UIComponent partiallyComponent = ComponentUtils.findComponent(component, componentId);
+    if (partiallyComponent != null) {
+      final String clientId = partiallyComponent.getClientId(context);
+      if (partiallyComponent instanceof AbstractUISheet) {
+        final int rowIndex = ((AbstractUISheet) partiallyComponent).getRowIndex();
+        if (rowIndex >= 0 && clientId.endsWith(Integer.toString(rowIndex))) {
+          return clientId.substring(0, clientId.lastIndexOf(UINamingContainer.getSeparatorChar(context)));
+        }
+      }
+      return clientId;
+    }
+    LOG.error("No component found for id='" + componentId + "', "
+        + "search base component is '" + component.getClientId(context) + "'");
+    return null;
+  }
+
+  public static String[] splitList(final String renderers) {
+    return StringUtils.split(renderers, LIST_SEPARATOR_CHARS);
+  }
+
+  public static Object getConvertedValue(
+      final FacesContext facesContext, final UIComponent component, final String stringValue) {
+    try {
+      final Renderer renderer = getRenderer(facesContext, component);
+      if (renderer != null) {
+        if (component instanceof UISelectMany) {
+          final Object converted = renderer.getConvertedValue(facesContext, component, new String[]{stringValue});
+          return converted instanceof Collection ? CollectionUtils.get(converted, 0) : ((Object[]) converted)[0];
+        } else {
+          return renderer.getConvertedValue(facesContext, component, stringValue);
+        }
+      } else if (component instanceof ValueHolder) {
+        Converter converter = ((ValueHolder) component).getConverter();
+        if (converter == null) {
+          //Try to find out by value binding
+          final ValueBinding vb = component.getValueBinding("value");
+          if (vb != null) {
+            final Class valueType = vb.getType(facesContext);
+            if (valueType != null) {
+              converter = facesContext.getApplication().createConverter(valueType);
+            }
+          }
+        }
+        if (converter != null) {
+          converter.getAsObject(facesContext, component, stringValue);
+        }
+      }
+    } catch (final Exception e) {
+      LOG.warn("Can't convert string value '" + stringValue + "'", e);
+    }
+    return stringValue;
+  }
+
+  public static Markup updateMarkup(final UIComponent component, Markup markup) {
+    if (markup == null) {
+      markup = Markup.NULL;
+    }
+    if (ComponentUtils.getBooleanAttribute(component, Attributes.disabled)) {
+      markup = markup.add(Markup.DISABLED);
+    }
+    if (ComponentUtils.getBooleanAttribute(component, Attributes.readonly)) {
+      markup = markup.add(Markup.READONLY);
+    }
+    if (component instanceof UIInput) {
+      final UIInput input = (UIInput) component;
+
+      final FacesMessage.Severity maximumSeverity = ComponentUtils.getMaximumSeverity(input);
+      markup = markup.add(markupOfSeverity(maximumSeverity));
+
+      if (input.isRequired()) {
+        markup = markup.add(Markup.REQUIRED);
+      }
+    }
+    return markup;
+  }
+
+  public static Markup markupOfSeverity(final FacesMessage.Severity maximumSeverity) {
+    if (FacesMessage.SEVERITY_FATAL.equals(maximumSeverity)) {
+      return Markup.FATAL;
+    } else if (FacesMessage.SEVERITY_ERROR.equals(maximumSeverity)) {
+      return Markup.ERROR;
+    } else if (FacesMessage.SEVERITY_WARN.equals(maximumSeverity)) {
+      return Markup.WARN;
+    } else if (FacesMessage.SEVERITY_INFO.equals(maximumSeverity)) {
+      return Markup.INFO;
+    }
+    return null;
+  }
+
+  public static FacesMessage.Severity getMaximumSeverityOfChildrenMessages(
+      final FacesContext facesContext, final NamingContainer container) {
+    if (container instanceof UIComponent) {
+      final String clientId = ((UIComponent) container).getClientId(facesContext);
+      FacesMessage.Severity max = null;
+      for (final Iterator ids = facesContext.getClientIdsWithMessages(); ids.hasNext();) {
+        final String id = (String) ids.next();
+        if (id != null && id.startsWith(clientId)) {
+          final Iterator messages = facesContext.getMessages(id);
+          while (messages.hasNext()) {
+            final FacesMessage message = (FacesMessage) messages.next();
+            if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) {
+              max = message.getSeverity();
+            }
+          }
+        }
+      }
+      return max;
+    }
+    return null;
+  }
+
+  /**
+   * Adding a data attribute to the component.
+   * The name must start with "data-", e. g. "data-tobago-foo" or "data-bar"
+   */
+  public static void putDataAttributeWithPrefix(
+      final UIComponent component, final DataAttributes name, final Object value) {
+    if (name.getValue().startsWith("data-")) {
+      putDataAttribute(component, name.getValue().substring(5), value);
+    } else {
+      LOG.error("The name must start with 'data-' but it doesn't: '" + name + "'");
+    }
+  }
+
+  /**
+   * Adding a data attribute to the component.
+   * The name should not start with "data-", e. g. "tobago-foo" or "bar"
+   */
+  public static void putDataAttribute(final UIComponent component, final Object name, final Object value) {
+    Map<Object, Object> map = getDataAttributes(component);
+    if (map == null) {
+      map = new HashMap<Object, Object>();
+      component.getAttributes().put(DATA_ATTRIBUTES_KEY, map);
+    }
+    map.put(name, value);
+  }
+
+  @SuppressWarnings("unchecked")
+  public static Map<Object, Object> getDataAttributes(final UIComponent component) {
+    return (Map<Object, Object>) component.getAttributes().get(DATA_ATTRIBUTES_KEY);
+  }
+
+  public static Object getDataAttribute(final UIComponent component, final String name) {
+    Map<Object, Object> map = getDataAttributes(component);
+    return map != null ? map.get(name) : null;
+  }
+
+  public static Converter getConverter(
+      final FacesContext facesContext, final UIComponent component, final Object value) {
+
+    Converter converter = null;
+    if (component instanceof ValueHolder) {
+      converter = ((ValueHolder) component).getConverter();
+    }
+
+    if (converter == null) {
+      final ValueExpression valueExpression = component.getValueExpression("value");
+      if (valueExpression != null) {
+        Class converterType = null;
+        try {
+          converterType = valueExpression.getType(facesContext.getELContext());
+        } catch (Exception e) {
+          // ignore, seems not to be possible, when EL is a function like #{bean.getName(item.id)}
+        }
+        if (converterType == null) {
+          converterType = value.getClass();
+        }
+        if (converterType != null && converterType != Object.class) {
+          converter = facesContext.getApplication().createConverter(converterType);
+        }
+      }
+    }
+
+    return converter;
+  }
+
+  public static String getFormattedValue(
+      final FacesContext facesContext, final UIComponent component, final Object currentValue)
+      throws ConverterException {
+
+    if (currentValue == null) {
+      return "";
+    }
+
+    final Converter converter = ComponentUtils.getConverter(facesContext, component, currentValue);
+    if (converter != null) {
+      return converter.getAsString(facesContext, component, currentValue);
+    } else {
+      return currentValue.toString();
+    }
+  }
+
+  public static UIComponent createComponent(
+      final FacesContext facesContext, final String componentType, final RendererTypes rendererType,
+      final String clientId) {
+    final UIComponent component  = facesContext.getApplication().createComponent(componentType);
+    if (rendererType != null) {
+      component.setRendererType(rendererType.name());
+    }
+    component.setId(clientId);
+    return component;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ContextCallback.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ContextCallback.java
new file mode 100644
index 0000000..88c165b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ContextCallback.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+
+import javax.faces.context.FacesContext;
+import javax.faces.component.UIComponent;
+
+public interface ContextCallback {
+  void invokeContextCallback(FacesContext facesContext, UIComponent component);
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/CreateComponentUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/CreateComponentUtils.java
new file mode 100644
index 0000000..8481ec5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/CreateComponentUtils.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+public final class CreateComponentUtils {
+
+  private CreateComponentUtils() {
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugActionListener.java
new file mode 100644
index 0000000..12c945a0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugActionListener.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.event.ActionListener;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.AbortProcessingException;
+
+public class DebugActionListener implements ActionListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DebugActionListener.class);
+
+  private final ActionListener actionListener;
+
+
+  public DebugActionListener(final ActionListener actionListener) {
+    this.actionListener = actionListener;
+  }
+
+  @Override
+  public void processAction(final ActionEvent actionEvent) throws AbortProcessingException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("processAction " + actionEvent);
+    }
+    actionListener.processAction(actionEvent);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugNavigationHandler.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugNavigationHandler.java
new file mode 100644
index 0000000..92a485f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugNavigationHandler.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.NavigationHandler;
+import javax.faces.context.FacesContext;
+
+public class DebugNavigationHandler extends NavigationHandler {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DebugNavigationHandler.class);
+
+  private NavigationHandler navigationHandler;
+
+  public DebugNavigationHandler(final NavigationHandler navigationHandler) {
+    this.navigationHandler = navigationHandler;
+  }
+
+  @Override
+  public void handleNavigation(final FacesContext facesContext, final String fromAction, final String outcome) {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Handle Navigation context: " + facesContext + " fromAction: '"
+          + fromAction + "' outcome: '" + outcome + "'");
+    }
+
+    // TBD: is this correct?
+    if (outcome != null && facesContext.getPartialViewContext().isAjaxRequest()) {
+        LOG.warn("An AJAX-Request should not have an outcome set: outcome='" + outcome + "'");
+    }
+
+    navigationHandler.handleNavigation(facesContext, fromAction, outcome);
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("Handled Navigation context: " + facesContext + " fromAction: '"
+          + fromAction + "' outcome: '" + outcome + "'");
+    }
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugPhaseListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugPhaseListener.java
new file mode 100644
index 0000000..0e10386
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugPhaseListener.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.application.ProjectStage;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.text.MessageFormat;
+import java.util.Iterator;
+import java.util.Map;
+
+public class DebugPhaseListener implements PhaseListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DebugPhaseListener.class);
+
+  private static final String KEY = DebugPhaseListener.class.getName() + "_ID_";
+
+  @Override
+  public void afterPhase(final PhaseEvent phaseEvent) {
+    final FacesContext facesContext = phaseEvent.getFacesContext();
+    final boolean productionMode = TobagoConfig.getInstance(facesContext).getProjectStage() == ProjectStage.Production;
+    if (facesContext.getResponseComplete() || productionMode) {
+      return;
+    }
+
+    if (LOG.isInfoEnabled()) {
+      final Long end = System.currentTimeMillis();
+      final Map<String, Object> map = facesContext.getExternalContext().getRequestMap();
+      map.put(KEY + phaseEvent.getPhaseId().getOrdinal() + "E", end);
+
+      if (LOG.isTraceEnabled()) {
+        LOG.trace("After Phase :" + phaseEvent.getPhaseId() + " Time=" + end);
+      }
+
+      if (LOG.isDebugEnabled()) {
+        final Long start = (Long) map.get(KEY + phaseEvent.getPhaseId().getOrdinal() + "S");
+        LOG.debug("Phase " + phaseEvent.getPhaseId() + " needs " + (end - start + " milliseconds"));
+      }
+
+      if (phaseEvent.getPhaseId().getOrdinal() == 6) {
+        if (LOG.isTraceEnabled()) {
+          final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
+          LOG.trace(" response Locale            = '" + response.getLocale() + "'");
+          LOG.trace(" response ContentType       = '" + response.getContentType() + "'");
+          LOG.trace(" response CharacterEncoding = '{" + response.getCharacterEncoding() + "}'");
+        }
+
+        final Long start = (Long) map.get(KEY + "1S");
+        if (start != null) {
+          LOG.info("Total response time : " + (end - start + " milliseconds"));
+        }
+      }
+      for (final Iterator iterator = facesContext.getClientIdsWithMessages(); iterator.hasNext();) {
+        final String clientId = (String) iterator.next();
+
+        for (final Iterator messageIterator = facesContext.getMessages(clientId); messageIterator.hasNext();) {
+          final FacesMessage msg = (FacesMessage) messageIterator.next();
+          LOG.info(MessageFormat.format("Faces message found."
+              + "\n  Component: {0} \n  Severity : {1}"
+              + "\n  Summary  : {2} \n  Detail   : {3}",
+              clientId, msg.getSeverity(), msg.getSummary(), msg.getDetail()));
+        }
+      }
+    }
+  }
+
+  @Override
+  public void beforePhase(final PhaseEvent phaseEvent) {
+    final FacesContext facesContext = phaseEvent.getFacesContext();
+    final boolean productionMode = TobagoConfig.getInstance(facesContext).getProjectStage() == ProjectStage.Production;
+    if (facesContext.getResponseComplete()) {
+      LOG.info("Response is completed.");
+      return;
+    }
+    if (productionMode) {
+      LOG.warn("DebugPhaseListener disabled, because the project stage is 'production'.");
+      return;
+    }
+
+    if (LOG.isInfoEnabled()) {
+      final PhaseId phaseId = phaseEvent.getPhaseId();
+      if (LOG.isDebugEnabled() || phaseId.getOrdinal() == 1) {
+
+        final ExternalContext externalContext = facesContext.getExternalContext();
+
+        if (LOG.isTraceEnabled() && PhaseId.RESTORE_VIEW == phaseId) {
+          // this is before restoreView
+
+          final Object request = externalContext.getRequest();
+          if (request instanceof HttpServletRequest) {
+            final HttpServletRequest servletRequest = (HttpServletRequest) request;
+            LOG.trace("RequestURI = " + servletRequest.getRequestURI());
+          }
+          final Map headerMap = externalContext.getRequestHeaderMap();
+          for (final Object key : headerMap.keySet()) {
+            LOG.trace("Header : '" + key + "' = '" + headerMap.get(key) + "'");
+          }
+          final Map parameterMap = externalContext.getRequestParameterMap();
+          for (final Object key : parameterMap.keySet()) {
+            LOG.trace("Param  : '" + key + "' = '" + parameterMap.get(key) + "'");
+          }
+        }
+
+        final Long start = System.currentTimeMillis();
+        final Map<String, Object> map = externalContext.getRequestMap();
+        map.put(KEY + phaseId.getOrdinal() + "S", start);
+
+        if (LOG.isDebugEnabled()) {
+          Long end = null;
+          int ordinal = phaseId.getOrdinal();
+          while (end == null && ordinal > 0) {
+            end = (Long) map.get(KEY + --ordinal + "E");
+          }
+          if (end != null) {
+            LOG.debug("Time between phases " + ordinal + " and " + phaseId.getOrdinal() + ": "
+                + (start - end) + " milliseconds");
+          }
+        }
+        if (LOG.isTraceEnabled()) {
+          LOG.trace("Before Phase :" + phaseId + " Time=" + start);
+        }
+      }
+    }
+  }
+
+  @Override
+  public PhaseId getPhaseId() {
+    return PhaseId.ANY_PHASE;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugUtils.java
new file mode 100644
index 0000000..03d245c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/DebugUtils.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.application.ProjectStage;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+
+public final class DebugUtils {
+
+  private DebugUtils() {
+    // to prevent instantiation
+  }
+
+  public static String toString(final UIComponent component, final int offset) {
+    return toString(component, offset, false, null);
+  }
+
+  public static String toString(
+      final UIComponent component, final int offset, final boolean asFacet, final Integer childIndex) {
+    final StringBuilder result = new StringBuilder();
+    if (component == null) {
+      result.append("null");
+    } else {
+      if (!asFacet) {
+        result.append(spaces(offset));
+        if (childIndex != null) {
+          result.append('[');
+          result.append(childIndex);
+          result.append("] ");
+        }
+        result.append(toString(component));
+      }
+      final Map facets = component.getFacets();
+      if (facets.size() > 0) {
+        for (final Map.Entry<String, UIComponent> entry : (Set<Map.Entry<String, UIComponent>>) facets.entrySet()) {
+          final UIComponent facet = entry.getValue();
+          result.append(spaces(offset + 1));
+          result.append('[');
+          result.append(entry.getKey());
+          result.append("] ");
+          result.append(toString(facet));
+          result.append(toString(facet, offset + 1, true, null));
+        }
+      }
+      final List<UIComponent> children = component.getChildren();
+      for (int i = 0; i < children.size(); i++) {
+        result.append(toString(children.get(i), offset + 1, false, i));
+      }
+    }
+    return result.toString();
+  }
+
+  public static String toString(final UIComponent component) {
+    final StringBuilder buf = new StringBuilder(component.getClass().getName());
+//    buf.append('@');
+//    buf.append(Integer.toHexString(component.hashCode()));
+    buf.append(" ");
+    buf.append(component.getRendererType());
+    buf.append(" ");
+//      buf.append(component.getId());
+//      buf.append(" ");
+      buf.append(component.getClientId(FacesContext.getCurrentInstance()));
+    if (component instanceof javax.faces.component.UIViewRoot) {
+      buf.append(" viewId=");
+      buf.append(((javax.faces.component.UIViewRoot) component).getViewId());
+    }
+    buf.append(" rendered=");
+    buf.append(component.isRendered());
+    buf.append('\n');
+    return buf.toString();
+  }
+
+  public static String spaces(final int n) {
+    final StringBuilder buffer = new StringBuilder();
+    for (int i = 0; i < n; i++) {
+      buffer.append("  ");
+    }
+    return buffer.toString();
+  }
+
+  public static void addDevelopmentMessage(final FacesContext facesContext, final String message) {
+    if (TobagoConfig.getInstance(FacesContext.getCurrentInstance()).getProjectStage() == ProjectStage.Development) {
+      facesContext.addMessage(null, new FacesMessage(message));
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/FacesELUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/FacesELUtils.java
new file mode 100644
index 0000000..95dafb7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/FacesELUtils.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import javax.el.MethodExpression;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.FacesEvent;
+
+public final class FacesELUtils {
+
+  private FacesELUtils() {
+    // prevent object creation
+  }
+
+  public static void invokeMethodExpression(
+      final FacesContext facesContext, final MethodExpression methodExpression, final FacesEvent event) {
+
+    if (methodExpression != null && event != null) {
+      try {
+        methodExpression.invoke(facesContext.getELContext(), new Object[]{event});
+      } catch (final Exception e) {
+        throw new AbortProcessingException(e);
+      }
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/FacesVersion.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/FacesVersion.java
new file mode 100644
index 0000000..fd3cf51
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/FacesVersion.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import javax.faces.application.Application;
+import javax.faces.context.FacesContext;
+
+public enum FacesVersion {
+
+  VERSION_11,
+  VERSION_12,
+  VERSION_20,
+  VERSION_21,
+  VERSION_22;
+
+  private static FacesVersion currentVersion;
+  private static boolean mojarra;
+  private static boolean myfaces;
+
+  static {
+    try {
+      currentVersion = VERSION_11;
+      Application.class.getMethod("getExpressionFactory");
+      currentVersion = VERSION_12;
+      Application.class.getMethod("getDefaultValidatorInfo");
+      currentVersion = VERSION_20;
+      FacesContext.class.getMethod("isReleased");
+      currentVersion = VERSION_21;
+      Application.class.getMethod("getFlowHandler");
+      currentVersion = VERSION_22;
+    } catch (final NoSuchMethodException e) {
+      // ignore
+    }
+
+    mojarra = isAvailable("com.sun.faces.application.ApplicationImpl");
+    myfaces = isAvailable("org.apache.myfaces.application.ApplicationImpl");
+
+  }
+
+  private static boolean isAvailable(final String className) {
+    try {
+      try {
+        Class.forName(className, false, Thread.currentThread().getContextClassLoader());
+        return true;
+      } catch (final ClassNotFoundException e) {
+        // ignore
+        try {
+          Class.forName(className, false, FacesVersion.class.getClassLoader());
+          return true;
+        } catch (final ClassNotFoundException e1) {
+          // ignore
+        }
+      }
+    } catch (final Exception e) {
+      // ignore
+    }
+    return false;
+  }
+
+  /**
+   * Does the JSF is version 1.2 or higher
+   * @return Supports 1.2 or higher
+   */
+  public static boolean supports12() {
+    return currentVersion == VERSION_12
+        || currentVersion == VERSION_20
+        || currentVersion == VERSION_21
+        || currentVersion == VERSION_22;
+  }
+
+  /**
+   * Does the JSF is version 2.0 or higher
+   * @return Supports 2.0 or higher
+   */
+  public static boolean supports20() {
+    return currentVersion == VERSION_20
+        || currentVersion == VERSION_21
+        || currentVersion == VERSION_22;
+  }
+
+  /**
+   * Does the JSF is version 2.1 or higher
+   * @return Supports 2.1 or higher
+   */
+  public static boolean supports21() {
+    return currentVersion == VERSION_21
+        || currentVersion == VERSION_22;
+  }
+
+  /**
+   * Does the JSF is version 2.2 or higher
+   * @return Supports 2.2 or higher
+   */
+  public static boolean supports22() {
+    return currentVersion == VERSION_22;
+  }
+
+  public static boolean isMojarra() {
+    return mojarra;
+  }
+
+  public static boolean isMyfaces() {
+    return myfaces;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/LocaleUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/LocaleUtils.java
new file mode 100644
index 0000000..a0767e8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/LocaleUtils.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public final class LocaleUtils {
+
+  private LocaleUtils() {
+  }
+
+  public static Locale createLocale(final String value) {
+    Locale locale = null;
+    final String[] strings = StringUtils.split(value, "_");
+    switch (strings.length) {
+      case 1:
+        locale = new Locale(strings[0]);
+        break;
+      case 2:
+        locale = new Locale(strings[0], strings[1]);
+        break;
+      case 3:
+        locale = new Locale(strings[0], strings[1], strings[2]);
+        break;
+      default:
+        // TODO
+    }
+    return locale;
+  }
+
+  /**
+   * @deprecated since 1.5
+   */
+  @Deprecated
+  public static List<Locale> getLocaleList(final Locale locale) {
+
+    String string = locale.toString();
+    final List<Locale> locales = new ArrayList<Locale>(3);
+    locales.add(locale);
+    int underscore;
+    while ((underscore = string.lastIndexOf('_')) > 0) {
+      string = string.substring(0, underscore);
+      locales.add(createLocale(string));
+    }
+
+    return locales;
+  }
+
+  /**
+   * Returns a list of strings, which are used as suffix for resources from resource manager.
+   * 
+   * Sample: "de_DE" -&gt; "_de_DE", "_de", ""
+   */
+  public static List<String> getLocaleSuffixList(final Locale locale) {
+
+    if (locale == null) {
+      return Arrays.asList("");
+    }
+    
+    String string = locale.toString();
+    final String prefix = "_";
+    final List<String> locales = new ArrayList<String>(4);
+    locales.add(prefix + string);
+    int underscore;
+    while ((underscore = string.lastIndexOf('_')) > 0) {
+      string = string.substring(0, underscore);
+      locales.add(prefix + string);
+    }
+
+    locales.add(""); // default suffix is nothing
+
+    return locales;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/MessageFormat.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/MessageFormat.java
new file mode 100644
index 0000000..43414bd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/MessageFormat.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * Helper class for the EL functions <code>tc:format1()</code> ... <code>tc:format9()</code>
+ */
+public class MessageFormat {
+
+  public static String format(String pattern, Object param0) {
+    return createMessageFormat(pattern).format(new Object[] {param0});
+  }
+
+  public static String format(String pattern, Object param0, Object param1) {
+    return createMessageFormat(pattern).format(new Object[] {param0, param1});
+  }
+
+  public static String format(String pattern, Object param0, Object param1, Object param2) {
+    return createMessageFormat(pattern).format(new Object[] {param0, param1, param2});
+  }
+
+  public static String format(String pattern, Object param0, Object param1, Object param2, Object param3) {
+    return createMessageFormat(pattern).format(new Object[] {param0, param1, param2, param3});
+  }
+
+  public static String format(String pattern, Object param0, Object param1, Object param2, Object param3,
+                               Object param4) {
+    return createMessageFormat(pattern).format(new Object[] {param0, param1, param2, param3, param4});
+  }
+
+  public static String format(String pattern, Object param0, Object param1, Object param2, Object param3,
+                               Object param4, Object param5) {
+    return createMessageFormat(pattern).format(new Object[] {param0, param1, param2, param3, param4, param5});
+  }
+
+  public static String format(String pattern, Object param0, Object param1, Object param2, Object param3,
+                               Object param4, Object param5, Object param6) {
+    return createMessageFormat(pattern).format(new Object[] {param0, param1, param2, param3, param4, param5, param6});
+  }
+
+  public static String format(String pattern, Object param0, Object param1, Object param2, Object param3,
+                               Object param4, Object param5, Object param6, Object param7) {
+    return createMessageFormat(pattern).format(
+        new Object[] {param0, param1, param2, param3, param4, param5, param6, param7});
+  }
+
+  public static String format(String pattern, Object param0, Object param1, Object param2, Object param3,
+                               Object param4, Object param5, Object param6, Object param7, Object param8) {
+    return createMessageFormat(pattern).format(
+        new Object[] {param0, param1, param2, param3, param4, param5, param6, param7, param8});
+  }
+
+  private static java.text.MessageFormat createMessageFormat(String pattern) {
+    return new java.text.MessageFormat(pattern, FacesContext.getCurrentInstance().getViewRoot().getLocale());
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/MessageUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/MessageUtils.java
new file mode 100644
index 0000000..a4fec60
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/MessageUtils.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.application.LabelValueExpressionFacesMessage;
+import org.apache.myfaces.tobago.context.TobagoResourceBundle;
+
+import javax.el.ValueExpression;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.text.MessageFormat;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+/**
+ * Utility to create and add {@link FacesMessage} object to the context.
+ * The message will be internationalized with a bundle in the following order:
+ * <ol>
+ * <li>Application bundle</li>
+ * <li>Tobago bundle</li>
+ * <li>Default JSF bundle</li>
+ * </ol>
+ */
+public final class MessageUtils {
+
+  private static final String DETAIL_SUFFIX = "_detail";
+
+  private MessageUtils() {
+  }
+
+  public static void addMessage(
+      final FacesContext facesContext, final UIComponent component, final FacesMessage.Severity severity,
+      final String messageId, final Object[] args) {
+    facesContext.addMessage(component.getClientId(facesContext),
+        getMessage(facesContext, facesContext.getViewRoot().getLocale(), severity, messageId, args));
+  }
+
+  public static FacesMessage getMessage(
+      final FacesContext facesContext, final Locale locale,
+      final FacesMessage.Severity severity, final String messageId, final Object... args) {
+
+    final ResourceBundle appBundle = getApplicationBundle(facesContext, locale);
+    String summary = getBundleString(appBundle, messageId);
+    String detail = getBundleString(appBundle, messageId + DETAIL_SUFFIX);
+
+    if (summary == null || detail == null) {
+      final ResourceBundle tobagoBundle = new TobagoResourceBundle();
+      if (summary == null) {
+        summary = getBundleString(tobagoBundle, messageId);
+      }
+      if (detail == null) {
+        detail = getBundleString(tobagoBundle, messageId + DETAIL_SUFFIX);
+      }
+
+      if (summary == null || detail == null) {
+        final ResourceBundle defBundle = getDefaultBundle(facesContext, locale);
+        if (summary == null) {
+          summary = getBundleString(defBundle, messageId);
+        }
+        if (detail == null) {
+          detail = getBundleString(defBundle, messageId + DETAIL_SUFFIX);
+        }
+      }
+    }
+
+    if (summary == null && detail == null) {
+      //Neither detail nor summary found
+      facesContext.getExternalContext().log("No message with id " + messageId + " found in any bundle");
+      return new FacesMessage(severity, messageId, null);
+    }
+
+    if (args != null && args.length > 0) {
+      MessageFormat format;
+      if (summary != null) {
+        format = new MessageFormat(summary, locale);
+        summary = format.format(args);
+      }
+
+      if (detail != null) {
+        format = new MessageFormat(detail, locale);
+        detail = format.format(args);
+      }
+    }
+    return new LabelValueExpressionFacesMessage(severity, summary, detail);
+  }
+
+  private static String getBundleString(final ResourceBundle bundle, final String key) {
+    try {
+      return bundle == null ? null : bundle.getString(key);
+    } catch (final MissingResourceException e) {
+      return null;
+    }
+  }
+
+  private static ResourceBundle getApplicationBundle(final FacesContext facesContext, final Locale locale) {
+    final String bundleName = facesContext.getApplication().getMessageBundle();
+    return bundleName != null ? getBundle(facesContext, locale, bundleName) : null;
+  }
+
+  private static ResourceBundle getDefaultBundle(final FacesContext facesContext, final Locale locale) {
+    return getBundle(facesContext, locale, FacesMessage.FACES_MESSAGES);
+  }
+
+  private static ResourceBundle getBundle(
+      final FacesContext facesContext, final Locale locale, final String bundleName) {
+    try {
+      return ResourceBundle.getBundle(bundleName, locale, MessageUtils.class.getClassLoader());
+    } catch (final MissingResourceException ignore2) {
+      try {
+        return ResourceBundle.getBundle(bundleName, locale, Thread.currentThread().getContextClassLoader());
+      } catch (final MissingResourceException damned) {
+        facesContext.getExternalContext().log("resource bundle " + bundleName + " could not be found");
+        return null;
+      }
+    }
+  }
+
+  public static String getLabel(final FacesContext facesContext, final UIComponent component) {
+    final Object label = component.getAttributes().get("label");
+    if (label != null) {
+      return label.toString();
+    }
+    final ValueExpression expression = component.getValueExpression("label");
+    if (expression != null) {
+      return expression.getExpressionString();
+    }
+    return component.getClientId(facesContext);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ValueBindingComparator.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ValueBindingComparator.java
new file mode 100644
index 0000000..03454f6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ValueBindingComparator.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+import java.util.Comparator;
+import java.util.Map;
+
+/**
+ * @deprecated Since 2.0.0
+ */
+@Deprecated
+public class ValueBindingComparator extends ComparatorBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ValueBindingComparator.class);
+
+  private FacesContext facesContext;
+
+  private String var;
+
+  private ValueBinding valueBinding;
+
+  public ValueBindingComparator(final FacesContext facesContext, final String var, final ValueBinding valueBinding) {
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueBinding = valueBinding;
+  }
+
+  public ValueBindingComparator(
+      final FacesContext facesContext, final String var, final ValueBinding valueBinding, final boolean reverse) {
+    super(reverse);
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueBinding = valueBinding;
+  }
+
+  public ValueBindingComparator(
+      final FacesContext facesContext, final String var,
+      final ValueBinding valueBinding, final Comparator comparator) {
+    super(comparator);
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueBinding = valueBinding;
+  }
+
+  public ValueBindingComparator(
+      final FacesContext facesContext, final String var,
+      final ValueBinding valueBinding, final boolean reverse, final Comparator comparator) {
+    super(reverse, comparator);
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueBinding = valueBinding;
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final ValueBindingComparator that = (ValueBindingComparator) o;
+
+    if (!super.equals(o)) {
+      return false;
+    }
+    if (facesContext != null ? !facesContext.equals(that.facesContext) : that.facesContext != null) {
+      return false;
+    }
+    if (valueBinding != null ? !valueBinding.equals(that.valueBinding) : that.valueBinding != null) {
+      return false;
+    }
+    if (var != null ? !var.equals(that.var) : that.var != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public int hashCode() {
+    int result;
+    result = (facesContext != null ? facesContext.hashCode() : 0);
+    result = 29 * result + (var != null ? var.hashCode() : 0);
+    result = 29 * result + (valueBinding != null ? valueBinding.hashCode() : 0);
+    result = 29 * result + super.hashCode();
+    return result;
+  }
+
+  // implementation of java.util.Comparator interface
+
+  @Override
+  public int compare(final Object param1, final Object param2) {
+    final Object obj1;
+    final Object obj2;
+    try {
+      final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
+      requestMap.put(var, param1);
+      obj1 = valueBinding.getValue(facesContext);
+      requestMap.put(var, param2);
+      obj2 = valueBinding.getValue(facesContext);
+
+    } catch (final Exception e) {
+      LOG.error(e.getMessage(), e);
+      return 0;
+    }
+    return super.internalCompare(obj1, obj2);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ValueExpressionComparator.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ValueExpressionComparator.java
new file mode 100644
index 0000000..5ec55fc
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/ValueExpressionComparator.java
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ValueExpression;
+import javax.faces.context.FacesContext;
+import java.util.Comparator;
+import java.util.Map;
+
+public class ValueExpressionComparator extends ComparatorBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ValueExpressionComparator.class);
+
+  private FacesContext facesContext;
+
+  private String var;
+
+  private ValueExpression valueExpression;
+
+  public ValueExpressionComparator(
+      final FacesContext facesContext, final String var, final ValueExpression valueExpression) {
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueExpression = valueExpression;
+  }
+
+  public ValueExpressionComparator(
+      final FacesContext facesContext, final String var, final ValueExpression valueExpression,
+      final boolean reverse) {
+    super(reverse);
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueExpression = valueExpression;
+  }
+
+  public ValueExpressionComparator(
+      final FacesContext facesContext, final String var,
+      final ValueExpression valueExpression, final Comparator comparator) {
+    super(comparator);
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueExpression = valueExpression;
+  }
+
+  public ValueExpressionComparator(
+      final FacesContext facesContext, final String var,
+      final ValueExpression valueExpression, final boolean reverse, final Comparator comparator) {
+    super(reverse, comparator);
+    this.facesContext = facesContext;
+    this.var = var;
+    this.valueExpression = valueExpression;
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final ValueExpressionComparator that = (ValueExpressionComparator) o;
+
+    if (!super.equals(o)) {
+      return false;
+    }
+    if (facesContext != null ? !facesContext.equals(that.facesContext) : that.facesContext != null) {
+      return false;
+    }
+    if (valueExpression != null ? !valueExpression.equals(that.valueExpression) : that.valueExpression != null) {
+      return false;
+    }
+    if (var != null ? !var.equals(that.var) : that.var != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public int hashCode() {
+    int result;
+    result = (facesContext != null ? facesContext.hashCode() : 0);
+    result = 29 * result + (var != null ? var.hashCode() : 0);
+    result = 29 * result + (valueExpression != null ? valueExpression.hashCode() : 0);
+    result = 29 * result + super.hashCode();
+    return result;
+  }
+
+  // implementation of java.util.Comparator interface
+
+  @Override
+  public int compare(final Object param1, final Object param2) {
+    final Object obj1;
+    final Object obj2;
+    try {
+      final Map requestMap = facesContext.getExternalContext().getRequestMap();
+      requestMap.put(var, param1);
+      obj1 = valueExpression.getValue(facesContext.getELContext());
+      requestMap.put(var, param2);
+      obj2 = valueExpression.getValue(facesContext.getELContext());
+
+    } catch (final Exception e) {
+      LOG.error(e.getMessage(), e);
+      return 0;
+    }
+    return super.internalCompare(obj1, obj2);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/VariableResolverUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/VariableResolverUtils.java
new file mode 100644
index 0000000..f288860
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/VariableResolverUtils.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import javax.el.ELContext;
+import javax.faces.context.FacesContext;
+
+public final class VariableResolverUtils {
+
+  private VariableResolverUtils() {
+    // utils class
+  }
+
+  /**
+   * Returns the requested object configured in the faces-config or from library.
+   */
+  public static Object resolveVariable(final FacesContext context, final String variable) {
+    final ELContext elContext = context.getELContext();
+    return elContext.getELResolver().getValue(elContext, null, variable);
+  }
+
+  /**
+   * Clears the value of the variable.
+   * Useful for cleaning up e.g. a session or application variable
+   * to save memory without the knowledge of the scope.
+   * Also useful to enforce a new creation of a managed-bean.
+   */
+  public static void clearVariable(final FacesContext context, final String variable) {
+    final ELContext elContext = context.getELContext();
+    elContext.getELResolver().setValue(elContext, null, variable, null);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/XmlUtils.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/XmlUtils.java
new file mode 100644
index 0000000..821515b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/util/XmlUtils.java
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.util.Properties;
+
+public final class XmlUtils {
+
+  private XmlUtils() {
+  }
+
+  public static String escape(final String s) {
+    return escape(s, true);
+  }
+
+  public static String escape(final String s, final boolean isAttributeValue) {
+    if (null == s) {
+      return "";
+    }
+    final int len = s.length();
+    final StringBuilder buffer = new StringBuilder(len);
+    for (int i = 0; i < len; i++) {
+      appendEntityRef(buffer, s.charAt(i), isAttributeValue);
+    }
+    return buffer.toString();
+  }
+
+  public static String escape(final char[] chars, final int offset, final int length, final boolean isAttributeValue) {
+    if (null == chars) {
+      return "";
+    }
+    final StringBuilder buffer = new StringBuilder(length);
+    for (int i = offset; i < length; i++) {
+      appendEntityRef(buffer, chars[i], isAttributeValue);
+    }
+    return buffer.toString();
+  }
+
+  private static void appendEntityRef(final StringBuilder buffer, final char ch,
+      final boolean isAttributeValue) {
+    // Encode special XML characters into the equivalent character references.
+    // These five are defined by default for all XML documents.
+    switch (ch) {
+      case '<':
+        buffer.append("&lt;");
+        break;
+      case '&':
+        buffer.append("&amp;");
+        break;
+      case '"': // need inside attributes values
+        if (isAttributeValue) {
+          buffer.append("&quot;");
+        } else {
+          buffer.append(ch);
+        }
+        break;
+      case '\'': // need inside attributes values
+        if (isAttributeValue) {
+          buffer.append("&apos;");
+        } else {
+          buffer.append(ch);
+        }
+        break;
+      case '>': // optional
+        buffer.append("&gt;");
+        break;
+      default:
+        buffer.append(ch);
+    }
+  }
+
+  /** @deprecated */
+  @Deprecated
+  public static void load(final Properties properties, final InputStream stream)
+      throws IOException {
+    final Document document;
+    try {
+      document = createDocument(stream);
+    } catch (final SAXException e) {
+      throw new RuntimeException("Invalid properties format", e);
+    }
+    final Element propertiesElement = (Element) document.getChildNodes().item(
+        document.getChildNodes().getLength() - 1);
+    importProperties(properties, propertiesElement);
+  }
+
+  private static Document createDocument(final InputStream stream)
+      throws SAXException, IOException {
+    final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+    factory.setIgnoringElementContentWhitespace(true);
+    factory.setValidating(false);
+    factory.setCoalescing(true);
+    factory.setIgnoringComments(true);
+    try {
+      final DocumentBuilder builder = factory.newDocumentBuilder();
+      builder.setEntityResolver(new Resolver());
+      final InputSource source = new InputSource(stream);
+      return builder.parse(source);
+    } catch (final ParserConfigurationException e) {
+      throw new Error(e);
+    }
+  }
+
+  static void importProperties(final Properties properties, final Element propertiesElement) {
+    final NodeList entries = propertiesElement.getChildNodes();
+    final int numEntries = entries.getLength();
+    final int start = numEntries > 0
+        && entries.item(0).getNodeName().equals("comment") ? 1 : 0;
+    for (int i = start; i < numEntries; i++) {
+      final Node child = entries.item(i);
+      if (child instanceof Element) {
+        final Element entry = (Element) child;
+        if (entry.hasAttribute("key")) {
+          final Node node = entry.getFirstChild();
+          final String value = (node == null) ? "" : node.getNodeValue();
+          properties.setProperty(entry.getAttribute("key"), value);
+        }
+      }
+    }
+  }
+
+  private static class Resolver implements EntityResolver {
+
+    @Override
+    public InputSource resolveEntity(final String publicId, final String systemId)
+        throws SAXException {
+      final String dtd = "<!ELEMENT properties (comment?, entry*)>"
+          + "<!ATTLIST properties version CDATA #FIXED '1.0'>"
+          + "<!ELEMENT comment (#PCDATA)>"
+          + "<!ELEMENT entry (#PCDATA)>"
+          + "<!ATTLIST entry key CDATA #REQUIRED>";
+      final InputSource inputSource = new InputSource(new StringReader(dtd));
+      inputSource.setSystemId("http://java.sun.com/dtd/properties.dtd");
+      return inputSource;
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/ClearValidatorsActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/ClearValidatorsActionListener.java
new file mode 100644
index 0000000..dcc3e32
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/ClearValidatorsActionListener.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.validator;
+
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.ActionListener;
+import javax.faces.event.PhaseId;
+import java.util.StringTokenizer;
+
+public class ClearValidatorsActionListener implements ActionListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ClearValidatorsActionListener.class);
+
+  public PhaseId getPhaseId() {
+    return PhaseId.APPLY_REQUEST_VALUES;
+  }
+
+  @Override
+  public void processAction(final ActionEvent actionEvent) throws AbortProcessingException {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("actionEvent = '" + actionEvent + "'");
+    }
+    final UIComponent source = actionEvent.getComponent();
+    final String clearValidatorsFieldIds
+        = (String) ComponentUtils.findParameter(source, "clearValidatorsFieldIds");
+
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("clearValidatorsFieldIds = '" + clearValidatorsFieldIds + "'");
+    }
+
+    // FIXME: finding mechanism??? JSF ???
+
+    for (final StringTokenizer tokenizer
+        = new StringTokenizer(clearValidatorsFieldIds, ",");
+         tokenizer.hasMoreTokens();) {
+      final String clearValidatorsFieldId = tokenizer.nextToken();
+
+      UIComponent component = source.findComponent(clearValidatorsFieldId);
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("component = '" + component + "'");
+      }
+
+      if (component == null) { // not found locally
+        if (LOG.isDebugEnabled()) {
+          LOG.debug("Component not found locally, asking the tree.");
+        }
+        final FacesContext facesContext = FacesContext.getCurrentInstance();
+        component = facesContext.getViewRoot().findComponent(clearValidatorsFieldId);
+      }
+
+      if (component == null) { // not found 
+        LOG.warn("Component not found.");
+      } else {
+//        component.clearValidators();
+        LOG.error("NO LONGER AVAILABLE: component.clearValidators();");
+      }
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/FileItemValidator.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/FileItemValidator.java
new file mode 100644
index 0000000..e5bd3c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/FileItemValidator.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.validator;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUIFile;
+import org.apache.myfaces.tobago.internal.util.ContentType;
+import org.apache.myfaces.tobago.util.MessageUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.StateHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+import javax.servlet.http.Part;
+import java.util.Arrays;
+
+/**
+ * <p><strong>FileItemValidator</strong> is a {@link Validator} that checks
+ * the FileItem in the value of the associated component.
+ */
+@org.apache.myfaces.tobago.apt.annotation.Validator(id = FileItemValidator.VALIDATOR_ID)
+public class FileItemValidator implements Validator, StateHolder {
+  public static final String VALIDATOR_ID = "org.apache.myfaces.tobago.FileItem";
+  public static final String SIZE_LIMIT_MESSAGE_ID = "org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT";
+  public static final String CONTENT_TYPE_MESSAGE_ID = "org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE";
+  private Integer maxSize = null;
+  private String[] contentType;
+  private boolean transientValue;
+
+  /**
+   * No-arg constructor used during restoreState
+   */
+  public FileItemValidator() {
+  }
+
+  @Override
+  public void validate(final FacesContext facesContext, final UIComponent component, final Object value)
+      throws ValidatorException {
+    if (value != null && component instanceof AbstractUIFile) {
+      final Part file = (Part) value;
+      if (maxSize != null && file.getSize() > maxSize) {
+        final FacesMessage facesMessage = MessageUtils.getMessage(
+            facesContext, facesContext.getViewRoot().getLocale(), FacesMessage.SEVERITY_ERROR,
+            SIZE_LIMIT_MESSAGE_ID, maxSize, component.getId());
+        throw new ValidatorException(facesMessage);
+      }
+      // Check only a valid file
+      if (file.getSize() > 0 && contentType != null && contentType.length > 0) {
+        boolean found = false;
+        for (final String contentTypeStr : contentType) {
+          if (ContentType.valueOf(contentTypeStr).match(ContentType.valueOf(file.getContentType()))) {
+            found = true;
+            break;
+          }
+        }
+        if (!found) {
+          final String message;
+          if (contentType.length == 1) {
+            message = contentType[0];
+          } else {
+            message = Arrays.toString(contentType);
+          }
+          final FacesMessage facesMessage = MessageUtils.getMessage(
+              facesContext, facesContext.getViewRoot().getLocale(), FacesMessage.SEVERITY_ERROR,
+              CONTENT_TYPE_MESSAGE_ID, message, component.getId());
+          throw new ValidatorException(facesMessage);
+        }
+      }
+    }
+  }
+
+  public int getMaxSize() {
+    return maxSize;
+  }
+
+  public void setMaxSize(final int maxSize) {
+    if (maxSize > 0) {
+      this.maxSize = maxSize;
+    }
+  }
+
+  public String[] getContentType() {
+    return contentType;
+  }
+
+  public void setContentType(final String[] contentType) {
+    this.contentType = contentType;
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] values = new Object[2];
+    values[0] = maxSize;
+    values[1] = contentType;
+    return values;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    final Object[] values = (Object[]) state;
+    maxSize = (Integer) values[0];
+    contentType = (String[]) values[1];
+  }
+
+  @Override
+  public boolean isTransient() {
+    return transientValue;
+  }
+
+  @Override
+  public void setTransient(final boolean newTransientValue) {
+    this.transientValue = newTransientValue;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/SubmittedValueLengthValidator.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/SubmittedValueLengthValidator.java
new file mode 100644
index 0000000..f0a333b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/validator/SubmittedValueLengthValidator.java
@@ -0,0 +1,144 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.validator;
+
+import org.apache.myfaces.tobago.apt.annotation.Validator;
+import org.apache.myfaces.tobago.util.MessageUtils;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.EditableValueHolder;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.LengthValidator;
+import javax.faces.validator.ValidatorException;
+
+/**
+ * <p><strong>SubmittedLengthValidator</strong> is a {@link Validator} that checks
+ * the number of characters in the submitted value of the
+ * associated component.
+ */
+@Validator(id = SubmittedValueLengthValidator.VALIDATOR_ID)
+public class SubmittedValueLengthValidator extends LengthValidator {
+  public static final String VALIDATOR_ID = "org.apache.myfaces.tobago.SubmittedValueLength";
+
+  private Integer minimum;
+  private Integer maximum;
+
+  public SubmittedValueLengthValidator() {
+  }
+
+  public SubmittedValueLengthValidator(final int maximum) {
+    setMaximum(maximum);
+  }
+
+  public SubmittedValueLengthValidator(final int maximum, final int minimum) {
+    setMaximum(maximum);
+    setMinimum(minimum);
+  }
+
+  @Override
+  public int getMinimum() {
+    return minimum != null ? minimum : 0;
+  }
+
+  @Override
+  public void setMinimum(final int minimum) {
+    if (minimum > 0) {
+      this.minimum = minimum;
+    }
+  }
+
+  @Override
+  public int getMaximum() {
+    return maximum != null ? maximum : 0;
+  }
+
+  @Override
+  public void setMaximum(final int maximum) {
+    if (maximum > 0) {
+      this.maximum = maximum;
+    }
+  }
+
+  @Override
+  public void validate(final FacesContext facesContext, final UIComponent uiComponent, final Object value)
+      throws ValidatorException {
+    if (value != null && uiComponent instanceof EditableValueHolder) {
+      final String submittedValue = ((EditableValueHolder) uiComponent).getSubmittedValue().toString();
+      if (maximum != null && submittedValue.length() > maximum) {
+        final Object[] args = {maximum, uiComponent.getId()};
+        final FacesMessage facesMessage = MessageUtils.getMessage(facesContext,
+            facesContext.getViewRoot().getLocale(), FacesMessage.SEVERITY_ERROR, MAXIMUM_MESSAGE_ID, args);
+        throw new ValidatorException(facesMessage);
+      }
+      if (minimum != null && submittedValue.length() < minimum) {
+        final Object[] args = {minimum, uiComponent.getId()};
+        final FacesMessage facesMessage = MessageUtils.getMessage(facesContext,
+            facesContext.getViewRoot().getLocale(), FacesMessage.SEVERITY_ERROR, MINIMUM_MESSAGE_ID, args);
+        throw new ValidatorException(facesMessage);
+      }
+    }
+  }
+
+  @Override
+  public Object saveState(final FacesContext context) {
+    final Object[] values = new Object[2];
+    values[0] = maximum;
+    values[1] = minimum;
+    return values;
+  }
+
+  @Override
+  public void restoreState(final FacesContext context, final Object state) {
+    final Object[] values = (Object[]) state;
+    maximum = (Integer) values[0];
+    minimum = (Integer) values[1];
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+    if (!super.equals(o)) {
+      return false;
+    }
+
+    final SubmittedValueLengthValidator validator = (SubmittedValueLengthValidator) o;
+
+    if (maximum != null ? !maximum.equals(validator.maximum) : validator.maximum != null) {
+      return false;
+    }
+    if (minimum != null ? !minimum.equals(validator.minimum) : validator.minimum != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public int hashCode() {
+    int result;
+    result = (minimum != null ? minimum.hashCode() : 0);
+    result = 31 * result + (maximum != null ? maximum.hashCode() : 0);
+    return result;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/LogoutActionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/LogoutActionListener.java
new file mode 100644
index 0000000..15a2401
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/LogoutActionListener.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.webapp;
+
+import org.apache.myfaces.tobago.portlet.PortletUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.ActionListener;
+import javax.portlet.PortletSession;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+public class LogoutActionListener implements ActionListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(LogoutActionListener.class);
+
+  @Override
+  public void processAction(final ActionEvent event) throws AbortProcessingException {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    final Object session = externalContext.getSession(false);
+    if (session != null) {
+      if (session instanceof HttpSession) {
+        ((HttpSession) session).invalidate();
+      }
+      if (PortletUtils.isPortletApiAvailable() && session instanceof PortletSession) {
+        ((PortletSession) session).invalidate();
+      }
+    }
+    final String forward = externalContext.getRequestContextPath() + "/";
+    try {
+      externalContext.redirect(forward);
+    } catch (final IOException e) {
+      LOG.error("", e);
+      // TODO: may do error handling
+      throw new FacesException("Can't redirect to '" + forward + "'");
+    }
+    facesContext.responseComplete();
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/Secret.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/Secret.java
new file mode 100644
index 0000000..00dce79
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/Secret.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.webapp;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.myfaces.tobago.portlet.PortletUtils;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+
+import javax.faces.context.FacesContext;
+import javax.portlet.PortletSession;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+import java.io.Serializable;
+import java.security.SecureRandom;
+import java.util.Map;
+
+public final class Secret implements Serializable {
+
+  private static final long serialVersionUID = 1L;
+
+  private static final String KEY = Secret.class.getName();
+
+  private static final SecureRandom RANDOM = new SecureRandom();
+
+  private static final int SECRET_LENGTH = 16;
+
+  private static final boolean COMMONS_CODEC_AVAILABLE = commonsCodecAvailable();
+
+  private static boolean commonsCodecAvailable() {
+    try {
+      Base64.encodeBase64URLSafeString(new byte[0]);
+      return true;
+    } catch (final Error e) {
+      return false;
+    }
+  }
+
+  private String secret;
+
+  private Secret() {
+    final byte[] bytes = new byte[SECRET_LENGTH];
+    RANDOM.nextBytes(bytes);
+    secret = COMMONS_CODEC_AVAILABLE ? encodeBase64(bytes) : encodeHex(bytes);
+  }
+
+  private String encodeBase64(final byte[] bytes) {
+    return Base64.encodeBase64URLSafeString(bytes);
+  }
+
+  private String encodeHex(final byte[] bytes) {
+    final StringBuilder builder = new StringBuilder(SECRET_LENGTH * 2);
+    for (final byte b : bytes) {
+      builder.append(String.format("%02x", b));
+    }
+    return builder.toString();
+  }
+
+  /**
+   * Checks that the request contains a parameter {@link org.apache.myfaces.tobago.webapp.Secret#KEY}
+   * which is equals to a secret value in the session.
+   */
+  public static boolean check(final FacesContext facesContext) {
+    final Map requestParameterMap = facesContext.getExternalContext().getRequestParameterMap();
+    final String fromRequest = (String) requestParameterMap.get(Secret.KEY);
+    final Object session = facesContext.getExternalContext().getSession(false);
+    Secret secret = getSecret(session);
+    return secret != null && secret.secret.equals(fromRequest);
+  }
+
+  private static Secret getSecret(Object session) {
+    Secret secret = null;
+    if (session!=null) {
+      if (session instanceof HttpSession) {
+        secret = (Secret) ((HttpSession) session).getAttribute(Secret.KEY);
+      } else if (PortletUtils.isPortletApiAvailable() && session instanceof PortletSession) {
+        secret = (Secret) ((PortletSession) session).getAttribute(Secret.KEY, PortletSession.APPLICATION_SCOPE);
+      } else {
+        throw new IllegalArgumentException("Unknown session type: " + session);
+      }
+    }
+    return secret;
+  }
+
+  /**
+   * Encode a hidden field with the secret value from the session.
+   */
+  public static void encode(final FacesContext facesContext, final TobagoResponseWriter writer) throws IOException {
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+    writer.writeAttribute(HtmlAttributes.NAME, Secret.KEY, false);
+    writer.writeAttribute(HtmlAttributes.ID, Secret.KEY, false);
+    final Object session = facesContext.getExternalContext().getSession(true);
+    final Secret secret = getSecret(session);
+    if (secret != null) {
+      writer.writeAttribute(HtmlAttributes.VALUE, secret.secret, false);
+    }
+    writer.endElement(HtmlElements.INPUT);
+  }
+
+  /**
+   * Create a secret attribute in the session.
+   * Should usually be called in a {@link javax.servlet.http.HttpSessionListener}.
+   */
+  public static void create(final HttpSession session) {
+    session.setAttribute(Secret.KEY, new Secret());
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/SecretSessionListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/SecretSessionListener.java
new file mode 100644
index 0000000..ee557c0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/SecretSessionListener.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.webapp;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+public class SecretSessionListener implements HttpSessionListener {
+
+  @Override
+  public void sessionCreated(final HttpSessionEvent sessionEvent) {
+    // a session creation may happen outside from JSF 
+    if (TobagoConfig.getInstance(sessionEvent.getSession().getServletContext()).isCreateSessionSecret()) {
+      Secret.create(sessionEvent.getSession());
+    }
+  }
+
+  @Override
+  public void sessionDestroyed(final HttpSessionEvent se) {
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
new file mode 100644
index 0000000..e6867a0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriter.java
@@ -0,0 +1,317 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.webapp;
+
+import org.apache.myfaces.tobago.renderkit.css.CssItem;
+import org.apache.myfaces.tobago.renderkit.css.FontAwesomeIconEncoder;
+import org.apache.myfaces.tobago.renderkit.css.IconEncoder;
+import org.apache.myfaces.tobago.renderkit.css.Icons;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlTypes;
+import org.apache.myfaces.tobago.renderkit.html.MarkupLanguageAttributes;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.ResponseWriter;
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * <p>
+ * This provides an alternative ResponseWriter interfaces, which allows optimizations.
+ * E. g. some attributes needed to to be escaped.
+ * </p>
+ */
+public abstract class TobagoResponseWriter extends ResponseWriter {
+
+  private static final CssItem[] NO_CSS_ITEMS = new CssItem[0];
+
+  private IconEncoder iconEncoder = new FontAwesomeIconEncoder();
+
+  // same as in ResponseWriter
+
+  /**
+   * @deprecated Should not directly called via this interface. There is be a special method which might be better.
+   */
+  @Deprecated
+  @Override
+  public abstract void startElement(String name, UIComponent component) throws IOException;
+
+  public abstract void startElement(HtmlElements name) throws IOException;
+
+  /**
+   * @deprecated Should not directly called via this interface. There is be a special method which might be better.
+   */
+  @Deprecated
+  @Override
+  public abstract void endElement(String name) throws IOException;
+    
+  public abstract void endElement(HtmlElements name) throws IOException;
+
+  @Override
+  public abstract void write(String string) throws IOException;
+
+  @Override
+  public abstract void writeComment(Object comment) throws IOException;
+
+  @Override
+  public abstract ResponseWriter cloneWithWriter(Writer writer);
+
+  /**
+   * @deprecated Should not directly called via this interface. There is be a special method which might be better.
+   */
+  @Override
+  @Deprecated
+  public abstract void writeAttribute(String name, Object value, final String property) throws IOException;
+
+  /**
+   * @deprecated Should not directly called via this interface. There is be a special method which might be better.
+   */
+  @Override
+  @Deprecated
+  public abstract void writeURIAttribute(String name, Object value, final String property) throws IOException;
+
+  /**
+   * @deprecated Should not directly called via this interface. There is be a special method which might be better.
+   */
+  @Override
+  @Deprecated
+  public abstract void writeText(Object text, String property) throws IOException;
+
+  @Override
+  public abstract void flush() throws IOException;
+
+  // others (not from ResponseWriter)
+
+  /**
+   * Writes a string attribute. The renderer may set escape=false to switch of escaping of the string,
+   * if it is not necessary.
+   */
+  public abstract void writeAttribute(MarkupLanguageAttributes name, String string, boolean escape) throws IOException;
+
+  public abstract void writeAttribute(MarkupLanguageAttributes name, HtmlTypes type) throws IOException;
+
+  /**
+   * Writes a string attribute URL encoded.
+   */
+  public abstract void writeURIAttribute(MarkupLanguageAttributes name, String string) throws IOException;
+
+  /**
+   * Writes a boolean attribute. The value will not escaped.
+   */
+  public void writeAttribute(final MarkupLanguageAttributes name, final boolean on) throws IOException {
+    if (on) {
+      writeAttribute(name, name.getValue(), false);
+    }
+  }
+
+  /**
+   * Writes a {@link Integer} attribute, if the value is not {@code null}. The value will not be escaped.
+   */
+  public void writeAttribute(final MarkupLanguageAttributes name, final Integer number) throws IOException {
+    if (number != null) {
+      writeAttribute(name, Integer.toString(number), false);
+    }
+  }
+
+  /**
+   * Write the id attribute. The value will not escaped.
+   */
+  public void writeIdAttribute(final String id) throws IOException {
+    writeAttribute(HtmlAttributes.ID, id, false);
+  }
+
+  /**
+   * Write the name attribute. The value will not escaped.
+   */
+  public void writeNameAttribute(final String name) throws IOException {
+    writeAttribute(HtmlAttributes.NAME, name, false);
+  }
+
+  /**
+   * Write the class attribute. The value will not escaped.
+   */
+  public void writeClassAttribute(final CssItem first) throws IOException {
+    if (first != null) {
+      // todo: optimize me, do not use StringBuilder
+      final StringBuilder builder = new StringBuilder();
+      builder.append(first.getName());
+      builder.append(' ');
+      writeAttribute(HtmlAttributes.CLASS, builder.deleteCharAt(builder.length() - 1).toString(), false);
+    }
+  }
+
+  /**
+   * Write the command map data attribute.
+   */
+  public void writeCommandMapAttribute(final String map) throws IOException { // XXX use CommandMap instead of String
+    if (map != null) {
+      // XXX
+      writeAttribute(DataAttributes.COMMANDS, map, true);
+    }
+  }
+
+  /**
+   * Write the class attribute. The value will not escaped.
+   */
+  public void writeClassAttribute(final CssItem first, final CssItem second) throws IOException {
+    final StringBuilder builder = new StringBuilder();
+    boolean render = false;
+    if (first != null) {
+      builder.append(first.getName());
+      builder.append(' ');
+      render = true;
+    }
+    if (second != null) {
+      builder.append(second.getName());
+      builder.append(' ');
+      render = true;
+    }
+    if (render) {
+      writeAttribute(HtmlAttributes.CLASS, builder.deleteCharAt(builder.length() - 1).toString(), false);
+    }
+  }
+
+  /**
+   * Write the class attribute. The value will not escaped.
+   */
+  public void writeClassAttribute(final CssItem first, final CssItem second, final CssItem... others)
+      throws IOException {
+    final StringBuilder builder = new StringBuilder();
+    boolean render = false;
+    if (first != null) {
+      builder.append(first.getName());
+      builder.append(' ');
+      render = true;
+    }
+    if (second != null) {
+      builder.append(second.getName());
+      builder.append(' ');
+      render = true;
+    }
+    for (CssItem other : others) {
+      if (other != null) {
+        builder.append(other.getName());
+        builder.append(' ');
+        render = true;
+      }
+    }
+    if (render) {
+      writeAttribute(HtmlAttributes.CLASS, builder.deleteCharAt(builder.length() - 1).toString(), false);
+    }
+  }
+
+  /**
+   * Write the style attribute. The value may be escaped (depending of the content).
+   */
+  public void writeStyleAttribute(final Style style) throws IOException {
+    if (style != null) {
+      final String json = style.encodeJson();
+      if (json.length() > 2) { // empty "{}" needs not to be written
+        writeAttribute(DataAttributes.STYLE, json, style.needsToBeEscaped());
+      }
+    }
+  }
+
+  /**
+   * Write the style attribute. The value will not escaped.
+   * @deprecated since 1.5.0, use writeStyleAttribute(Style) instead.
+   */
+  @Deprecated
+  public void writeStyleAttribute(final String style) throws IOException {
+    writeAttribute(HtmlAttributes.STYLE, style, false);
+  }
+
+  /**
+   * Writes an supported icon.
+   */
+  public void writeIcon(final Icons icon, final CssItem... cssItems) throws IOException {
+    writeIcon(icon, null, cssItems);
+  }
+
+  /**
+   * Writes an supported icon with explicit style information.
+   */
+  public void writeIcon(final Icons icon, final Style style, final CssItem... cssItems) throws IOException {
+    iconEncoder.encode(this, icon, style, cssItems);
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  public void writeJavascript(final String script) throws IOException {
+    startJavascript();
+    write(script);
+    endJavascript();
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  public void endJavascript() throws IOException {
+//    write("\n// -->\n"); // todo: for XHMTL we may need
+    endElement(HtmlElements.SCRIPT);
+  }
+
+  /**
+   * @deprecated Should not be used, because it conflicts with CSP.
+   */
+  @Deprecated
+  public void startJavascript() throws IOException {
+    startElement(HtmlElements.SCRIPT);
+    writeAttribute(HtmlAttributes.TYPE, "text/javascript", false);
+  }
+
+  /**
+   * Write text content. The text will be escaped.
+   */
+  public void writeText(final String text) throws IOException {
+    writeText(text, null);
+  }
+
+  public String getContentTypeWithCharSet() {
+    String contentType = getContentType();
+    if (contentType == null) {
+      contentType = "text/html";
+    }
+    String characterEncoding = getCharacterEncoding();
+    if (characterEncoding == null) {
+      characterEncoding = "UTF-8";
+    }
+
+    return contentType + "; charset=" + characterEncoding;
+  }
+
+  @Override
+  public void startCDATA() throws IOException {
+    write("<![CDATA[");
+  }
+
+  @Override
+  public void endCDATA() throws IOException {
+    write("]]>");
+  }
+
+//  protected abstract void writeNewline() throws IOException;
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoServletContextListener.java b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoServletContextListener.java
new file mode 100644
index 0000000..eb815a7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/java/org/apache/myfaces/tobago/webapp/TobagoServletContextListener.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.webapp;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.internal.config.ContentSecurityPolicy;
+import org.apache.myfaces.tobago.internal.config.TobagoConfigBuilder;
+import org.apache.myfaces.tobago.internal.util.MimeTypeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletContext;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+
+public class TobagoServletContextListener implements ServletContextListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TobagoServletContextListener.class);
+
+  @Override
+  public void contextInitialized(final ServletContextEvent event) {
+
+    if (LOG.isInfoEnabled()) {
+      LOG.info("*** contextInitialized ***");
+    }
+
+    final ServletContext servletContext = event.getServletContext();
+
+    if (servletContext.getAttribute(TobagoConfig.TOBAGO_CONFIG) != null) {
+      LOG.warn("Tobago has been already initialized. Do nothing.");
+      return;
+    }
+
+    TobagoConfigBuilder.init(servletContext);
+    if (LOG.isInfoEnabled()) {
+      final TobagoConfig tobagoConfig = TobagoConfig.getInstance(servletContext);
+      LOG.info("TobagoConfig: " + tobagoConfig);
+
+      MimeTypeUtils.init(servletContext);
+
+      final ContentSecurityPolicy.Mode mode = tobagoConfig.getContentSecurityPolicy().getMode();
+      final StringBuilder builder = new StringBuilder();
+      builder.append("\n*************************************************************************************");
+      builder.append("\nNote: CSP is ");
+      builder.append(mode);
+      if (mode == ContentSecurityPolicy.Mode.ON) {
+        builder.append("\nYou may need to check application specific JavaScript code.");
+        builder.append("\nOtherwise the application will not run in modern browsers, that are supporting CSP.");
+        builder.append("\nFor more information see http://myfaces.apache.org/tobago/migration-2.0.html");
+      }
+      builder.append("\n*************************************************************************************");
+      final String note = builder.toString();
+      LOG.info(note);
+    }
+  }
+
+  @Override
+  public void contextDestroyed(final ServletContextEvent event) {
+    if (LOG.isInfoEnabled()) {
+      LOG.info("*** contextDestroyed ***\n--- snip ---------"
+          + "--------------------------------------------------------------");
+    }
+
+    final ServletContext servletContext = event.getServletContext();
+
+    servletContext.removeAttribute(TobagoConfig.TOBAGO_CONFIG);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/META-INF/web-fragment.xml b/tobago-3.0.x/tobago-core/src/main/resources/META-INF/web-fragment.xml
new file mode 100644
index 0000000..cc64359
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/META-INF/web-fragment.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<web-fragment
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd"
+    version="3.0">
+
+  <name>tobago_core</name>
+
+<!--
+  <ordering>
+    <after>
+      <others/>
+    </after>
+  </ordering>
+-->
+
+  <listener>
+    <listener-class>org.apache.myfaces.tobago.webapp.TobagoServletContextListener</listener-class>
+  </listener>
+  <listener>
+    <listener-class>org.apache.myfaces.tobago.webapp.SecretSessionListener</listener-class>
+  </listener>
+
+</web-fragment>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.29.dtd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.29.dtd
new file mode 100644
index 0000000..5034901
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.29.dtd
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+  This is the DTD for the tobago configuration files version 1.0.29.
+  You should use the following DOCTYPE in your tobago-config.xml:
+
+  <!DOCTYPE tobago-config PUBLIC
+      "-//The Apache Software Foundation//DTD Tobago Config 1.0.29//EN"
+      "http://myfaces.apache.org/tobago/tobago-config-1.0.29.dtd">
+-->
+
+<!ENTITY % Boolean "(true|false|yes|no)">
+
+<!ELEMENT tobago-config (theme-config, resource-dir*, ajax-enabled?, fix-resource-order?, renderers?)>
+
+<!ELEMENT theme-config (default-theme, supported-theme*)>
+<!ELEMENT default-theme (#PCDATA)>
+<!ELEMENT supported-theme (#PCDATA)>
+
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT display-name (#PCDATA)>
+<!ELEMENT fallback (#PCDATA)>
+
+<!ELEMENT resource-dir (#PCDATA)>
+
+<!ELEMENT ajax-enabled (#PCDATA)>
+
+<!ELEMENT fix-resource-order (#PCDATA)>
+
+<!ELEMENT renderers (renderer)*>
+<!ELEMENT renderer (name|supported-markup)*>
+<!ELEMENT supported-markup (markup)*>
+<!ELEMENT markup (#PCDATA)>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.30.dtd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.30.dtd
new file mode 100644
index 0000000..4f64d8d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.30.dtd
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+  This is the DTD for the tobago configuration files version 1.0.30.
+  You should use the following DOCTYPE in your tobago-config.xml:
+
+  <!DOCTYPE tobago-config PUBLIC
+      "-//The Apache Software Foundation//DTD Tobago Config 1.0.30//EN"
+      "http://myfaces.apache.org/tobago/tobago-config-1.0.30.dtd">
+-->
+
+<!ENTITY % Boolean "(true|false|yes|no)">
+
+<!ELEMENT tobago-config (theme-config, resource-dir*,
+    ajax-enabled?, fix-resource-order?, fix-layout-transparency?, renderers?)>
+
+<!ELEMENT theme-config (default-theme, supported-theme*)>
+<!ELEMENT default-theme (#PCDATA)>
+<!ELEMENT supported-theme (#PCDATA)>
+
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT display-name (#PCDATA)>
+<!ELEMENT fallback (#PCDATA)>
+
+<!ELEMENT resource-dir (#PCDATA)>
+
+<!ELEMENT ajax-enabled (#PCDATA)>
+
+<!ELEMENT fix-resource-order (#PCDATA)>
+
+<!--
+  UIParameter, UIHiddenInput and UIInstruction (from the <?xml ...> declaration when using facelets)
+  should not be part of the layout.
+  You have to enable this behavior, because of backward compatibility.
+  For Tobago 1.5 this will be the normal behavior and this configuration entry will be removed.
+ -->
+<!ELEMENT fix-layout-transparency (#PCDATA)>
+
+<!ELEMENT renderers (renderer)*>
+<!ELEMENT renderer (name|supported-markup)*>
+<!ELEMENT supported-markup (markup)*>
+<!ELEMENT markup (#PCDATA)>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.34.dtd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.34.dtd
new file mode 100644
index 0000000..d132088
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.0.34.dtd
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+  This is the DTD for the tobago configuration files version 1.0.34.
+  You should use the following DOCTYPE in your tobago-config.xml:
+
+  <!DOCTYPE tobago-config PUBLIC
+      "-//The Apache Software Foundation//DTD Tobago Config 1.0.34//EN"
+      "http://myfaces.apache.org/tobago/tobago-config-1.0.34.dtd">
+-->
+
+<!ENTITY % Boolean "(true|false|yes|no)">
+
+<!ELEMENT tobago-config (theme-config, resource-dir*,
+    ajax-enabled?, fix-resource-order?, fix-layout-transparency?,
+    create-session-secret?, check-session-secret?, renderers?)>
+
+<!ELEMENT theme-config (default-theme, supported-theme*)>
+<!ELEMENT default-theme (#PCDATA)>
+<!ELEMENT supported-theme (#PCDATA)>
+
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT display-name (#PCDATA)>
+<!ELEMENT fallback (#PCDATA)>
+
+<!ELEMENT resource-dir (#PCDATA)>
+
+<!ELEMENT ajax-enabled (#PCDATA)>
+
+<!ELEMENT fix-resource-order (#PCDATA)>
+
+<!--
+  UIParameter, UIHiddenInput and UIInstruction (from the <?xml ...> declaration when using facelets)
+  should not be part of the layout.
+  You have to enable this behavior, because of backward compatibility.
+  For Tobago 1.5 this will be the normal behavior and this configuration entry will be removed.
+ -->
+<!ELEMENT fix-layout-transparency (#PCDATA)>
+
+<!ELEMENT create-session-secret (#PCDATA)>
+<!ELEMENT check-session-secret (#PCDATA)>
+
+<!ELEMENT renderers (renderer)*>
+<!ELEMENT renderer (name|supported-markup)*>
+<!ELEMENT supported-markup (markup)*>
+<!ELEMENT markup (#PCDATA)>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.5.xsd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.5.xsd
new file mode 100644
index 0000000..5fdd9040
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.5.xsd
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema
+    targetNamespace="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:tobago="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    xmlns:xml="http://www.w3.org/XML/1998/namespace"
+    elementFormDefault="qualified"
+    attributeFormDefault="unqualified"
+    version="1.5">
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      Licensed to the Apache Software Foundation (ASF) under one or more
+      contributor license agreements.  See the NOTICE file distributed with
+      this work for additional information regarding copyright ownership.
+      The ASF licenses this file to You under the Apache License, Version 2.0
+      (the "License"); you may not use this file except in compliance with
+      the License.  You may obtain a copy of the License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      This is the XML schema for the tobago configuration files version 1.5.
+
+      Use the following definition:
+
+      <tobago-config
+          xmlns="http://myfaces.apache.org/tobago/tobago-config"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-1.5.xsd"
+          version="1.5">
+        ...
+      </tobago-config>
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="tobago-config" type="tobago:tobago-config-type"/>
+
+  <xs:complexType name="tobago-config-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" minOccurs="0"/>
+      <xs:element name="ordering" type="tobago:ordering-type" minOccurs="0"/>
+      <xs:element name="theme-config" type="tobago:theme-config-type" minOccurs="0"/>
+      <xs:element name="resource-dir" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="create-session-secret" type="xs:boolean" minOccurs="0"/>
+      <xs:element name="check-session-secret" type="xs:boolean" minOccurs="0"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="theme-definitions" type="tobago:theme-definitions-type" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="version"
+                   type="tobago:tobago-config-version-type"
+                   use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="tobago-config-version-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="1.5"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="ordering-type">
+    <xs:sequence>
+      <xs:element name="after" type="tobago:before-after-type" minOccurs="0"/>
+      <xs:element name="before" type="tobago:before-after-type" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="before-after-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-config-type">
+    <xs:sequence>
+      <xs:element name="default-theme" type="xs:string"/>
+      <xs:element name="supported-theme" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="renderers-type">
+    <xs:sequence>
+      <xs:element name="renderer" type="tobago:renderer-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="renderer-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="supported-markup" type="tobago:supported-markup-type"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="supported-markup-type">
+    <xs:sequence>
+      <xs:element name="markup" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definitions-type">
+    <xs:sequence>
+      <xs:element name="theme-definition" type="tobago:theme-definition-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definition-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="display-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="deprecated-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="resource-path" type="xs:string"/>
+      <xs:element name="fallback" type="xs:string" minOccurs="0"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="resources" type="tobago:resources-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="resources-type">
+    <xs:sequence>
+      <xs:element name="script" type="tobago:script-type" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="style" type="tobago:style-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="production" type="xs:boolean" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="script-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="style-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="name-type">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+</xs:schema>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd
new file mode 100644
index 0000000..fa7f6be
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-1.6.xsd
@@ -0,0 +1,168 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema
+    targetNamespace="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:tobago="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    elementFormDefault="qualified"
+    attributeFormDefault="unqualified"
+    version="1.6">
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      Licensed to the Apache Software Foundation (ASF) under one or more
+      contributor license agreements.  See the NOTICE file distributed with
+      this work for additional information regarding copyright ownership.
+      The ASF licenses this file to You under the Apache License, Version 2.0
+      (the "License"); you may not use this file except in compliance with
+      the License.  You may obtain a copy of the License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+
+      ************************************************************************************
+      ************************************************************************************
+      Warning: This version is not officially release, please use version 2.0!
+      http://myfaces.apache.org/tobago/tobago-config-2.0.xsd
+      ************************************************************************************
+      ************************************************************************************
+
+      This is the XML schema for the tobago configuration files version 1.6.
+
+      Use the following definition:
+
+      <tobago-config
+          xmlns="http://myfaces.apache.org/tobago/tobago-config"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-1.6.xsd"
+          version="1.6">
+        ...
+      </tobago-config>
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="tobago-config" type="tobago:tobago-config-type"/>
+
+  <xs:complexType name="tobago-config-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" minOccurs="0"/>
+      <xs:element name="ordering" type="tobago:ordering-type" minOccurs="0"/>
+      <xs:element name="theme-config" type="tobago:theme-config-type" minOccurs="0"/>
+      <xs:element name="resource-dir" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="create-session-secret" type="xs:boolean" minOccurs="0"/>
+      <xs:element name="check-session-secret" type="xs:boolean" minOccurs="0"/>
+      <xs:element name="prevent-frame-attacks" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="content-security-policy" type="tobago:content-security-policy-type" minOccurs="0"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="theme-definitions" type="tobago:theme-definitions-type" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="version"
+                   type="tobago:tobago-config-version-type"
+                   use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="tobago-config-version-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="1.6"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="ordering-type">
+    <xs:sequence>
+      <xs:element name="after" type="tobago:before-after-type" minOccurs="0"/>
+      <xs:element name="before" type="tobago:before-after-type" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="before-after-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-config-type">
+    <xs:sequence>
+      <xs:element name="default-theme" type="xs:string"/>
+      <xs:element name="supported-theme" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="content-security-policy-type">
+    <xs:sequence>
+      <xs:element name="directive" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="renderers-type">
+    <xs:sequence>
+      <xs:element name="renderer" type="tobago:renderer-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="renderer-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="supported-markup" type="tobago:supported-markup-type"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="supported-markup-type">
+    <xs:sequence>
+      <xs:element name="markup" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definitions-type">
+    <xs:sequence>
+      <xs:element name="theme-definition" type="tobago:theme-definition-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definition-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="display-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="deprecated-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="resource-path" type="xs:string"/>
+      <xs:element name="fallback" type="xs:string" minOccurs="0"/>
+      <xs:element name="versioned" type="xs:boolean" minOccurs="0" default="false"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="resources" type="tobago:resources-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="resources-type">
+    <xs:sequence>
+      <xs:element name="script" type="tobago:script-type" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="style" type="tobago:style-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="production" type="xs:boolean" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="script-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="style-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="name-type">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+</xs:schema>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-2.0.6.xsd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-2.0.6.xsd
new file mode 100644
index 0000000..cddb900
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-2.0.6.xsd
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema
+    targetNamespace="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:tobago="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    elementFormDefault="qualified"
+    attributeFormDefault="unqualified"
+    version="2.0.6">
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      Licensed to the Apache Software Foundation (ASF) under one or more
+      contributor license agreements.  See the NOTICE file distributed with
+      this work for additional information regarding copyright ownership.
+      The ASF licenses this file to You under the Apache License, Version 2.0
+      (the "License"); you may not use this file except in compliance with
+      the License.  You may obtain a copy of the License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      ************************************************************************************
+      ************************************************************************************
+      WARNING
+      THIS IS A PRE-RELEASE VERSION OF THIS FILE, PLEASE CHECK IF THERE IS AN UPDATE ON
+      http://myfaces.apache.org/tobago/tobago-config-2.0.xsd
+      ************************************************************************************
+      ************************************************************************************
+
+      This is the XML schema for the Tobago configuration files version 2.0.
+
+      Use the following definition:
+
+      <tobago-config
+          xmlns="http://myfaces.apache.org/tobago/tobago-config"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+          version="2.0">
+        ...
+      </tobago-config>
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="tobago-config" type="tobago:tobago-config-type"/>
+
+  <xs:complexType name="tobago-config-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" minOccurs="0"/>
+      <xs:element name="ordering" type="tobago:ordering-type" minOccurs="0"/>
+      <xs:element name="theme-config" type="tobago:theme-config-type" minOccurs="0"/>
+      <xs:element name="resource-dir" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="create-session-secret" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="check-session-secret" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="prevent-frame-attacks" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="set-nosniff-header" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="auto-access-key-from-label" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="classic-date-time-picker" type="xs:boolean" minOccurs="0" default="false"/>
+      <xs:element name="content-security-policy" type="tobago:content-security-policy-type" minOccurs="0"/>
+      <xs:element name="sanitizer" type="tobago:sanitizer-type" minOccurs="0"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="theme-definitions" type="tobago:theme-definitions-type" minOccurs="0"/>
+      <xs:element name="mime-types" type="tobago:mime-types-type" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="version"
+                  type="tobago:tobago-config-version-type"
+                  use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="tobago-config-version-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="2.0.6"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="ordering-type">
+    <xs:sequence>
+      <xs:element name="after" type="tobago:before-after-type" minOccurs="0"/>
+      <xs:element name="before" type="tobago:before-after-type" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="before-after-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-config-type">
+    <xs:sequence>
+      <xs:element name="default-theme" type="xs:string"/>
+      <xs:element name="supported-theme" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="content-security-policy-type">
+    <xs:sequence>
+      <xs:element name="directive" type="xs:string" maxOccurs="unbounded" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="mode" type="tobago:scp-mode-type" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="sanitizer-type">
+    <xs:sequence>
+      <xs:element name="sanitizer-class" type="xs:string" maxOccurs="1" minOccurs="1"/>
+      <xs:element name="properties" type="tobago:properties-type" maxOccurs="1" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:simpleType name="scp-mode-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="on"/>
+      <xs:enumeration value="off"/>
+      <xs:enumeration value="report-only"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="renderers-type">
+    <xs:sequence>
+      <xs:element name="renderer" type="tobago:renderer-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="renderer-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="supported-markup" type="tobago:supported-markup-type"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="supported-markup-type">
+    <xs:sequence>
+      <xs:element name="markup" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definitions-type">
+    <xs:sequence>
+      <xs:element name="theme-definition" type="tobago:theme-definition-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definition-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="display-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="resource-path" type="xs:string"/>
+      <xs:element name="fallback" type="xs:string" minOccurs="0"/>
+      <xs:element name="versioned" type="xs:boolean" minOccurs="0" default="false"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="resources" type="tobago:resources-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="resources-type">
+    <xs:sequence>
+      <xs:element name="script" type="tobago:script-type" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="style" type="tobago:style-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="production" type="xs:boolean" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="script-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="style-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="name-type">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:complexType name="properties-type">
+    <xs:sequence>
+      <xs:element name="entry" type="tobago:entry-type" maxOccurs="unbounded" minOccurs="1"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="entry-type">
+    <xs:simpleContent>
+      <xs:extension base="xs:string">
+        <xs:attribute name="key" type="xs:string" use="required"/>
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+  <xs:complexType name="mime-types-type">
+    <xs:sequence>
+      <xs:element name="mime-type" type="tobago:mime-type-type" minOccurs="1" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="mime-type-type">
+    <xs:sequence>
+      <xs:element name="extension" type="xs:string"/>
+      <xs:element name="type" type="xs:string"/>
+    </xs:sequence>
+  </xs:complexType>
+
+</xs:schema>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-2.0.xsd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-2.0.xsd
new file mode 100644
index 0000000..74d7087
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-2.0.xsd
@@ -0,0 +1,201 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema
+    targetNamespace="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:tobago="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    elementFormDefault="qualified"
+    attributeFormDefault="unqualified"
+    version="2.0">
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      Licensed to the Apache Software Foundation (ASF) under one or more
+      contributor license agreements.  See the NOTICE file distributed with
+      this work for additional information regarding copyright ownership.
+      The ASF licenses this file to You under the Apache License, Version 2.0
+      (the "License"); you may not use this file except in compliance with
+      the License.  You may obtain a copy of the License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      ************************************************************************************
+      ************************************************************************************
+      WARNING
+      THIS IS A PRE-RELEASE VERSION OF THIS FILE, PLEASE CHECK IF THERE IS AN UPDATE ON
+      http://myfaces.apache.org/tobago/tobago-config-2.0.xsd
+      ************************************************************************************
+      ************************************************************************************
+
+      This is the XML schema for the Tobago configuration files version 2.0.
+
+      Use the following definition:
+
+      <tobago-config
+          xmlns="http://myfaces.apache.org/tobago/tobago-config"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+          version="2.0">
+        ...
+      </tobago-config>
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="tobago-config" type="tobago:tobago-config-type"/>
+
+  <xs:complexType name="tobago-config-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" minOccurs="0"/>
+      <xs:element name="ordering" type="tobago:ordering-type" minOccurs="0"/>
+      <xs:element name="theme-config" type="tobago:theme-config-type" minOccurs="0"/>
+      <xs:element name="resource-dir" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="create-session-secret" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="check-session-secret" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="prevent-frame-attacks" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="set-nosniff-header" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="auto-access-key-from-label" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="classic-date-time-picker" type="xs:boolean" minOccurs="0" default="false"/>
+      <xs:element name="content-security-policy" type="tobago:content-security-policy-type" minOccurs="0"/>
+      <xs:element name="sanitizer" type="tobago:sanitizer-type" minOccurs="0"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="theme-definitions" type="tobago:theme-definitions-type" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="version"
+                  type="tobago:tobago-config-version-type"
+                  use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="tobago-config-version-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="2.0"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="ordering-type">
+    <xs:sequence>
+      <xs:element name="after" type="tobago:before-after-type" minOccurs="0"/>
+      <xs:element name="before" type="tobago:before-after-type" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="before-after-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-config-type">
+    <xs:sequence>
+      <xs:element name="default-theme" type="xs:string"/>
+      <xs:element name="supported-theme" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="content-security-policy-type">
+    <xs:sequence>
+      <xs:element name="directive" type="xs:string" maxOccurs="unbounded" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="mode" type="tobago:scp-mode-type" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="sanitizer-type">
+    <xs:sequence>
+      <xs:element name="sanitizer-class" type="xs:string" maxOccurs="1" minOccurs="1"/>
+      <xs:element name="properties" type="tobago:properties-type" maxOccurs="1" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:simpleType name="scp-mode-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="on"/>
+      <xs:enumeration value="off"/>
+      <xs:enumeration value="report-only"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="renderers-type">
+    <xs:sequence>
+      <xs:element name="renderer" type="tobago:renderer-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="renderer-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="supported-markup" type="tobago:supported-markup-type"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="supported-markup-type">
+    <xs:sequence>
+      <xs:element name="markup" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definitions-type">
+    <xs:sequence>
+      <xs:element name="theme-definition" type="tobago:theme-definition-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definition-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="display-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="resource-path" type="xs:string"/>
+      <xs:element name="fallback" type="xs:string" minOccurs="0"/>
+      <xs:element name="versioned" type="xs:boolean" minOccurs="0" default="false"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="resources" type="tobago:resources-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="resources-type">
+    <xs:sequence>
+      <xs:element name="script" type="tobago:script-type" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="style" type="tobago:style-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="production" type="xs:boolean" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="script-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="style-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="name-type">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:complexType name="properties-type">
+    <xs:sequence>
+      <xs:element name="entry" type="tobago:entry-type" maxOccurs="unbounded" minOccurs="1"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="entry-type">
+    <xs:simpleContent>
+      <xs:extension base="xs:string">
+        <xs:attribute name="key" type="xs:string" use="required"/>
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+</xs:schema>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-3.0.xsd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-3.0.xsd
new file mode 100644
index 0000000..723c4d2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config-3.0.xsd
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<xs:schema
+    targetNamespace="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:tobago="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xs="http://www.w3.org/2001/XMLSchema"
+    elementFormDefault="qualified"
+    attributeFormDefault="unqualified"
+    version="3.0">
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      Licensed to the Apache Software Foundation (ASF) under one or more
+      contributor license agreements.  See the NOTICE file distributed with
+      this work for additional information regarding copyright ownership.
+      The ASF licenses this file to You under the Apache License, Version 2.0
+      (the "License"); you may not use this file except in compliance with
+      the License.  You may obtain a copy of the License at
+
+           http://www.apache.org/licenses/LICENSE-2.0
+
+      Unless required by applicable law or agreed to in writing, software
+      distributed under the License is distributed on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+      See the License for the specific language governing permissions and
+      limitations under the License.
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:annotation>
+    <xs:documentation>
+      <![CDATA[
+      ************************************************************************************
+      ************************************************************************************
+      WARNING
+      THIS IS A PRE-RELEASE VERSION OF THIS FILE, PLEASE CHECK IF THERE IS AN UPDATE ON
+      http://myfaces.apache.org/tobago/tobago-config-3.0.xsd
+      ************************************************************************************
+      ************************************************************************************
+
+      This is the XML schema for the Tobago configuration files version 3.0.
+
+      Use the following definition:
+
+      <tobago-config
+          xmlns="http://myfaces.apache.org/tobago/tobago-config"
+          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+          xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+          version="3.0">
+        ...
+      </tobago-config>
+      ]]>
+    </xs:documentation>
+  </xs:annotation>
+
+  <xs:element name="tobago-config" type="tobago:tobago-config-type"/>
+
+  <xs:complexType name="tobago-config-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" minOccurs="0"/>
+      <xs:element name="ordering" type="tobago:ordering-type" minOccurs="0"/>
+      <xs:element name="theme-config" type="tobago:theme-config-type" minOccurs="0"/>
+      <xs:element name="create-session-secret" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="check-session-secret" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="prevent-frame-attacks" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="set-nosniff-header" type="xs:boolean" minOccurs="0" default="true"/>
+      <xs:element name="classic-date-time-picker" type="xs:boolean" minOccurs="0" default="false"/>
+      <xs:element name="content-security-policy" type="tobago:content-security-policy-type" minOccurs="0"/>
+      <xs:element name="sanitizer" type="tobago:sanitizer-type" minOccurs="0"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="theme-definitions" type="tobago:theme-definitions-type" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="version"
+                  type="tobago:tobago-config-version-type"
+                  use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="tobago-config-version-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="3.0"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="ordering-type">
+    <xs:sequence>
+      <xs:element name="after" type="tobago:before-after-type" minOccurs="0"/>
+      <xs:element name="before" type="tobago:before-after-type" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="before-after-type">
+    <xs:sequence>
+      <xs:element name="name" type="tobago:name-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-config-type">
+    <xs:sequence>
+      <xs:element name="default-theme" type="xs:string"/>
+      <xs:element name="supported-theme" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="content-security-policy-type">
+    <xs:sequence>
+      <xs:element name="directive" type="xs:string" maxOccurs="unbounded" minOccurs="0"/>
+    </xs:sequence>
+    <xs:attribute name="mode" type="tobago:scp-mode-type" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="sanitizer-type">
+    <xs:sequence>
+      <xs:element name="sanitizer-class" type="xs:string" maxOccurs="1" minOccurs="1"/>
+      <xs:element name="properties" type="tobago:properties-type" maxOccurs="1" minOccurs="0"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:simpleType name="scp-mode-type">
+    <xs:restriction base="xs:token">
+      <xs:enumeration value="on"/>
+      <xs:enumeration value="off"/>
+      <xs:enumeration value="report-only"/>
+    </xs:restriction>
+  </xs:simpleType>
+
+  <xs:complexType name="renderers-type">
+    <xs:sequence>
+      <xs:element name="renderer" type="tobago:renderer-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="renderer-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="supported-markup" type="tobago:supported-markup-type"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="supported-markup-type">
+    <xs:sequence>
+      <xs:element name="markup" type="xs:string" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definitions-type">
+    <xs:sequence>
+      <xs:element name="theme-definition" type="tobago:theme-definition-type" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="theme-definition-type">
+    <xs:sequence>
+      <xs:element name="name" type="xs:string"/>
+      <xs:element name="display-name" type="xs:string" minOccurs="0"/>
+      <xs:element name="fallback" type="xs:string" minOccurs="0"/>
+      <xs:element name="versioned" type="xs:boolean" minOccurs="0" default="false"/>
+      <xs:element name="renderers" type="tobago:renderers-type" minOccurs="0"/>
+      <xs:element name="resources" type="tobago:resources-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="resources-type">
+    <xs:sequence>
+      <xs:element name="excludes" type="tobago:excludes-type" minOccurs="0" maxOccurs="1"/>
+      <xs:element name="script" type="tobago:script-type" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="style" type="tobago:style-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+    <xs:attribute name="production" type="xs:boolean" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="excludes-type">
+    <xs:sequence>
+      <xs:element name="script" type="tobago:script-type" minOccurs="0" maxOccurs="unbounded"/>
+      <xs:element name="style" type="tobago:style-type" minOccurs="0" maxOccurs="unbounded"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="script-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:complexType name="style-type">
+    <xs:attribute name="name" type="xs:string" use="required"/>
+  </xs:complexType>
+
+  <xs:simpleType name="name-type">
+    <xs:restriction base="xs:string"/>
+  </xs:simpleType>
+
+  <xs:complexType name="properties-type">
+    <xs:sequence>
+      <xs:element name="entry" type="tobago:entry-type" maxOccurs="unbounded" minOccurs="1"/>
+    </xs:sequence>
+  </xs:complexType>
+
+  <xs:complexType name="entry-type">
+    <xs:simpleContent>
+      <xs:extension base="xs:string">
+        <xs:attribute name="key" type="xs:string" use="required"/>
+      </xs:extension>
+    </xs:simpleContent>
+  </xs:complexType>
+
+</xs:schema>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config_1_0.dtd b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config_1_0.dtd
new file mode 100644
index 0000000..4d41568
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/config/tobago-config_1_0.dtd
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+  This is the DTD for the tobago configuration files version 1.0.
+  You should use the following DOCTYPE in your tobago-config.xml:
+
+  <!DOCTYPE tobago-config PUBLIC
+      "-//The Apache Software Foundation//DTD Tobago Config 1.0//EN"
+      "http://myfaces.apache.org/tobago/tobago-config_1_0.dtd">
+-->
+
+<!ENTITY % Boolean "(true|false|yes|no)">
+
+<!ELEMENT tobago-config (theme-config, resource-dir*, load-theme-resources-from-classpath?, mapping-rule*, ajax-enabled?, renderers?)>
+
+<!ELEMENT theme-config (default-theme, supported-theme*)>
+<!ELEMENT default-theme (#PCDATA)>
+<!ELEMENT supported-theme (#PCDATA)>
+
+<!ELEMENT name (#PCDATA)>
+<!ELEMENT display-name (#PCDATA)>
+<!ELEMENT fallback (#PCDATA)>
+
+<!ELEMENT resource-dir (#PCDATA)>
+
+<!-- deprecated -->
+<!ELEMENT load-theme-resources-from-classpath (#PCDATA)>
+
+<!-- deprecated -->
+<!ELEMENT mapping-rule (request-uri, forward-uri, attribute*)>
+<!-- deprecated -->
+<!ELEMENT request-uri (#PCDATA)>
+<!-- deprecated -->
+<!ELEMENT forward-uri (#PCDATA)>
+
+<!ELEMENT attribute (key, value)>
+<!ELEMENT key (#PCDATA)>
+<!ELEMENT value (#PCDATA)>
+
+<!ELEMENT ajax-enabled (#PCDATA)>
+
+<!ELEMENT renderers (renderer)*>
+<!ELEMENT renderer (name|supported-markup)*>
+<!ELEMENT supported-markup (markup)*>
+<!ELEMENT markup (#PCDATA)>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage.xml b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage.xml
new file mode 100644
index 0000000..88eb9e5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+
+  <!-- requiredvalidator -->
+  <entry key="tobago.requiredvalidator.message.empty.summary">Required field.</entry>
+  <entry key="tobago.requiredvalidator.message.empty.detail">Field is required.</entry>
+
+  <!-- longrangevalidator -->
+  <entry key="tobago.longrangevalidator.message.range.summary">Not in range.</entry>
+  <entry key="tobago.longrangevalidator.message.range.detail">Value must be between {0} and {1}.</entry>
+  <entry key="tobago.longrangevalidator.message.type.summary">Wrong type.</entry>
+  <entry key="tobago.longrangevalidator.message.type.detail">Value is not of the correct type.</entry>
+  <entry key="tobago.message.number_conversion_error.summary">Unable to convert number.</entry>
+  <entry key="tobago.message.number_conversion_error.detail">Unable to convert ''{0}'' to number type {1}.</entry>
+  <entry key="tobago.message.conversion_error.summary">Unable to convert.</entry>
+  <entry key="tobago.message.conversion_error.detail">Unable to convert ''{0}'' to type {1}.</entry>
+  <entry key="tobago.tree.MESSAGE_NOT_LEAF">Only leaf selection allowed.</entry>
+  <entry key="tobago.SelectOne.MESSAGE_VALUE_REQUIRED">Selection required</entry>
+
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE">Content type error</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE_detail">The given file is not content type of "{0}".</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT">File size error</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT_detail">The uploaded file exceeded the maximum size of {0} bytes.</entry>
+
+</properties>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage_de.xml b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage_de.xml
new file mode 100644
index 0000000..a5f6717
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage_de.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!-- $Source$ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+
+  <!-- requiredvalidator -->
+  <entry key="tobago.requiredvalidator.message.empty.summary">Pflichtfeld</entry>
+  <entry key="tobago.requiredvalidator.message.empty.detail">Feld benötigt eine Eingabe!</entry>
+
+  <!-- longrangevalidator -->
+  <entry key="tobago.longrangevalidator.message.range.summary">Bereichsüberschreitung.</entry>
+  <entry key="tobago.longrangevalidator.message.range.detail">Wert muss zwischen {0} und {1} liegen.</entry>
+  <entry key="tobago.longrangevalidator.message.type.summary">Falscher Typ.</entry>
+  <entry key="tobago.longrangevalidator.message.type.detail">Wert hat den falschen Typ.</entry>
+  <entry key="tobago.message.number_conversion_error.summary">Zahl kann nicht konvertiert werden.</entry>
+  <entry key="tobago.message.number_conversion_error.detail">''{0}'' kann nicht zum Typ {1} umgewandelt werden.</entry>
+  <entry key="tobago.message.conversion_error.summary">Konvertierung nicht möglich.</entry>
+  <entry key="tobago.message.conversion_error.detail">''{0}'' kann nicht zum Typ {1} umgewandelt werden.</entry>
+  <entry key="tobago.tree.MESSAGE_NOT_LEAF">Es dürfen nur Endknoten ausgewählt werden.</entry>
+  <entry key="tobago.SelectOne.MESSAGE_VALUE_REQUIRED">Eine Auswahl wird benötigt!</entry>
+
+  <entry key="tobago.ajax.response.error">Server Error: Fehler beim Bearbeiten der Anfrage. Eventuell ein Session Timeout!</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE">Dateityp Fehler</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE_detail">Die hochgeladene Datei ist nicht vom Typ "{0}".</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT">Dateigröße Fehler</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT_detail">Die Größe der hochgeladenen Datei darf nicht größer als {1} Bytes sein.</entry>
+
+</properties>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage_es.xml b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage_es.xml
new file mode 100644
index 0000000..59193f0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoMessage_es.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+
+  <!-- requiredvalidator -->
+  <entry key="tobago.requiredvalidator.message.empty.summary">Campo requerido.</entry>
+  <entry key="tobago.requiredvalidator.message.empty.detail">Campo es requerido.</entry>
+
+  <!-- longrangevalidator -->
+  <entry key="tobago.longrangevalidator.message.range.summary">Fuera de rango.</entry>
+  <entry key="tobago.longrangevalidator.message.range.detail">El valor debe de ser entre {0} y {1}.</entry>
+  <entry key="tobago.longrangevalidator.message.type.summary">Tipo erroneo.</entry>
+  <entry key="tobago.longrangevalidator.message.type.detail">El valor no es del tipo correcto.</entry>
+  <entry key="tobago.message.number_conversion_error.summary">Número no se puede convertir.</entry>
+  <entry key="tobago.message.number_conversion_error.detail">No se puede convertir ''{0}'' a tipo de número {1}.</entry>
+  <entry key="tobago.message.conversion_error.summary">No se puede convertir.</entry>
+  <entry key="tobago.message.conversion_error.detail">No se puede convertir ''{0}'' al tipo {1}.</entry>
+  <entry key="tobago.tree.MESSAGE_NOT_LEAF">Solo se permite seleccionar hojas.</entry>
+  <entry key="tobago.SelectOne.MESSAGE_VALUE_REQUIRED">Se requiere seleccionar.</entry>
+
+  <entry key="tobago.ajax.response.error">Error en el servidor: No hay respuesta del servidor. Probablemente debido a un tiempo agotado de sesion!</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE">Error de tipo de contenido</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.CONTENT_TYPE_detail">El archivo no es del tipo de contenido "{0}".</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT">Error en el tamaño del archivo</entry>
+  <entry key="org.apache.myfaces.tobago.FileItemValidator.SIZE_LIMIT_detail">El archivo subido excede el máximo tamaño de {0} bytes.</entry>
+
+</properties>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource.xml b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource.xml
new file mode 100644
index 0000000..b717226
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+
+  <!-- Page -->
+  <entry key="pageNoscript">This site requires JavaScript, but JavaScript is currently not activated in your browser. To enable JavaScript you may consult your browsers the documentation.</entry>
+
+  <!-- Client Configuration -->
+  <entry key="configTitle">Client configuration of the Tobago framework</entry>
+  <entry key="configTheme">Theme</entry>
+  <entry key="configThemeText">Which theme should be used?</entry>
+  <entry key="configLocale">Locale</entry>
+  <entry key="configLocaleText">Which locale should be used?</entry>
+  <entry key="configContentType">Content type</entry>
+  <entry key="configContentTypeText">Which Content-Type should be used?</entry>
+  <entry key="configSubmit">Submit</entry>
+  <entry key="configButtonText">Configuration</entry>
+  <entry key="configCachecoverage">Cache coverage</entry>
+
+  <!-- File-->
+  <entry key="tobago.file.multiFormat">{} files selected</entry>
+
+  <!-- Sheet -->
+  <entry key="sheetFirst">First Page</entry>
+  <entry key="sheetPrev">Previous Page</entry>
+  <entry key="sheetNext">Next Page</entry>
+  <entry key="sheetLast">Last Page</entry>
+  <entry key="sheetToPage">Page {0}</entry>
+  <entry key="sheetTipSorting">Click to sort this column</entry>
+  <entry key="sheetAscending">Ascending</entry>
+  <entry key="sheetDescending">Descending</entry>
+  <entry key="sheetPagingInfoRows">Rows {0} to {1} of {2}</entry>
+  <entry key="sheetPagingInfoSingleRow">Row {0} of {2}</entry>
+  <entry key="sheetPagingInfoUndefinedRows">Rows {0} to {1}</entry>
+  <entry key="sheetPagingInfoUndefinedSingleRow">Row {0}</entry>
+  <entry key="sheetPagingInfoEmptyRow">No rows available</entry>
+  <entry key="sheetPagingInfoRowPagingTip">Click here, to change the first displayed row</entry>
+  <entry key="sheetPagingInfoPages">Page {0} of {1}</entry>
+  <entry key="sheetPagingInfoSinglePage">Page {0} of {1}</entry>
+  <entry key="sheetPagingInfoUndefinedPages">Page {0}</entry>
+  <entry key="sheetPagingInfoUndefinedSinglePage">Page {0}</entry>
+  <entry key="sheetPagingInfoEmptyPage"/>
+  <entry key="sheetPagingInfoPagePagingTip">Click here, to change the displayed page</entry>
+  <entry key="sheetMenuToggleselect">Invert selections</entry>
+  <entry key="sheetMenuUnselect">Unselect all</entry>
+  <entry key="sheetMenuSelect">Select all</entry>
+
+  <!-- Tree -->
+  <entry key="treeNew">New</entry>
+  <entry key="treeDelete">Delete</entry>
+  <entry key="treeEdit">Edit</entry>
+  <entry key="treeCut">Cut</entry>
+  <entry key="treeCopy">Copy</entry>
+  <entry key="treePaste">Paste</entry>
+  <entry key="treeMoveUp">Move Up</entry>
+  <entry key="treeMoveDown">Move Down</entry>
+  <entry key="treeNodeNew">New Node</entry>
+
+  <!-- datePicker -->
+  <entry key="datePickerTitle">Date Picker</entry>
+  <entry key="datePickerOk">OK</entry>
+  <entry key="datePickerCancel">Cancel</entry>
+
+  <!-- in - input suggest -->
+  <entry key="tobago.in.inputSuggest.moreElements">There are more matching entries…</entry>
+
+  <!-- messages -->
+  <entry key="tobago.message.confirmation.title">Messages</entry>
+  <entry key="tobago.message.confirmation.okay">OK</entry>
+
+  <entry key="browser.noframe.message.prefix">Your user agent does not support frames or is currently configured not to display frames. However, you may visit the related document manually: </entry>
+  <entry key="browser.noframe.message.postfix"></entry>
+
+</properties>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource_de.xml b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource_de.xml
new file mode 100644
index 0000000..aaceab8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource_de.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!-- $Source$ -->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+
+  <!-- Page -->
+  <entry key="pageNoscript">Diese Seite benötigt JavaScript, allerdings ist JavaScript in Ihrem Browser derzeit deaktiviert. Um JavaScript zu aktivieren, lesen Sie ggf. die Anleitung Ihres Browsers.</entry>
+
+  <!-- Client Configuration -->
+  <entry key="configTitle">Konfiguration des Clients des Tobago-Frameworks</entry>
+  <entry key="configTheme">Design</entry>
+  <entry key="configThemeText">Welches Design soll verwendet werden?</entry>
+  <entry key="configLocale">Sprache</entry>
+  <entry key="configLocaleText">Welche Sprache/Region soll verwendet werden?</entry>
+  <entry key="configContentType">Inhaltstyp</entry>
+  <entry key="configContentTypeText">Welcher Inhaltstyp (Content-Type) soll verwendet werden?</entry>
+  <entry key="configSubmit">Ändern</entry>
+  <entry key="configButtonText">Einstellungen</entry>
+  <entry key="configCachecoverage">Cache Abdeckung</entry>
+
+  <!-- File-->
+  <entry key="tobago.file.multiFormat">{} Dateien ausgewählt</entry>
+
+  <!-- Sheet -->
+  <entry key="sheetFirst">erste Seite</entry>
+  <entry key="sheetPrev">vorherige Seite</entry>
+  <entry key="sheetNext">nächste Seite</entry>
+  <entry key="sheetLast">letzte Seite</entry>
+  <entry key="sheetToPage">Seite {0}</entry>
+  <entry key="sheetTipSorting">nach dieser Spalte sortieren</entry>
+  <entry key="sheetAscending">aufsteigend sortiert</entry>
+  <entry key="sheetDescending">absteigend sortiert</entry>
+  <entry key="sheetPagingInfoRows">Zeilen {0} bis {1} von {2}</entry>
+  <entry key="sheetPagingInfoSingleRow">Zeile {0} von {2}</entry>
+  <entry key="sheetPagingInfoUndefinedRows">Zeilen {0} bis {1}</entry>
+  <entry key="sheetPagingInfoUndefinedSingleRow">Zeile {0}</entry>
+  <entry key="sheetPagingInfoEmptyRow">Keine Zeilen verf&amp;uuml;gbar</entry>
+  <entry key="sheetPagingInfoRowPagingTip">Hier klicken, zum Eingeben der ersten anzuzeigenden Zeile.</entry>
+  <entry key="sheetPagingInfoPages">Seite {0} von {1}</entry>
+  <entry key="sheetPagingInfoSinglePage">Seite {0} von {1}</entry>
+  <entry key="sheetPagingInfoUndefinedPages">Seite {0}</entry>
+  <entry key="sheetPagingInfoUndefinedSinglePage">Seite {0}</entry>
+  <entry key="sheetPagingInfoEmptyPage"/>
+  <entry key="sheetPagingInfoPagePagingTip">Hier klicken, zum Eingeben der anzuzeigenden Seite.</entry>
+  <entry key="sheetMenuToggleselect">Markierung umkehren</entry>
+  <entry key="sheetMenuUnselect">Markierungen löschen</entry>
+  <entry key="sheetMenuSelect">Alles markieren</entry>
+
+  <!-- Tree -->
+  <entry key="treeNew">Neu</entry>
+  <entry key="treeDelete">Löschen</entry>
+  <entry key="treeEdit">Bearbeiten</entry>
+  <entry key="treeCut">Ausschneiden</entry>
+  <entry key="treeCopy">Kopieren</entry>
+  <entry key="treePaste">Einfügen</entry>
+  <entry key="treeMoveUp">Nach oben verschieben</entry>
+  <entry key="treeMoveDown">Nach unten verschieben</entry>
+  <entry key="treeNodeNew">Neuer Knoten</entry>
+
+  <!-- datePicker -->
+  <entry key="datePickerTitle">Datumsauswahl</entry>
+  <entry key="datePickerOk">OK</entry>
+  <entry key="datePickerCancel">Abbrechen</entry>
+
+  <!-- in - input suggest -->
+  <entry key="tobago.in.inputSuggest.moreElements">Es gibt weitere passende Einträge…</entry>
+
+  <!-- messages -->
+  <entry key="tobago.message.confirmation.title">Meldungen</entry>
+
+  <entry key="browser.noframe.message.prefix">Ihr Browser stellt keine so genannten Frames dar. Den Inhalt können Sie hier erreichen:</entry>
+  <entry key="browser.noframe.message.postfix"></entry>
+
+</properties>
diff --git a/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource_es.xml b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource_es.xml
new file mode 100644
index 0000000..4a96633
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/main/resources/org/apache/myfaces/tobago/context/TobagoResource_es.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+
+  <!-- Page -->
+  <entry key="pageNoscript">Esta página requiere JavaScript, pero JavaScript no se activa actualmente en su navegador. Para permitir JavaScript usted puede consultar la documentación del navegador.</entry>
+
+  <!-- Client Configuration -->
+  <entry key="configTitle">Configuración cliente del framework Tobago</entry>
+  <entry key="configTheme">Tema</entry>
+  <entry key="configThemeText">¿Que tema debe de ser utilizado?</entry>
+  <entry key="configLocale">Idioma</entry>
+  <entry key="configLocaleText">¿Que idioma debe de ser utilizado?</entry>
+  <entry key="configContentType">Tipo de contenido</entry>
+  <entry key="configContentTypeText">¿Que tipo de contenido debe de ser utilizado?</entry>
+  <entry key="configSubmit">Enviar</entry>
+  <entry key="configButtonText">Configuracion</entry>
+  <entry key="configCachecoverage">Cobertura de cache</entry>
+
+  <!-- File-->
+  <entry key="tobago.file.multiFormat">{} archivos seleccionados</entry>
+
+  <!-- Sheet -->
+  <entry key="sheetFirst">Primera Página</entry>
+  <entry key="sheetPrev">Página Anterior</entry>
+  <entry key="sheetNext">Página Siguiente</entry>
+  <entry key="sheetLast">Última Página</entry>
+  <entry key="sheetToPage">Página {0}</entry>
+  <entry key="sheetTipSorting">Ordenar por esta columna</entry>
+  <entry key="sheetAscending">Ascendente</entry>
+  <entry key="sheetDescending">Descendente</entry>
+  <entry key="sheetPagingInfoRows">Registros {0} {1} de {2}</entry>
+  <entry key="sheetPagingInfoSingleRow">Registro {0} de {2}</entry>
+  <entry key="sheetPagingInfoUndefinedRows">Registros {0} {1}</entry>
+  <entry key="sheetPagingInfoUndefinedSingleRow">Registro {0}</entry>
+  <entry key="sheetPagingInfoEmptyRow">No hay registros disponibles</entry>
+  <entry key="sheetPagingInfoRowPagingTip">Click aqui, para cambiar el primer registro desplegado.</entry>
+  <entry key="sheetPagingInfoPages">Página {0} de {1}</entry>
+  <entry key="sheetPagingInfoSinglePage">Página {0} de {1}</entry>
+  <entry key="sheetPagingInfoUndefinedPages">Página {0}</entry>
+  <entry key="sheetPagingInfoUndefinedSinglePage">Página {0}</entry>
+  <entry key="sheetPagingInfoEmptyPage"/>
+  <entry key="sheetPagingInfoPagePagingTip">Click aquí, para cambiar el nombre desplegado.</entry>
+  <entry key="sheetMenuToggleselect">Invertir seleccion</entry>
+  <entry key="sheetMenuUnselect">Deseleccionar todo</entry>
+  <entry key="sheetMenuSelect">Seleccionar todo</entry>
+
+  <!-- Tree -->
+  <entry key="treeNew">Nuevo</entry>
+  <entry key="treeDelete">Borrar</entry>
+  <entry key="treeEdit">Editar</entry>
+  <entry key="treeCut">Cortar</entry>
+  <entry key="treeCopy">Copiar</entry>
+  <entry key="treePaste">Pegar</entry>
+  <entry key="treeMoveUp">Mover hacia arriba</entry>
+  <entry key="treeMoveDown">Mover hacia abajo</entry>
+  <entry key="treeNodeNew">Nuevo nodo</entry>
+
+  <!-- datePicker -->
+  <entry key="datePickerTitle">Escoger fecha</entry>
+  <entry key="datePickerOk">Enviar</entry>
+  <entry key="datePickerCancel">Cancelar</entry>
+
+  <!-- in - input suggest -->
+  <entry key="tobago.in.inputSuggest.moreElements">Hay más entradas aparejadas…</entry>
+
+  <!-- messages -->
+  <entry key="tobago.message.confirmation.title">Aviso</entry>
+
+  <entry key="tobago.ajax.response.error">Error en el servidor: No hay respuesta del servidor. Probablemente debido a un tiempo agotado de sesion!</entry>
+
+  <entry key="browser.noframe.message.prefix">Tu navegador no soporta frames o está configurado para no desplegar frames. Como sea, puedes visitar el documento relacionado: </entry>
+  <entry key="browser.noframe.message.postfix"></entry>
+
+</properties>
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/ClientBehaviorsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/ClientBehaviorsUnitTest.java
new file mode 100644
index 0000000..7ce2a79
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/ClientBehaviorsUnitTest.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class ClientBehaviorsUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(ClientBehaviors.class);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/FacetsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/FacetsUnitTest.java
new file mode 100644
index 0000000..481f7f4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/FacetsUnitTest.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class FacetsUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(Facets.class);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/MethodOverwritingOfGeneratedUIComponentsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/MethodOverwritingOfGeneratedUIComponentsUnitTest.java
new file mode 100644
index 0000000..cbbf7bf
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/MethodOverwritingOfGeneratedUIComponentsUnitTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.junit.Assert;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.faces.component.UIComponent;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.List;
+
+public class MethodOverwritingOfGeneratedUIComponentsUnitTest {
+
+  private static final List<String> IGNORED_METHODS
+      = Arrays.asList("getFamily", "saveState", "restoreState", "getEventNames", "getDefaultEventName");
+  private static final List<String> IGNORED_COMPONENTS = Arrays.asList(
+      /*UIMenuSelectOne.class.getSimpleName()*/);
+  private static final MethodOfComponentList IGNORED_METHODS_PER_COMPONENT = new MethodOfComponentList();
+
+  static {
+    IGNORED_METHODS_PER_COMPONENT.add("isResizable", UIColumn.class);
+    IGNORED_METHODS_PER_COMPONENT.add("isResizable", UIColumnNode.class);
+    IGNORED_METHODS_PER_COMPONENT.add("isShowRootJunction", UISheet.class);
+    IGNORED_METHODS_PER_COMPONENT.add("isShowRootJunction", UITree.class);
+  }
+
+  private List<Class<? extends UIComponent>> uiComponents;
+
+  @Before
+  public void setup() throws IOException, ClassNotFoundException {
+    uiComponents = findUIComponents();
+  }
+
+  @Test
+  public void test() {
+
+    for (final Class<? extends UIComponent> uiComponent : uiComponents) {
+      final Method[] methods = uiComponent.getMethods();
+      for (final Method method : methods) {
+
+        if (!method.getDeclaringClass().equals(uiComponent)) {
+          // check only the method, that have an implementation in the generated class
+          continue;
+        }
+
+        if (IGNORED_METHODS.contains(method.getName())) {
+          continue;
+        }
+
+        if (IGNORED_METHODS_PER_COMPONENT.contains(method.getName(), uiComponent)) {
+          continue;
+        }
+
+        for (Class<?> superClass = uiComponent.getSuperclass();
+             superClass != null;
+             superClass = superClass.getSuperclass()) {
+          final Method superMethod;
+          try {
+            superMethod = superClass.getMethod(method.getName(), method.getParameterTypes());
+          } catch (final NoSuchMethodException e) {
+            // only looking for super methods
+            continue;
+          }
+
+          if (!Modifier.isAbstract(superMethod.getModifiers())) {
+            Assert.fail(method.getName() + " of " + uiComponent.getName()
+                + " hides a concrete super method (but is not in the ignore list).");
+            break;
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Find all classes in a package
+   */
+  private List<Class<? extends UIComponent>> findUIComponents() throws ClassNotFoundException, IOException {
+    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+    final String packageName = this.getClass().getPackage().getName();
+    final String path = packageName.replace('.', '/');
+    final Enumeration<URL> resources = classLoader.getResources(path);
+    final List<File> directories = new ArrayList<File>();
+    while (resources.hasMoreElements()) {
+      final URL resource = resources.nextElement();
+      directories.add(new File(resource.getFile()));
+    }
+    final ArrayList<Class<? extends UIComponent>> result = new ArrayList<Class<? extends UIComponent>>();
+    for (final File directory : directories) {
+      final File[] files = directory.listFiles();
+      if (files != null) {
+        for (final File file : files) {
+          final String name = file.getName();
+          if (!StringUtils.endsWith(name, ".class")) {
+            continue;
+          }
+          final String nameWithoutSuffix = name.substring(0, name.length() - 6);
+          if (IGNORED_COMPONENTS.contains(nameWithoutSuffix)) {
+            continue;
+          }
+          final String className = packageName + '.' + nameWithoutSuffix;
+          final Class<? extends UIComponent> clazz = (Class<? extends UIComponent>) Class.forName(className);
+          if (UIComponent.class.isAssignableFrom(clazz)) {
+            result.add(clazz);
+          }
+        }
+      }
+    }
+    return result;
+  }
+
+  private static class MethodOfComponentList {
+
+    private List<String> list = new ArrayList<String>();
+
+    public void add(final String method, final Class<? extends UIComponent> component) {
+      list.add(concatenate(method, component));
+    }
+
+    public boolean contains(final String method, final Class<? extends UIComponent> component) {
+      return list.contains(concatenate(method, component));
+    }
+
+    private String concatenate(final String method, final Class<? extends UIComponent> component) {
+      return method + '@' + component.getName();
+    }
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/RendererTypesUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/RendererTypesUnitTest.java
new file mode 100644
index 0000000..a591a96
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/RendererTypesUnitTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class RendererTypesUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+
+    testNames(RendererTypes.class);
+  }
+
+  @Override
+  protected String getEnumRegexp() {
+    return "[A-Z][a-zA-Z]*";
+  }
+
+  @Override
+  protected String constantCaseToEnum(String constant) {
+    return StringUtils.constantToUpperCamelCase(constant);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/SorterUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/SorterUnitTest.java
new file mode 100644
index 0000000..f547ab6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/SorterUnitTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.test.el.MockValueExpression;
+import org.apache.myfaces.tobago.event.SortActionEvent;
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class SorterUnitTest extends AbstractTobagoTestBase {
+
+    @Test
+    public void testSorter() {
+        final UISheet sheet = new UISheet();
+        final UIColumn column = new UIColumn();
+        sheet.getChildren().add(column);
+        
+        final Sorter sorter = new Sorter();
+        final SortActionEvent sortActionEvent = new SortActionEvent(sheet, column);
+        sorter.perform(sortActionEvent);
+
+        final List list = new ArrayList();
+        sheet.setValue(list);
+        sorter.perform(sortActionEvent);
+
+        final UILink link = new UILink();
+        column.getChildren().add(link);
+
+        sorter.perform(sortActionEvent);
+        
+        link.setValueExpression(Attributes.label.getName(),
+                new MockValueExpression("var.test", String.class));
+
+        sorter.perform(sortActionEvent);
+
+    }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/UIMessagesUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/UIMessagesUnitTest.java
new file mode 100644
index 0000000..6d0daa5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/UIMessagesUnitTest.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.apache.myfaces.tobago.layout.OrderBy;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import java.util.List;
+
+public class UIMessagesUnitTest extends AbstractTobagoTestBase {
+
+  @Override
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+    final FacesContext facesContext = getFacesContext();
+    facesContext.addMessage("id0", new FacesMessage(FacesMessage.SEVERITY_INFO, "test", "a test"));
+    facesContext.addMessage("id0", new FacesMessage(FacesMessage.SEVERITY_WARN, "test", "a test"));
+    facesContext.addMessage("id1", new FacesMessage(FacesMessage.SEVERITY_ERROR, "test", "a test"));
+    facesContext.addMessage("id1", new FacesMessage(FacesMessage.SEVERITY_FATAL, "test", "a test"));
+    facesContext.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, "test", "a test"));
+  }
+
+  @Test
+  public void testCreateMessageListAll() {
+
+    final UIMessages component = new UIMessages();
+    final List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+
+    Assert.assertEquals(5, messages.size());
+  }
+
+  @Test
+  public void testCreateMessageListGlobalOnly() {
+
+    final UIMessages component = new UIMessages();
+    component.setGlobalOnly(true);
+    final List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+
+    Assert.assertEquals(1, messages.size());
+  }
+
+  @Test
+  public void testCreateMessageListForId0() {
+
+    final UIMessages component = new UIMessages();
+    component.setFor("id0");
+    final List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+
+    Assert.assertEquals(2, messages.size());
+  }
+
+  @Test
+  public void testCreateMessageListInfoToWarn() {
+
+    final UIMessages component = new UIMessages();
+    component.setMaxSeverity(FacesMessage.SEVERITY_WARN);
+    final List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+
+    Assert.assertEquals(2, messages.size());
+  }
+
+  @Test
+  public void testCreateMessageListWarnToError() {
+
+    final UIMessages component = new UIMessages();
+    component.setMinSeverity(FacesMessage.SEVERITY_WARN);
+    component.setMaxSeverity(FacesMessage.SEVERITY_ERROR);
+    final List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+
+    Assert.assertEquals(2, messages.size());
+  }
+
+  @Test
+  public void testCreateMessageListErrorToFatal() {
+
+    final UIMessages component = new UIMessages();
+    component.setMinSeverity(FacesMessage.SEVERITY_ERROR);
+    final List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+
+    Assert.assertEquals(3, messages.size());
+  }
+
+  @Test
+  public void testCreateMessageListMaxNumber() {
+
+    final UIMessages component = new UIMessages();
+
+    component.setMaxNumber(3);
+    List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+    Assert.assertEquals(3, messages.size());
+
+    component.setMaxNumber(30000);
+    messages = component.createMessageList(getFacesContext());
+    Assert.assertEquals(5, messages.size());
+  }
+
+  @Test
+  public void testCreateMessageListOrderBySeverity() {
+
+    final UIMessages component = new UIMessages();
+    component.setOrderBy(OrderBy.severity);
+    final List<UIMessages.Item> messages = component.createMessageList(getFacesContext());
+
+    int mustShrink = FacesMessage.SEVERITY_FATAL.getOrdinal();
+    for (final UIMessages.Item message : messages) {
+      final int newValue = message.getFacesMessage().getSeverity().getOrdinal();
+      Assert.assertTrue(mustShrink >= newValue);
+      mustShrink = newValue;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/UISheetUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/UISheetUnitTest.java
new file mode 100644
index 0000000..e537247
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/component/UISheetUnitTest.java
@@ -0,0 +1,404 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.component;
+
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.faces.model.ListDataModel;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class UISheetUnitTest extends AbstractTobagoTestBase {
+
+  private static final String[] DATA = {"one", "two", "three", "four", "five", "six", "seven", "eight", "nine"};
+  private List<String> nineRows;
+  private UISheet data;
+  private UISheet unknown;
+
+  @Override
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+    nineRows = new ArrayList<String>();
+    Collections.addAll(nineRows, DATA);
+
+    data = new UISheet();
+    data.setValue(new ListDataModel(nineRows));
+
+    unknown = new UISheet();
+    unknown.setValue(new DataModelWithUnknownRows(nineRows));
+  }
+  
+  @Test
+  public void test5RowsPerPage() {
+    data.setRows(5);
+    // having rowCount 9 and 5 rows to display it looks like this (rotated, X X X X X means one page with 5 rows):
+    // X X X X X
+    // X X X X
+    Assert.assertEquals("number of pages", 2, data.getPages());
+  }
+
+  @Test
+  public void test9RowsPerPage() {
+    data.setRows(9);
+    // X X X X X X X X X
+    Assert.assertEquals("number of pages", 1, data.getPages());
+  }
+
+  @Test
+  public void test2RowsPerPage() {
+    data.setRows(2);
+    // X X
+    // X X
+    // X X
+    // X X
+    // X
+    Assert.assertEquals("number of pages", 5, data.getPages());
+  }
+
+  @Test
+  public void test3RowsPerPage() {
+    data.setRows(3);
+    // X X X
+    // X X X
+    // X X X
+    Assert.assertEquals("number of pages", 3, data.getPages());
+  }
+
+  @Test
+  public void test1RowPerPage() {
+    data.setRows(1);
+    // X
+    // X
+    // X
+    // X
+    // X
+    // X
+    // X
+    // X
+    // X
+    Assert.assertEquals("number of pages", 9, data.getPages());
+  }
+
+  @Test
+  public void testAllRowsPerPage() {
+    data.setRows(0); // zero means all
+    // X X X X X X X X X
+    Assert.assertEquals("number of pages", 1, data.getPages());
+  }
+
+  @Test
+  public void testCurrentPageRows5() {
+    data.setRows(5);
+    // initially first = 0
+    // * X X X X
+    // X X X X
+    Assert.assertEquals("current page", 0, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", true, data.isAtBeginning());
+
+    data.setFirst(5);
+    // now we set the first (show as an F)
+    // X X X X X
+    // * X X X
+    Assert.assertEquals("current page", 1, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", false, data.isAtBeginning());
+
+    data.setFirst(0);
+    // * X X X X
+    // X X X X
+    Assert.assertEquals("current page", 0, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", true, data.isAtBeginning());
+
+    data.setFirst(4);
+    // X X X X *
+    // X X X X
+    Assert.assertEquals("current page", 0, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", false, data.isAtBeginning());
+
+    data.setFirst(100);
+    // out of rage
+    Assert.assertEquals("current page", 1, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", false, data.isAtBeginning());
+  }
+
+  @Test
+  public void testCurrentPageRows20() {
+    data.setRows(20); // more rows than data entries
+    // initially first = 0
+    // * X X X X X X X X
+    Assert.assertEquals("current page", 0, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", true, data.isAtBeginning());
+
+    data.setFirst(8);
+    // now we set the first (show as an F)
+    // X X X X X X X X *
+    Assert.assertEquals("current page", 0, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", false, data.isAtBeginning());
+
+    data.setFirst(0);
+    // * X X X X X X X X
+    Assert.assertEquals("current page", 0, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", true, data.isAtBeginning());
+
+    data.setFirst(100);
+    // out of range
+    Assert.assertEquals("current page", 0, data.getCurrentPage());
+    Assert.assertEquals("is at beginning", false, data.isAtBeginning());
+  }
+
+  @Test
+  public void testRowData() {
+    data.setRowIndex(0);
+    Assert.assertEquals("one", data.getRowData());
+    data.setRowIndex(8);
+    Assert.assertEquals("nine", data.getRowData());
+    data.setRowIndex(9);
+    try {
+      data.getRowData();
+      Assert.fail();
+    } catch (final IllegalArgumentException e) {
+      // okay: row is unavailable
+    }
+  }
+
+  @Test
+  public void testHasRowCount() {
+    Assert.assertEquals("has row count", true, data.hasRowCount());
+    Assert.assertEquals("has row count", false, unknown.hasRowCount());
+  }
+
+  @Test
+  public void testRowsUnlimited() {
+    data.setRows(5);
+    unknown.setRows(5);
+
+    Assert.assertEquals("unlimited rows", false, data.isRowsUnlimited());
+    Assert.assertEquals("unlimited rows", false, unknown.isRowsUnlimited());
+
+    data.setRows(0);
+    unknown.setRows(0);
+
+    Assert.assertEquals("unlimited rows", true, data.isRowsUnlimited());
+    Assert.assertEquals("unlimited rows", true, unknown.isRowsUnlimited());
+  }
+
+  @Test
+  public void testNeedMoreThanOnePage() {
+
+    // known length:
+
+    data.setRows(0);
+    // * X X X X X X X X
+    Assert.assertEquals("need more than one page", false, data.needMoreThanOnePage());
+
+    data.setRows(5);
+    // * X X X X
+    // X X X X
+    Assert.assertEquals("need more than one page", true, data.needMoreThanOnePage());
+
+    data.setRows(20);
+    // * X X X X X X X X
+    Assert.assertEquals("need more than one page", false, data.needMoreThanOnePage());
+
+    // unknown length:
+
+    unknown.setRows(0);
+    // * X X X X X X X X
+    Assert.assertEquals("need more than one page", false, unknown.needMoreThanOnePage());
+
+    unknown.setRows(5);
+    // * X X X X
+    // X X X X
+    Assert.assertEquals("need more than one page", true, unknown.needMoreThanOnePage());
+
+    unknown.setRows(20);
+    // * X X X X X X X X
+    Assert.assertEquals("need more than one page", true, unknown.needMoreThanOnePage());
+  }
+
+  @Test
+  public void testFirstRowIndexOfLastPage() {
+
+    // known length:
+
+    data.setRows(0);
+    // * X X X X X X X X
+    Assert.assertEquals("first row index of last page", 0, data.getFirstRowIndexOfLastPage());
+
+    data.setRows(5);
+    // * X X X X
+    // X X X X
+    Assert.assertEquals("first row index of last page", 5, data.getFirstRowIndexOfLastPage());
+
+    data.setRows(20);
+    // * X X X X X X X X
+    Assert.assertEquals("first row index of last page", 0, data.getFirstRowIndexOfLastPage());
+
+    // unknown length:
+
+    unknown.setRows(0);
+    // * X X X X X X X X
+    Assert.assertEquals("first row index of last page", 0, unknown.getFirstRowIndexOfLastPage());
+
+    unknown.setRows(5);
+    // * X X X X
+    // X X X X
+    try {
+      unknown.getFirstRowIndexOfLastPage();
+      Assert.fail("first row index of last page");
+    } catch (final IllegalArgumentException e) {
+      // okay: last page can't determined
+    }
+
+    unknown.setRows(20);
+    // * X X X X X X X X
+    try {
+      unknown.getFirstRowIndexOfLastPage();
+      Assert.fail("first row index of last page");
+    } catch (final IllegalArgumentException e) {
+      // okay: last page can't determined
+    }
+  }
+
+  @Test
+  public void testLastRowIndexOfCurrentPage() {
+
+    // known length:
+
+    data.setRows(0);
+    // * X X X X X X X X
+    Assert.assertEquals("last row index of current page", 9, data.getLastRowIndexOfCurrentPage());
+
+    data.setRows(5);
+    // * X X X X
+    // X X X X
+    Assert.assertEquals("last row index of current page", 5, data.getLastRowIndexOfCurrentPage());
+
+    data.setRows(20);
+    // * X X X X X X X X
+    Assert.assertEquals("last row index of current page", 9, data.getLastRowIndexOfCurrentPage());
+
+    // unknown length:
+
+    unknown.setRows(0);
+    // * X X X X X X X X
+    try {
+      unknown.getLastRowIndexOfCurrentPage();
+      Assert.fail("last row index of current page");
+    } catch (final IllegalArgumentException e) {
+      // okay: last row index of current page can't determined
+    }
+
+    unknown.setRows(5);
+    // * X X X X
+    // X X X X
+    try {
+      unknown.getLastRowIndexOfCurrentPage();
+      Assert.fail("last row index of current page");
+    } catch (final IllegalArgumentException e) {
+      // okay: last row index of current page can't determined
+    }
+
+    unknown.setRows(20);
+    // * X X X X X X X X
+    try {
+      unknown.getLastRowIndexOfCurrentPage();
+      Assert.fail("last row index of current page");
+    } catch (final IllegalArgumentException e) {
+      // okay: last row index of current page can't determined
+    }
+  }
+
+  @Test
+  public void testGetCurrentPageOnUnknown() {
+
+    // unknown length:
+
+    unknown.setRows(0);
+    // * X X X X X X X X
+    Assert.assertEquals("current page", 0, unknown.getCurrentPage());
+
+    unknown.setRows(5);
+    // * X X X X
+    // X X X X
+    Assert.assertEquals("current page", 0, unknown.getCurrentPage());
+
+    unknown.setFirst(5);
+    // X X X X X
+    // * X X X
+    Assert.assertEquals("current page", 1, unknown.getCurrentPage());
+  }
+
+  @Test
+  public void testGetPagesOnUnknown() {
+
+    // unknown length:
+
+    unknown.setRows(0);
+    // * X X X X X X X X
+    Assert.assertEquals("pages", 1, unknown.getPages());
+
+    unknown.setRows(5);
+    // * X X X X
+    // X X X X
+    try {
+      unknown.getPages();
+      Assert.fail("pages");
+    } catch (final IllegalArgumentException e) {
+      // okay: pages can't determined
+    }
+  }
+
+  @Test
+  public void testDynamicRemoval() {
+    nineRows.remove(0);
+    nineRows.remove(0);
+    nineRows.remove(0);
+    data.setRows(5);
+    Assert.assertEquals(2, data.getPages());
+    nineRows.remove(0);
+    nineRows.remove(0);
+    nineRows.remove(0);
+    Assert.assertEquals(1, data.getPages());
+  }
+
+  @Test
+  public void testStripRowIndex() {
+    Assert.assertEquals("comp1:comp2", new UISheet().stripRowIndex("123:comp1:comp2"));
+    Assert.assertEquals("comp1:comp2", new UISheet().stripRowIndex("comp1:comp2"));
+  }
+
+  private static class DataModelWithUnknownRows extends ListDataModel {
+
+    public DataModelWithUnknownRows(final List list) {
+      super(list);
+    }
+
+    @Override
+    public int getRowCount() {
+      return -1;
+    }
+  }
+  
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/MarkupUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/MarkupUnitTest.java
new file mode 100644
index 0000000..89a55f1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/MarkupUnitTest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.apache.commons.collections.IteratorUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+public class MarkupUnitTest {
+  
+  private static final String[] AB = new String[] {"a", "b"};
+
+  @Test
+  public void testString() {
+    Assert.assertNull(Markup.valueOf((String) null));
+    
+    Assert.assertArrayEquals(new String[] {"accent"}, IteratorUtils.toArray(Markup.valueOf("accent").iterator()));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf("a,b").iterator()));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf("a, b").iterator()));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf(", \ta , ,\n b ,").iterator()));
+  }
+  
+  @Test
+  public void testStringArray() {
+    Assert.assertNull(Markup.valueOf((String[]) null));
+    
+    Assert.assertNull(Markup.valueOf(new String[] {}));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf(new String[] {"a", "b"}).iterator()));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf(new String[] {" a ", " b "}).iterator()));
+  }
+  
+  @Test
+  public void testObject() {
+    Assert.assertNull(Markup.valueOf((Object) null));
+
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf((Object) ", \ta , ,\n b ,").iterator()));
+
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf((Object) new String[] {"a", "b"}).iterator()));
+    
+    Assert.assertArrayEquals(AB,
+        IteratorUtils.toArray(Markup.valueOf((Object) new String[] {" a ", " b "}).iterator()));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf(new StringBuilder("a, b")).iterator()));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf(AB).iterator()));
+    
+    Assert.assertArrayEquals(AB, IteratorUtils.toArray(Markup.valueOf(Arrays.asList(AB)).iterator()));
+  }
+  
+  @Test
+  public void testMarkup() {
+    Assert.assertNull(Markup.valueOf((Markup) null));
+    
+    final Markup accent = Markup.valueOf("accent");
+    Assert.assertSame(accent, Markup.valueOf(accent));
+  }
+
+  @Test
+  public void testAdd() {
+    final Markup a = Markup.valueOf("a");
+    final Markup b = Markup.valueOf("b");
+    final Markup c = Markup.valueOf("c");
+    final Markup ab = Markup.valueOf("a,b");
+    final Markup abc = Markup.valueOf("a,b,c");
+    Assert.assertEquals(a, Markup.NULL.add(a));
+    Assert.assertEquals(ab, a.add(b));
+    Assert.assertEquals(abc, ab.add(c));
+    Assert.assertEquals(abc, ab.add(abc));
+    Assert.assertSame(a, a.add(a));
+    Assert.assertSame(ab, ab.add(a));
+    Assert.assertSame(ab, ab.add(ab));
+  }
+
+  @Test
+  public void testRemove() {
+    final Markup a = Markup.valueOf("a");
+    final Markup b = Markup.valueOf("b");
+    final Markup c = Markup.valueOf("c");
+    final Markup ab = Markup.valueOf("a,b");
+    final Markup bc = Markup.valueOf("b,c");
+    final Markup abc = Markup.valueOf("a,b,c");
+    Assert.assertEquals(Markup.NULL, Markup.NULL.remove(a));
+    Assert.assertEquals(a, a.remove(b));
+    Assert.assertEquals(Markup.NULL, a.remove(a));
+    Assert.assertEquals(b, ab.remove(a));
+    Assert.assertEquals(a, ab.remove(b));
+    Assert.assertEquals(c, abc.remove(ab));
+    Assert.assertEquals(a, ab.remove(bc));
+    Assert.assertEquals(Markup.NULL, abc.remove(abc));
+    Assert.assertSame(b, b.remove(a));
+    Assert.assertSame(ab, ab.remove(c));
+  }
+
+  @Test
+  public void testContainsString() {
+    final Markup a = Markup.valueOf("a");
+    final Markup ab = Markup.valueOf("a,b");
+    Assert.assertFalse(Markup.NULL.contains("a"));
+    Assert.assertTrue(a.contains("a"));
+    Assert.assertTrue(a.contains((String) null));
+    Assert.assertFalse(a.contains("b"));
+    Assert.assertTrue(ab.contains("a"));
+    Assert.assertTrue(ab.contains("b"));
+    Assert.assertFalse(ab.contains("c"));
+  }
+
+  @Test
+  public void testContainsMarkup() {
+    final Markup a = Markup.valueOf("a");
+    final Markup ab = Markup.valueOf("a,b");
+    Assert.assertFalse(Markup.NULL.contains(Markup.valueOf("a")));
+    Assert.assertTrue(a.contains(Markup.NULL));
+    Assert.assertTrue(a.contains((Markup) null));
+    Assert.assertTrue(a.contains(Markup.valueOf("a")));
+    Assert.assertFalse(a.contains(Markup.valueOf("b")));
+    Assert.assertTrue(ab.contains(Markup.valueOf("a")));
+    Assert.assertTrue(ab.contains(Markup.valueOf("b")));
+    Assert.assertFalse(ab.contains(Markup.valueOf("c")));
+    Assert.assertTrue(ab.contains(Markup.valueOf("a,b")));
+    Assert.assertTrue(ab.contains(Markup.valueOf("a,a")));
+    Assert.assertFalse(ab.contains(Markup.valueOf("a,c")));
+    Assert.assertFalse(ab.contains(Markup.valueOf("a,c,d,e,c,f,e,f")));
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/ResourceUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/ResourceUtilsUnitTest.java
new file mode 100644
index 0000000..afdd1c1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/ResourceUtilsUnitTest.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ResourceUtilsUnitTest {
+
+  @Test
+  public void testAddPostfixToFilename() {
+    Assert.assertEquals("folder/treeNode-iconDisabled.gif",
+        ResourceUtils.addPostfixToFilename("folder/treeNode-icon.gif", "Disabled"));
+  }
+
+  @Test
+  public void testAddPostfixToFilenameWithoutExtension() {
+    Assert.assertEquals("folder/treeNode-iconDisabled",
+        ResourceUtils.addPostfixToFilename("folder/treeNode-icon", "Disabled"));
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/UserAgentUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/UserAgentUnitTest.java
new file mode 100644
index 0000000..ffa7f8a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/context/UserAgentUnitTest.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.context;
+
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+import java.util.List;
+
+@RunWith(Parameterized.class)
+public class UserAgentUnitTest {
+
+  private UserAgent agent;
+  private String headerString;
+
+  public UserAgentUnitTest(final String title, final UserAgent agent, final String headerString) {
+    this.agent = agent;
+    this.headerString = headerString;
+  }
+
+  @Test
+  public void test() {
+    Assert.assertEquals(agent, UserAgent.getInstance(headerString));
+  }
+
+  @Parameterized.Parameters
+  public static List<Object[]> data() {
+    return Arrays.asList(new Object[][]{
+
+        {"Internet Explorer 6 - Windows 2000",
+            UserAgent.MSIE_6_0,
+            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0"},
+
+        {"Internet Explorer 6 - Windows XP",
+            UserAgent.MSIE_6_0,
+            "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)'"},
+
+        {"Internet Explorer 7 - Windows XP",
+            UserAgent.MSIE_7_0,
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)"},
+
+        {"Internet Explorer 8 - Windows XP",
+            UserAgent.MSIE_8_0,
+            "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727;"
+            + " .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)"},
+
+        {"Internet Explorer 8 - Compatibility Mode - Windows XP",
+            UserAgent.MSIE_7_0_COMPAT,
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0)"},
+
+        {"Internet Explorer 9 preview - Windows 7",
+            UserAgent.MSIE_9_0,
+            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)"},
+
+        {"Internet Explorer 9 - Windows 7",
+            UserAgent.MSIE_9_0,
+            "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)"},
+
+        {"Internet Explorer 9 - Compatibility Mode - Windows 7",
+            UserAgent.MSIE_7_0_COMPAT,
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Win64; x64; Trident/5.0; "
+                + ".NET CLR 2.0.50727; SLCC2; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C)"},
+
+        {"Internet Explorer 10 - Windows 8 - Developer Preview",
+            UserAgent.MSIE_10_0,
+            "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"},
+
+        {"Internet Explorer 10 - Compatibility Mode - Windows 8 - Developer Preview",
+            UserAgent.MSIE_7_0_COMPAT,
+            "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.2; WOW64; Trident/6.0; .NET4.0E; .NET4.0C)"},
+
+        {"Internet Explorer 11 - Windows 7",
+            UserAgent.MSIE_11_0,
+            "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; SLCC2; "
+                + ".NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; "
+                + ".NET4.0C; .NET4.0E; rv:11.0) like Gecko"},
+
+        {"Firefox 3.6 - Ubuntu 10.4",
+            UserAgent.GECKO_1_9,
+            "Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2) Gecko/20100308 Ubuntu/10.04 (lucid) Firefox/3.6"},
+
+        {"Firefox 3.6 - Ubuntu 9.10",
+            UserAgent.GECKO_1_9,
+            "Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.2.3pre) Gecko/20100328 Ubuntu/9.10 (karmic) "
+                + "Namoroka/3.6.3pre"},
+
+        {"Firefox 23.0 - Mac OS X Mountain Lion",
+            UserAgent.GECKO_23_0,
+            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:23.0) Gecko/20100101 Firefox/23.0"},
+
+        {"Firefox 5.0 - Mac OS X Snow Leopard",
+            UserAgent.GECKO_2_0,
+            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:5.0) Gecko/20100101 Firefox/5.0"},
+
+        {"Firefox 4.0 beta 2 - Mac OS X Snow Leopard",
+            UserAgent.GECKO_2_0,
+            "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0b2) Gecko/20100720 Firefox/4.0b2"},
+
+        {"Firefox 3.6 - Mac OS X Snow Leopard",
+            UserAgent.GECKO_1_9,
+            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; de; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8"},
+
+        {"Firefox 3.5 - Mac OS X Snow Leopard",
+            UserAgent.GECKO_1_9,
+            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; de; rv:1.9.1.9) Gecko/20100315 Firefox/3.5.9"},
+
+        {"Firefox 3.0 - Mac OS X Snow Leopard",
+            UserAgent.GECKO_1_9,
+            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.6; de; rv:1.9.0.19) Gecko/2010031218 Firefox/3.0.19"},
+
+        {"Firefox 2.0 - Mac OS X Snow Leopard",
+            UserAgent.GECKO_1_8,
+            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X; de; rv:1.8.1.20) Gecko/20081217 Firefox/2.0.0.20"},
+
+        {"Opera 10.61 - Windows 7",
+            UserAgent.PRESTO,
+            "Opera/9.80 (Windows NT 6.1; U; de) Presto/2.6.30 Version/10.61"},
+
+        {"Opera 10.10 - Mac OS X Snow Leopard",
+            UserAgent.PRESTO,
+            "Opera/9.80 (Macintosh; Intel Mac OS X; U; de) Presto/2.2.15 Version/10.10"},
+
+        {"Opera 10.51 - Ubuntu 9.10",
+            UserAgent.PRESTO,
+            "Opera/9.80 (X11; Linux i686; U; en) Presto/2.5.22 Version/10.51"},
+
+        {"Chrome 4.1 - Windows 7",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko)"
+            + " Chrome/4.1.249.1042 Safari/532.5"},
+
+        {"Chrome 5 - Mac OS X Snow Leopard",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/533.4 (KHTML, like Gecko)"
+            + " Chrome/5.0.375.127 Safari/533.4"},
+
+        {"Chrome 5 - Ubuntu 9.10",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.3 (KHTML, like Gecko)"
+            + " Chrome/5.0.360.0 Safari/533.3"},
+
+        {"Chromium 5 - Ubuntu 9.10",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 (X11; U; Linux i686; en-US) AppleWebKit/533.3 (KHTML, like Gecko)"
+            + " Chrome/5.0.365.0 Safari/533.3"},
+
+        {"Safari 5 - Mac OS X Snow Leopard",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; de-de) AppleWebKit/533.17.8 (KHTML, like Gecko) "
+            + "Version/5.0.1 Safari/533.17.8"},
+
+        {"Safari 4 - Mac OS X Snow Leopard",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; de-de) AppleWebKit/531.22.7 (KHTML, like Gecko) "
+            + "Version/4.0.5 Safari/531.22.7"},
+
+        {"Safari 4 - iPad",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 (iPad; U; CPU OS 3_2_1 like Mac OS X; de-de) AppleWebKit/531.21.10 (KHTML, like Gecko) "
+                + "Version/4.0.4 Mobile/7B405 Safari/531.21.10"},
+
+        {"Web-Browser for S60 - Symbian - Nokia E51",
+            UserAgent.WEBKIT,
+            "Mozilla/5.0 "
+                + "(SymbianOS/9.2; U; Series60/3.1 NokiaE51-1/300.34.56; Profile/MIDP-2.0 Configuration/CLDC-1.1 ) "
+                + "AppleWebKit/413 (KHTML, like Gecko) Safari/413"},
+    });
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/convert/DurationConverterUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/convert/DurationConverterUnitTest.java
new file mode 100644
index 0000000..a79ccdf
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/convert/DurationConverterUnitTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.convert;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.UIIn;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import javax.faces.convert.Converter;
+
+public class DurationConverterUnitTest {
+
+  private Converter converter;
+
+  @Before
+  public void setUp() throws Exception {
+    converter = new DurationConverter();
+  }
+
+  @Test
+  public void testFormat() {
+
+    format(null, 1000L, "0:01");
+    format("second", 1000L, "16:40");
+    format("minute", -100L, "-1:40:00");
+    format("hour", 1L, "1:00:00");
+    format("day", 1L, "24:00:00");
+    format("year", 1L, "8765:45:36");
+
+  }
+
+  @Test
+  public void testParse() {
+
+    parse(null, 1000L, "0:01");
+    parse("second", 1001L, "16:41");
+    parse("minute", -16L, "-16:41");
+    parse("hour", 1L, "1:00:00");
+    parse("day", 1L, "24:00:00");
+    parse("year", 1L, "8765:45:36");
+  }
+
+  private void format(final String unit, final Long aLong, final String string) {
+    final UIIn input = new UIIn();
+    final String info = "Formatting numbers:"
+        + " unit='" + unit + "'"
+        + " long='" + aLong + "'";
+    final String result;
+    if (unit != null) {
+      input.getAttributes().put(Attributes.unit.getName(), unit);
+    }
+    result = converter.getAsString(null, input, aLong);
+    Assert.assertEquals(info, string, result);
+  }
+
+  private void parse(final String unit, final Long aLong, final String string) {
+    final UIIn input = new UIIn();
+    final String info = "Parsing numbers:"
+        + " unit='" + unit + "'"
+        + " string='" + string + "'";
+    final Long result;
+    if (unit != null) {
+      input.getAttributes().put(Attributes.unit.getName(), unit);
+    }
+    result = (Long) converter.getAsObject(null, input, string);
+    Assert.assertEquals(info, aLong, result);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
new file mode 100644
index 0000000..0fa9ca8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/AbstractTobagoTestBase.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
+import org.apache.myfaces.test.mock.MockFacesContext;
+import org.apache.myfaces.test.mock.MockHttpServletRequest;
+import org.apache.myfaces.tobago.component.UIButton;
+import org.apache.myfaces.tobago.component.UIIn;
+import org.apache.myfaces.tobago.component.UILink;
+import org.apache.myfaces.tobago.component.UIOut;
+import org.apache.myfaces.tobago.component.UIPanel;
+import org.apache.myfaces.tobago.component.UIPopup;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.apache.myfaces.tobago.context.TobagoContext;
+import org.apache.myfaces.tobago.internal.mock.faces.MockTheme;
+import org.apache.myfaces.tobago.internal.util.MimeTypeUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.Locale;
+
+/**
+ * <p>Abstract JUnit test case base class, which sets up the JavaServer Faces
+ * mock object environment for a particular simulated request.
+ * </p>
+ * <p>
+ * This is a port of the class AbstractJsfTestCase from myfaces-test12 to JUnit 4.
+ * It also contains Tobago specifics.
+ * </p>
+ */
+
+public abstract class AbstractTobagoTestBase extends AbstractJsfTestCase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractTobagoTestBase.class);
+
+  /**
+   * <p>Set up instance variables required by Tobago test cases.</p>
+   */
+  @Override
+  @Before
+  public void setUp() throws Exception {
+
+    super.setUp();
+
+    // Tobago specific extensions
+
+    final TobagoConfigImpl tobagoConfig = TobagoConfigMergingUnitTest.loadAndMerge("tobago-config-for-unit-tests.xml");
+    final ThemeImpl theme = new MockTheme("default", "Default Mock Theme", Collections.<Theme>emptyList());
+    final ThemeImpl one = new MockTheme("one", "Mock Theme One", Collections.singletonList((Theme) theme));
+    tobagoConfig.addAvailableTheme(theme);
+    tobagoConfig.addAvailableTheme(one);
+    tobagoConfig.resolveThemes();
+    tobagoConfig.initProjectState(servletContext);
+    tobagoConfig.initDefaultValidatorInfo();
+    servletContext.setAttribute(TobagoConfig.TOBAGO_CONFIG, tobagoConfig);
+    try {
+      MimeTypeUtils.init(servletContext);
+    } catch (IllegalStateException e) {
+      // ignoring double call
+    }
+
+    final TobagoContext tobagoContext = new TobagoContext();
+    tobagoContext.setTheme(one);
+    facesContext.getViewRoot().setLocale(Locale.ENGLISH);
+    request.setAttribute(TobagoContext.BEAN_NAME, tobagoContext);
+
+    // XXX is there a better way? Get it from Tobagos generated faces-config.xml?
+    application.addComponent(UIIn.COMPONENT_TYPE, UIIn.class.getName());
+    application.addComponent(UIOut.COMPONENT_TYPE, UIOut.class.getName());
+    application.addComponent(UIPanel.COMPONENT_TYPE, UIPanel.class.getName());
+    application.addComponent(
+        javax.faces.component.UICommand.COMPONENT_TYPE, javax.faces.component.UICommand.class.getName());
+    application.addComponent(UILink.COMPONENT_TYPE, UILink.class.getName());
+    application.addComponent(UIButton.COMPONENT_TYPE, UIButton.class.getName());
+    application.addComponent(UIPopup.COMPONENT_TYPE, UIPopup.class.getName());
+
+    tobagoConfig.lock();
+  }
+
+  @Override
+  @After
+  public void tearDown() throws Exception {
+    super.tearDown();
+  }
+
+  public MockFacesContext getFacesContext() {
+    return facesContext;
+  }
+
+  public MockHttpServletRequest getRequest() {
+    return request;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigMergingUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigMergingUnitTest.java
new file mode 100644
index 0000000..58afc32
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigMergingUnitTest.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class TobagoConfigMergingUnitTest {
+
+  @Test
+  public void testPreventFrameAttacksCascadingDefault()
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final TobagoConfigImpl config = loadAndMerge(
+        "tobago-config-merge-0.xml",
+        "tobago-config-merge-1.xml");
+
+    Assert.assertFalse(config.isPreventFrameAttacks());
+  }
+
+  @Test
+  public void testPreventFrameAttacks()
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final TobagoConfigImpl config = loadAndMerge("tobago-config-merge-0.xml");
+
+    Assert.assertFalse(config.isPreventFrameAttacks());
+  }
+
+  @Test
+  public void testPreventFrameAttacksDefault()
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final TobagoConfigImpl config = loadAndMerge("tobago-config-merge-1.xml");
+
+    Assert.assertTrue(config.isPreventFrameAttacks());
+  }
+
+  @Test
+  public void testContentSecurityPolicy()
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final TobagoConfigImpl config = loadAndMerge(
+        "tobago-config-merge-0.xml");
+
+    Assert.assertTrue(config.getContentSecurityPolicy().getMode() == ContentSecurityPolicy.Mode.ON);
+    Assert.assertEquals(1, config.getContentSecurityPolicy().getDirectiveList().size());
+    Assert.assertEquals("default-src 'self'", config.getContentSecurityPolicy().getDirectiveList().get(0));
+  }
+
+  @Test
+  public void testContentSecurityPolicyExtend()
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final TobagoConfigImpl config = loadAndMerge(
+        "tobago-config-merge-0.xml",
+        "tobago-config-merge-1.xml");
+
+    Assert.assertTrue(config.getContentSecurityPolicy().getMode() == ContentSecurityPolicy.Mode.REPORT_ONLY);
+    Assert.assertEquals(2, config.getContentSecurityPolicy().getDirectiveList().size());
+    Assert.assertEquals("default-src 'self'", config.getContentSecurityPolicy().getDirectiveList().get(0));
+    Assert.assertEquals("image-src http://apache.org", config.getContentSecurityPolicy().getDirectiveList().get(1));
+  }
+
+  @Test
+  public void testContentSecurityPolicyOff()
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final TobagoConfigImpl config = loadAndMerge(
+        "tobago-config-merge-0.xml",
+        "tobago-config-merge-1.xml",
+        "tobago-config-merge-2.xml");
+
+    Assert.assertTrue(config.getContentSecurityPolicy().getMode() == ContentSecurityPolicy.Mode.OFF);
+    Assert.assertEquals(2, config.getContentSecurityPolicy().getDirectiveList().size());
+  }
+
+  @Test
+  public void testMimeTypes()
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final TobagoConfigImpl config = loadAndMerge(
+        "tobago-config-merge-0.xml",
+        "tobago-config-merge-1.xml",
+        "tobago-config-merge-2.xml");
+
+    final Map<String, String> mimeTypes = config.getMimeTypes();
+    Assert.assertTrue(mimeTypes.size() == 3);
+    Assert.assertEquals("test/one", mimeTypes.get("test-1"));
+    Assert.assertEquals("test/zwei", mimeTypes.get("test-2"));
+    Assert.assertEquals("test/three", mimeTypes.get("test-3"));
+  }
+
+  public static TobagoConfigImpl loadAndMerge(final String... names)
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+
+    final List<TobagoConfigFragment> list = new ArrayList<TobagoConfigFragment>();
+
+    for (final String name : names) {
+      final URL url = TobagoConfigMergingUnitTest.class.getClassLoader().getResource(name);
+      final TobagoConfigParser parser = new TobagoConfigParser();
+      list.add(parser.parse(url));
+    }
+
+    final TobagoConfigSorter sorter = new TobagoConfigSorter(list);
+    sorter.sort();
+    return sorter.merge();
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParserUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParserUnitTest.java
new file mode 100644
index 0000000..1f93938
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigParserUnitTest.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.junit.Assert;
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class TobagoConfigParserUnitTest {
+
+  @Test
+  public void testParser() throws Exception {
+    generalTest("tobago-config-2.0.xml");
+  }
+
+  @Test
+  public void testParserUntidy() throws Exception {
+    generalTest("tobago-config-untidy-2.0.xml");
+  }
+
+  private void generalTest(final String name)
+      throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+    final URL url = getClass().getClassLoader().getResource(name);
+    final TobagoConfigParser parser = new TobagoConfigParser();
+
+    final TobagoConfigFragment fragment = parser.parse(url);
+
+    Assert.assertEquals("my-name", fragment.getName());
+
+    Assert.assertEquals(1, fragment.getAfter().size());
+    Assert.assertEquals("my-after", fragment.getAfter().get(0));
+
+    Assert.assertEquals(2, fragment.getBefore().size());
+    Assert.assertEquals("my-before-1", fragment.getBefore().get(0));
+    Assert.assertEquals("my-before-2", fragment.getBefore().get(1));
+
+    Assert.assertEquals(false, fragment.getCreateSessionSecret().booleanValue());
+    Assert.assertEquals(false, fragment.getCheckSessionSecret().booleanValue());
+    Assert.assertEquals(false, fragment.getPreventFrameAttacks().booleanValue());
+
+    Assert.assertEquals(2, fragment.getContentSecurityPolicy().getDirectiveList().size());
+    Assert.assertEquals("default-src 'self'", fragment.getContentSecurityPolicy().getDirectiveList().get(0));
+    Assert.assertEquals("frame-src http://apache.org", fragment.getContentSecurityPolicy().getDirectiveList().get(1));
+
+    Assert.assertEquals(2, fragment.getRenderersConfig().getRendererConfigs().size());
+    Assert.assertTrue(fragment.getRenderersConfig().isMarkupSupported("myRenderer-1", "my-markup-1"));
+    Assert.assertTrue(fragment.getRenderersConfig().isMarkupSupported("myRenderer-2", "my-markup-2-1"));
+    Assert.assertTrue(fragment.getRenderersConfig().isMarkupSupported("myRenderer-2", "my-markup-2-2"));
+
+    Assert.assertEquals(2, fragment.getThemeDefinitions().size());
+    final ThemeImpl theme1 = fragment.getThemeDefinitions().get(0);
+    Assert.assertEquals("my-theme-1", theme1.getName());
+    Assert.assertEquals("My Theme 1", theme1.getDisplayName());
+    Assert.assertTrue(theme1.isVersioned());
+    Assert.assertTrue(theme1.getRenderersConfig().isMarkupSupported("themeRenderer", "theme-markup"));
+    Assert.assertTrue(theme1.getProductionResources().isProduction());
+    Assert.assertEquals("script.js", theme1.getProductionResources().getScriptList().get(0).getName());
+    Assert.assertEquals("style.css", theme1.getProductionResources().getStyleList().get(0).getName());
+
+    final ThemeImpl theme2 = fragment.getThemeDefinitions().get(1);
+    Assert.assertEquals("my-theme-2", theme2.getName());
+    Assert.assertEquals("my-theme-1", theme2.getFallbackName());
+    Assert.assertFalse(theme2.isVersioned());
+    Assert.assertFalse(theme2.getResources().isProduction());
+    Assert.assertEquals(0, theme2.getResources().getScriptList().size());
+    Assert.assertEquals(0, theme2.getResources().getStyleList().size());
+    Assert.assertEquals(0, theme2.getProductionResources().getScriptList().size());
+    Assert.assertEquals(0, theme2.getProductionResources().getStyleList().size());
+
+    Assert.assertFalse("set-nosniff-header", fragment.getSetNosniffHeader());
+  }
+
+  @Test
+  public void testParserFor10() throws Exception {
+    final URL url = getClass().getClassLoader().getResource("tobago-config-1.0.30.xml");
+    final TobagoConfigParser parser = new TobagoConfigParser();
+    final TobagoConfigFragment fragment = parser.parse(url);
+    Assert.assertEquals("speyside", fragment.getDefaultThemeName());
+  }
+
+  @Test
+  public void testFailParserFor10() throws Exception {
+    final URL url = getClass().getClassLoader().getResource("tobago-config-fail-1.0.30.xml");
+    final TobagoConfigParser parser = new TobagoConfigParser();
+    try {
+      parser.parse(url);
+      Assert.fail("No SAXParseException thrown!");
+    } catch (final SAXException e) {
+      // okay
+    }
+  }
+
+  @Test
+  public void testParserFor15() throws Exception {
+    final URL url = getClass().getClassLoader().getResource("tobago-config-1.5.xml");
+    final TobagoConfigParser parser = new TobagoConfigParser();
+    final TobagoConfigFragment fragment = parser.parse(url);
+    Assert.assertEquals("speyside", fragment.getDefaultThemeName());
+  }
+
+  @Test
+  public void testFailParserFor15() throws Exception {
+    final URL url = getClass().getClassLoader().getResource("tobago-config-fail-1.5.xml");
+    final TobagoConfigParser parser = new TobagoConfigParser();
+    try {
+      parser.parse(url);
+      Assert.fail("No SAXParseException thrown!");
+    } catch (final SAXException e) {
+      // okay
+    }
+  }
+
+  @Test
+  public void testFailParserFor20() throws Exception {
+    final URL url = getClass().getClassLoader().getResource("tobago-config-fail-2.0.xml");
+    final TobagoConfigParser parser = new TobagoConfigParser();
+    try {
+      parser.parse(url);
+      Assert.fail("No SAXParseException thrown!");
+    } catch (final SAXException e) {
+      // okay
+    }
+  }
+
+  @Test
+  public void testFailParserForUnknownVersion() throws Exception {
+    final URL url = getClass().getClassLoader().getResource("tobago-config-fail-unknown-version.xml");
+    final TobagoConfigParser parser = new TobagoConfigParser();
+    try {
+      parser.parse(url);
+      Assert.fail("No SAXParseException thrown!");
+    } catch (final SAXException e) {
+      // okay
+    }
+  }
+
+  @Test
+  public void testUniqueness() throws IllegalAccessException {
+    final Field[] all = TobagoConfigParser.class.getFields();
+    final List<Field> fields = new ArrayList<Field>();
+    for (final Field field : all) {
+      if (field.getType().equals(Integer.TYPE)) {
+        fields.add(field);
+      }
+    }
+    // uniqueness
+    final TobagoConfigParser dummy = new TobagoConfigParser();
+    final Set<Integer> hashCodes = new HashSet<Integer>();
+    for (final Field field : fields) {
+      hashCodes.add(field.getInt(dummy));
+    }
+    Assert.assertEquals("All used hash codes must be unique", fields.size(), hashCodes.size());
+
+    // check hash code values
+    for (final Field field : fields) {
+      final int hash = field.getInt(dummy);
+      final String name = field.getName().toLowerCase().replace('_', '-');
+      Assert.assertEquals("Are the constants correct?", name.hashCode(), hash);
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigSorterUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigSorterUnitTest.java
new file mode 100644
index 0000000..8d19fc2
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/config/TobagoConfigSorterUnitTest.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.config;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TobagoConfigSorterUnitTest {
+
+  @Test
+  public void testCompare() {
+
+    // config + names
+
+    final TobagoConfigFragment a = new TobagoConfigFragment();
+    a.setName("a");
+
+    final TobagoConfigFragment b = new TobagoConfigFragment();
+    b.setName("b");
+
+    final TobagoConfigFragment c = new TobagoConfigFragment();
+    c.setName("c");
+
+    final TobagoConfigFragment d = new TobagoConfigFragment();
+    d.setName("d");
+
+    final TobagoConfigFragment e = new TobagoConfigFragment();
+    e.setName("e");
+
+    final TobagoConfigFragment f = new TobagoConfigFragment();
+    f.setName("f");
+
+    final TobagoConfigFragment m = new TobagoConfigFragment();
+    m.setName("m");
+
+    final TobagoConfigFragment n = new TobagoConfigFragment();
+    n.setName("n");
+
+    // unnamed
+    final TobagoConfigFragment u1 = new TobagoConfigFragment();
+    final TobagoConfigFragment u2 = new TobagoConfigFragment();
+    final TobagoConfigFragment u3 = new TobagoConfigFragment();
+
+    // before
+    a.getBefore().add("b");
+    b.getBefore().add("c");
+
+    u1.getBefore().add("d");
+    u2.getBefore().add("d");
+
+    u2.getBefore().add("y"); // not relevant
+
+    // after
+    e.getAfter().add("d");
+    f.getAfter().add("e");
+
+    u1.getAfter().add("c");
+    u2.getAfter().add("c");
+
+    u2.getAfter().add("z"); // not relevant
+
+    n.getAfter().add("m");
+
+    final List<TobagoConfigFragment> list = new ArrayList<TobagoConfigFragment>();
+    list.add(a);
+    list.add(b);
+    list.add(c);
+    list.add(d);
+    list.add(e);
+    list.add(f);
+    list.add(u1);
+    list.add(u2);
+    list.add(u3);
+    list.add(m);
+    list.add(n);
+
+    final TobagoConfigSorter sorter = new TobagoConfigSorter(list);
+    sorter.createRelevantPairs();
+
+    Assert.assertEquals(9, sorter.getPairs().size()); // all but these with "z" and "y"
+
+    sorter.makeTransitive();
+
+    Assert.assertEquals(28, sorter.getPairs().size());
+
+    sorter.ensureIrreflexive();
+
+    sorter.ensureAntiSymmetric();
+
+    sorter.sort0();
+
+    Assert.assertEquals(a, list.get(0));
+    Assert.assertEquals(b, list.get(1));
+    Assert.assertEquals(c, list.get(2));
+    Assert.assertEquals(u1, list.get(3));
+    Assert.assertEquals(u2, list.get(4));
+    Assert.assertEquals(d, list.get(5));
+    Assert.assertEquals(e, list.get(6));
+    Assert.assertEquals(f, list.get(7));
+    Assert.assertEquals(u3, list.get(8));
+    Assert.assertEquals(m, list.get(9));
+    Assert.assertEquals(n, list.get(10));
+  }
+
+  @Test
+  public void testCycle() {
+
+    // config + names
+
+    final TobagoConfigFragment a = new TobagoConfigFragment();
+    a.setName("a");
+
+    final TobagoConfigFragment b = new TobagoConfigFragment();
+    b.setName("b");
+
+    // before
+    a.getBefore().add("b");
+    b.getBefore().add("a");
+
+    final List<TobagoConfigFragment> list = new ArrayList<TobagoConfigFragment>();
+    list.add(a);
+    list.add(b);
+
+    final TobagoConfigSorter sorter = new TobagoConfigSorter(list);
+    sorter.createRelevantPairs();
+
+    Assert.assertEquals(2, sorter.getPairs().size()); // all but these with "z" and "y"
+
+    sorter.makeTransitive();
+
+    try {
+      sorter.ensureIrreflexive();
+      sorter.ensureAntiSymmetric();
+
+      Assert.fail("Cycle was not found");
+    } catch (final RuntimeException e) {
+      // must find the cycle
+    }
+  }
+
+  @Test
+  public void testCycle2() {
+
+    // config + names
+
+    final TobagoConfigFragment a = new TobagoConfigFragment();
+    a.setName("a");
+
+    final TobagoConfigFragment b = new TobagoConfigFragment();
+    b.setName("b");
+
+    // before
+    a.getBefore().add("b");
+    // after
+    a.getAfter().add("b");
+
+    final List<TobagoConfigFragment> list = new ArrayList<TobagoConfigFragment>();
+    list.add(a);
+    list.add(b);
+
+    final TobagoConfigSorter sorter = new TobagoConfigSorter(list);
+    sorter.createRelevantPairs();
+
+    Assert.assertEquals(2, sorter.getPairs().size()); // all but these with "z" and "y"
+
+    sorter.makeTransitive();
+
+    try {
+      sorter.ensureIrreflexive();
+      sorter.ensureAntiSymmetric();
+
+      Assert.fail("Cycle was not found");
+    } catch (final RuntimeException e) {
+      // must find the cycle
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/context/ThemeParserUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/context/ThemeParserUnitTest.java
new file mode 100644
index 0000000..40883e1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/context/ThemeParserUnitTest.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.context;
+
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.apache.myfaces.tobago.context.ThemeResources;
+import org.apache.myfaces.tobago.internal.config.TobagoConfigParser;
+import org.junit.Assert;
+import org.junit.Test;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.Enumeration;
+
+public class ThemeParserUnitTest {
+
+  @Test
+  public void test() throws IOException, SAXException, ParserConfigurationException, URISyntaxException {
+    final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+    Enumeration<URL> urls = classLoader.getResources("theme-config.xml");
+
+    final TobagoConfigParser parser = new TobagoConfigParser();
+    ThemeImpl theme = null;
+    if (urls.hasMoreElements()) {
+      final URL themeUrl = urls.nextElement();
+      theme = parser.parse(themeUrl).getThemeDefinitions().get(0);
+      Assert.assertEquals("test", theme.getName());
+      Assert.assertNotNull(theme.getResources());
+      Assert.assertNotNull(theme.getProductionResources());
+      final ThemeResources resources = theme.getResources();
+      final ThemeResources productionResources = theme.getProductionResources();
+
+      Assert.assertEquals(1, resources.getScriptList().size());
+      Assert.assertEquals("script/tobago.js", resources.getScriptList().get(0).getName());
+//      Assert.assertEquals("script/tobago-console.js", resources.getScriptList().get(1).getName());
+
+      Assert.assertEquals(1, productionResources.getScriptList().size());
+    } else {
+      Assert.fail();
+    }
+
+    urls = classLoader.getResources("theme-config2.xml");
+
+    ThemeImpl theme2 = null;
+    if (urls.hasMoreElements()) {
+      final URL themeUrl = urls.nextElement();
+      theme2 = parser.parse(themeUrl).getThemeDefinitions().get(0);
+      Assert.assertEquals("test2", theme2.getName());
+      Assert.assertNotNull(theme2.getResources());
+      Assert.assertEquals(1, theme2.getResources().getScriptList().size());
+      Assert.assertEquals(1, theme2.getResources().getStyleList().size());
+    } else {
+      Assert.fail();
+    }
+
+    urls = classLoader.getResources("theme-config3.xml");
+
+    ThemeImpl theme3 = null;
+    if (urls.hasMoreElements()) {
+      final URL themeUrl = urls.nextElement();
+      theme3 = parser.parse(themeUrl).getThemeDefinitions().get(0);
+      Assert.assertEquals("test3", theme3.getName());
+      Assert.assertEquals(0, theme3.getResources().getScriptList().size());
+      Assert.assertEquals(0, theme3.getResources().getStyleList().size());
+    } else {
+      Assert.fail();
+    }
+
+    urls = classLoader.getResources("theme-config4.xml");
+
+    ThemeImpl theme4 = null;
+    if (urls.hasMoreElements()) {
+      final URL themeUrl = urls.nextElement();
+      theme4 = parser.parse(themeUrl).getThemeDefinitions().get(0);
+      Assert.assertEquals("test4", theme4.getName());
+      Assert.assertEquals(0, theme4.getResources().getScriptList().size());
+      Assert.assertEquals(0, theme4.getResources().getStyleList().size());
+    } else {
+      Assert.fail();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/internal/renderkit/CommandUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/internal/renderkit/CommandUnitTest.java
new file mode 100644
index 0000000..c2a26a3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/internal/renderkit/CommandUnitTest.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.internal.renderkit;
+
+import org.apache.myfaces.tobago.internal.renderkit.Collapse;
+import org.apache.myfaces.tobago.internal.renderkit.Command;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.internal.util.JsonUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CommandUnitTest {
+
+  @Test
+  public void test() {
+
+    final Command a = new Command();
+    a.setAction("a action");
+    a.setCollapse(new Collapse(Collapse.Action.show, "a collapse"));
+    a.setConfirmation("a conf");
+    a.setExecute("a execute");
+
+    final Command b = new Command();
+    b.setAction("b action");
+    b.setCollapse(new Collapse(Collapse.Action.show, "b collapse"));
+    b.setConfirmation("b conf");
+    b.setExecute("b execute");
+
+    a.merge(b);
+
+    Assert.assertEquals(
+        ("{'click':"
+            + "{'action':'a action',"
+            + "'execute':'a execute b execute'"
+            + ",'collapse':{'transition':'show','forId':'a collapse'}"
+            + ",'confirmation':'a conf'}}")
+            .replaceAll("'", "\""),
+        JsonUtils.encode(new CommandMap(a)));
+
+    final Command c = new Command();
+
+    c.merge(b);
+
+    Assert.assertEquals(
+        ("{'click':"
+            + "{'action':'b action',"
+            + "'execute':'b execute',"
+            + "'collapse':{'transition':'show','forId':'b collapse'},"
+            + "'confirmation':'b conf'}}")
+            .replaceAll("'", "\""),
+        JsonUtils.encode(new CommandMap(c)));
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/GridUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/GridUnitTest.java
new file mode 100644
index 0000000..6e112e5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/GridUnitTest.java
@@ -0,0 +1,233 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import org.apache.myfaces.tobago.layout.LayoutTokens;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class GridUnitTest {
+
+  @Test
+  public void test1x1() {
+
+    final Grid grid = new Grid(LayoutTokens.parse("*"), LayoutTokens.parse("*"));
+    Assert.assertEquals(1, grid.getColumns().getSize());
+    Assert.assertEquals(1, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┌─┐\n"
+        + "│◌│\n"
+        + "└─┘\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 1);
+    Assert.assertEquals(1, grid.getColumns().getSize());
+    Assert.assertEquals(1, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┓\n"
+        + "┃█┃\n"
+        + "┗━┛\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 1);
+    Assert.assertEquals(1, grid.getColumns().getSize());
+    Assert.assertEquals(2, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┓\n"
+        + "┃█┃\n"
+        + "┣━┫\n"
+        + "┃█┃\n"
+        + "┗━┛\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 2);
+    Assert.assertEquals(1, grid.getColumns().getSize());
+    Assert.assertEquals(4, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┓\n"
+        + "┃█┃\n"
+        + "┣━┫\n"
+        + "┃█┃\n"
+        + "┣━┫\n"
+        + "┃█┃\n"
+        + "┠─┨\n"
+        + "┃⬇┃\n"
+        + "┗━┛\n", grid.gridAsString());
+
+    // with warning
+    grid.add(new OriginCell(null), 2, 1);
+    Assert.assertEquals(1, grid.getColumns().getSize());
+    Assert.assertEquals(5, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┓\n"
+        + "┃█┃\n"
+        + "┣━┫\n"
+        + "┃█┃\n"
+        + "┣━┫\n"
+        + "┃█┃\n"
+        + "┠─┨\n"
+        + "┃⬇┃\n"
+        + "┣━┫\n"
+        + "┃✖┃\n"
+        + "┗━┛\n", grid.gridAsString());
+  }
+
+  @Test
+  public void test2x1() {
+
+    final Grid grid = new Grid(LayoutTokens.parse("*;*"), LayoutTokens.parse("*"));
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(1, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┌─┬─┐\n"
+        + "│◌│◌│\n"
+        + "└─┴─┘\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 1);
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(1, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┱─┐\n"
+        + "┃█┃◌│\n"
+        + "┗━┹─┘\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 1);
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(1, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┳━┓\n"
+        + "┃█┃█┃\n"
+        + "┗━┻━┛\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 2, 2);
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(3, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┳━┓\n"
+        + "┃█┃█┃\n"
+        + "┣━╇━┫\n"
+        + "┃█│➞┃\n"
+        + "┠─┼─┨\n"
+        + "┃⬇│⬇┃\n"
+        + "┗━┷━┛\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 2);
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(5, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┳━┓\n"
+        + "┃█┃█┃\n"
+        + "┣━╇━┫\n"
+        + "┃█│➞┃\n"
+        + "┠─┼─┨\n"
+        + "┃⬇│⬇┃\n"
+        + "┣━╈━┩\n"
+        + "┃█┃◌│\n"
+        + "┠─╂─┤\n"
+        + "┃⬇┃◌│\n"
+        + "┗━┹─┘\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 1);
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(5, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┳━┓\n"
+        + "┃█┃█┃\n"
+        + "┣━╇━┫\n"
+        + "┃█│➞┃\n"
+        + "┠─┼─┨\n"
+        + "┃⬇│⬇┃\n"
+        + "┣━╈━┫\n"
+        + "┃█┃█┃\n"
+        + "┠─╊━┩\n"
+        + "┃⬇┃◌│\n"
+        + "┗━┹─┘\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 2);
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(6, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┳━┓\n"
+        + "┃█┃█┃\n"
+        + "┣━╇━┫\n"
+        + "┃█│➞┃\n"
+        + "┠─┼─┨\n"
+        + "┃⬇│⬇┃\n"
+        + "┣━╈━┫\n"
+        + "┃█┃█┃\n"
+        + "┠─╊━┫\n"
+        + "┃⬇┃█┃\n"
+        + "┡━╉─┨\n"
+        + "│◌┃⬇┃\n"
+        + "└─┺━┛\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 2, 1);
+    // fehler
+    Assert.assertEquals(2, grid.getColumns().getSize());
+    Assert.assertEquals(6, grid.getRows().getSize());
+  }
+
+  @Test
+  public void test5x5() {
+
+    final Grid grid = new Grid(LayoutTokens.parse("*;*;*;*;*"), LayoutTokens.parse("*;*;*;*;*"));
+    Assert.assertEquals(5, grid.getColumns().getSize());
+    Assert.assertEquals(5, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┌─┬─┬─┬─┬─┐\n"
+        + "│◌│◌│◌│◌│◌│\n"
+        + "├─┼─┼─┼─┼─┤\n"
+        + "│◌│◌│◌│◌│◌│\n"
+        + "├─┼─┼─┼─┼─┤\n"
+        + "│◌│◌│◌│◌│◌│\n"
+        + "├─┼─┼─┼─┼─┤\n"
+        + "│◌│◌│◌│◌│◌│\n"
+        + "├─┼─┼─┼─┼─┤\n"
+        + "│◌│◌│◌│◌│◌│\n"
+        + "└─┴─┴─┴─┴─┘\n", grid.gridAsString());
+
+    grid.add(new OriginCell(null), 1, 2);
+    grid.add(new OriginCell(null), 1, 3);
+    grid.add(new OriginCell(null), 1, 1);
+    grid.add(new OriginCell(null), 2, 1);
+    grid.add(new OriginCell(null), 3, 1);
+    grid.add(new OriginCell(null), 1, 1);
+    grid.add(new OriginCell(null), 1, 1);
+    grid.add(new OriginCell(null), 1, 3);
+    grid.add(new OriginCell(null), 1, 1);
+    grid.add(new OriginCell(null), 3, 1);
+    grid.add(new OriginCell(null), 1, 2);
+    grid.add(new OriginCell(null), 2, 1);
+    grid.add(new OriginCell(null), 1, 1);
+    Assert.assertEquals(5, grid.getColumns().getSize());
+    Assert.assertEquals(5, grid.getRows().getSize());
+    Assert.assertEquals(""
+        + "┏━┳━┳━┳━┯━┓\n"
+        + "┃█┃█┃█┃█│➞┃\n"
+        + "┠─╂─╊━╇━┿━┫\n"
+        + "┃⬇┃⬇┃█│➞│➞┃\n"
+        + "┣━╉─╊━╈━╈━┫\n"
+        + "┃█┃⬇┃█┃█┃█┃\n"
+        + "┣━╇━╇━╉─╊━┫\n"
+        + "┃█│➞│➞┃⬇┃█┃\n"
+        + "┣━┿━╈━╉─╂─┨\n"
+        + "┃█│➞┃█┃⬇┃⬇┃\n"
+        + "┗━┷━┻━┻━┻━┛\n", grid.gridAsString());
+  }
+}
+
+
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/MathUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/MathUtilsUnitTest.java
new file mode 100644
index 0000000..6e73269
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/layout/MathUtilsUnitTest.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.layout;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MathUtilsUnitTest {
+
+  @Test
+  public void testAdjust() {
+    final double[] d = {6.3, 7.9, 8.7, 9.2, 10.3, 11.6};
+    MathUtils.adjustRemainders(d, 0.0);
+    Assert.assertArrayEquals("mixed", new double[]{6, 8, 9, 9, 10, 12}, d, MathUtils.EPSILON);
+  }
+
+  @Test
+  public void testAdjust999() {
+    final double[] d = {9.9, 9.9, 9.9, 9.9, 9.9, 9.9, 9.9, 9.9, 9.9, 9.9};
+    MathUtils.adjustRemainders(d, 0.0);
+    Assert.assertArrayEquals(
+        "9.9, ...", new double[]{9, 10, 10, 10, 10, 10, 10, 10, 10, 10}, d, MathUtils.EPSILON);
+  }
+
+  @Test
+  public void testAdjust111() {
+    final double[] d = {1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1};
+    MathUtils.adjustRemainders(d, 0.0);
+    Assert.assertArrayEquals(
+        "1.1, ...", new double[]{1, 2, 1, 1, 1, 1, 1, 1, 1, 1}, d, MathUtils.EPSILON);
+  }
+
+  @Test
+  public void testAdjust133() {
+    final double[] d = {1, 1, 1, 1.333333333, 1.333333333, 1.333333333, 1, 1, 1};
+    MathUtils.adjustRemainders(d, 0.0);
+    Assert.assertArrayEquals(
+        "1, ..., 1.333...", new double[]{1, 1, 1, 1, 2, 1, 1, 1, 1}, d, MathUtils.EPSILON);
+  }
+
+  @Test
+  public void testInitialBias() {
+    final double[] d = {5.5};
+    MathUtils.adjustRemainders(d, 0.5);
+    Assert.assertArrayEquals("initial bias", new double[]{5}, d, MathUtils.EPSILON);
+  }
+
+
+  @Test
+  public void testIsZero() {
+    Assert.assertTrue(MathUtils.isZero(0));
+    Assert.assertFalse(MathUtils.isZero(1.0/1000.0));
+    Assert.assertTrue(MathUtils.isZero(1.0/1000000000.0));
+    Assert.assertTrue(MathUtils.isZero(-1.0/1000000000.0));
+  }
+
+  @Test
+  public void testIsNotZero() {
+    Assert.assertFalse(MathUtils.isNotZero(0));
+    Assert.assertTrue(MathUtils.isNotZero(1.0/1000.0));
+    Assert.assertFalse(MathUtils.isNotZero(1.0/1000000000.0));
+    Assert.assertFalse(MathUtils.isNotZero(-1.0/1000000000.0));
+  }
+
+  @Test
+  public void testIsInteger() {
+    Assert.assertTrue(MathUtils.isInteger(1.0));
+    Assert.assertTrue(MathUtils.isInteger(0.0));
+    Assert.assertTrue(MathUtils.isInteger(1.0/1000000000.0));
+    Assert.assertFalse(MathUtils.isInteger(1.0/1000.0));
+  }
+
+  @Test
+  public void testIsNotInteger() {
+    Assert.assertFalse(MathUtils.isNotInteger(1.0));
+    Assert.assertFalse(MathUtils.isNotInteger(0.0));
+    Assert.assertFalse(MathUtils.isNotInteger(1.0/1000000000.0));
+    Assert.assertTrue(MathUtils.isNotInteger(1.0/1000.0));
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/faces/MockRenderersConfig.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/faces/MockRenderersConfig.java
new file mode 100644
index 0000000..8a1c982
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/faces/MockRenderersConfig.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.mock.faces;
+
+import org.apache.myfaces.tobago.internal.config.RendererConfig;
+import org.apache.myfaces.tobago.internal.config.RenderersConfig;
+
+import java.util.List;
+
+public class MockRenderersConfig implements RenderersConfig {
+
+  /**
+   * To keep it simple, we allow every value shorter than 10 characters.
+   */
+  @Override
+  public boolean isMarkupSupported(final String rendererName, final String markup) {
+    return markup.length() < 10;
+  }
+
+  @Override
+  public List<RendererConfig> getRendererConfigs() {
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/faces/MockTheme.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/faces/MockTheme.java
new file mode 100644
index 0000000..a786548
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/faces/MockTheme.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.mock.faces;
+
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.ThemeImpl;
+import org.apache.myfaces.tobago.internal.config.RenderersConfig;
+
+import java.util.List;
+
+public class MockTheme extends ThemeImpl {
+
+  private String name;
+
+  private String displayName;
+
+  private List<Theme> fallbackThemeList;
+
+  private RenderersConfig config = new MockRenderersConfig();
+
+  private boolean versioned;
+
+  private String version;
+
+  public MockTheme(final String name, final String displayName, final List<Theme> fallbackThemeList) {
+    this.name = name;
+    this.displayName = displayName;
+    this.fallbackThemeList = fallbackThemeList;
+  }
+
+  @Override
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public List<Theme> getFallbackList() {
+    return fallbackThemeList;
+  }
+
+  @Override
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  @Override
+  public RenderersConfig getRenderersConfig() {
+    return config;
+  }
+
+  @Override
+  public String[] getScriptResources(final boolean production) {
+    return new String[0];
+  }
+
+  @Override
+  public String[] getStyleResources(final boolean production) {
+    return new String[0];
+  }
+
+  @Override
+  public boolean isVersioned() {
+    return versioned;
+  }
+
+  @Override
+  public void setVersioned(final boolean versioned) {
+    this.versioned = versioned;
+  }
+
+  @Override
+  public String getVersion() {
+    return version;
+  }
+
+  @Override
+  public void setVersion(final String version) {
+    this.version = version;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/servlet/MockHttpSession.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/servlet/MockHttpSession.java
new file mode 100644
index 0000000..1bde1bb
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/servlet/MockHttpSession.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.mock.servlet;
+
+import org.apache.commons.collections.iterators.IteratorEnumeration;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionContext;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class MockHttpSession implements HttpSession {
+
+  private Map attributes = new HashMap();
+
+  @Override
+  public Object getAttribute(final String s) {
+    return attributes.get(s);
+  }
+
+  @Override
+  public Enumeration getAttributeNames() {
+    return (new IteratorEnumeration(attributes.keySet().iterator()));
+  }
+
+  @Override
+  public long getCreationTime() {
+    return 0;
+  }
+
+  @Override
+  public String getId() {
+    return null;
+  }
+
+  @Override
+  public long getLastAccessedTime() {
+    return 0;
+  }
+
+  @Override
+  public int getMaxInactiveInterval() {
+    return 0;
+  }
+
+  /** @deprecated */
+  @Override
+  public HttpSessionContext getSessionContext() {
+    return null;
+  }
+
+  @Override
+  public Object getValue(final String s) {
+    return null;
+  }
+
+  @Override
+  public String[] getValueNames() {
+    return new String[0];
+  }
+
+  @Override
+  public void invalidate() {
+  }
+
+  @Override
+  public boolean isNew() {
+    return false;
+  }
+
+  @Override
+  public void putValue(final String s, final Object o) {
+  }
+
+  @Override
+  public void removeAttribute(final String s) {
+    attributes.remove(s);
+  }
+
+  @Override
+  public void removeValue(final String s) {
+  }
+
+  @Override
+  public void setAttribute(final String s, final Object o) {
+    attributes.put(s, o);
+  }
+
+  @Override
+  public void setMaxInactiveInterval(final int i) {
+  }
+
+  @Override
+  public ServletContext getServletContext() {
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/servlet/MockServletInputStream.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/servlet/MockServletInputStream.java
new file mode 100644
index 0000000..4275ae7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/mock/servlet/MockServletInputStream.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.mock.servlet;
+
+import javax.servlet.ServletInputStream;
+import java.io.IOException;
+
+public class MockServletInputStream extends ServletInputStream {
+
+  private byte[] body;
+
+  private int next;
+
+  public MockServletInputStream(final byte[] body) {
+    this.body = body;
+  }
+
+  @Override
+  public int read() throws IOException {
+    if (next < body.length) {
+      return body[next++];
+    } else {
+      return -1;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/JsonUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/JsonUtilsUnitTest.java
new file mode 100644
index 0000000..ce1a058
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/JsonUtilsUnitTest.java
@@ -0,0 +1,157 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.component.Attributes;
+import org.apache.myfaces.tobago.component.ClientBehaviors;
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.UIButton;
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.apache.myfaces.tobago.internal.context.DateTimeI18n;
+import org.apache.myfaces.tobago.internal.renderkit.Collapse;
+import org.apache.myfaces.tobago.internal.renderkit.Command;
+import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+import java.util.Locale;
+
+// using ' instead of " to make it better readable.
+
+public class JsonUtilsUnitTest extends AbstractTobagoTestBase {
+
+  @Test
+  public void empty() {
+    final CommandMap map = new CommandMap();
+    Assert.assertEquals("{}", JsonUtils.encode(map));
+  }
+
+  @Test
+  public void click() {
+    final CommandMap map = new CommandMap();
+    map.setClick(new Command(null, null, null, "", null, null, null, null, null, null));
+    final String expected = "{'click':{}}".replaceAll("'", "\"");
+    Assert.assertEquals(expected, JsonUtils.encode(map));
+  }
+
+  @Test
+  public void change() {
+    final CommandMap map = new CommandMap();
+    map.addCommand(ClientBehaviors.change, new Command(null, null, null, null, null, null, null, null, null, null));
+    final String expected = "{'change':{}}".replaceAll("'", "\"");
+    Assert.assertEquals(expected, JsonUtils.encode(map));
+  }
+
+  @Test
+  public void two() {
+    final CommandMap map = new CommandMap();
+    map.addCommand(ClientBehaviors.click, new Command(null, null, "target", null, null, null, null, null, null, null));
+    map.addCommand(ClientBehaviors.change, new Command(null, null, null, null, null, null, null, null, null, null));
+    final String expected = "{'click':{'target':'target'},'change':{}}".replaceAll("'", "\"");
+    Assert.assertEquals(expected, JsonUtils.encode(map));
+  }
+
+  @Test
+  public void transition() {
+    final CommandMap commandMap = new CommandMap();
+    commandMap.setClick(new Command(null, false, null, null, null, null, null, null, null, null));
+    final String expected = "{'click':{'transition':false}}".replaceAll("'", "\"");
+    Assert.assertEquals(expected, JsonUtils.encode(commandMap));
+  }
+
+  @Test
+  public void more() {
+    final CommandMap map = new CommandMap();
+    final AbstractUICommand command = (AbstractUICommand)
+        ComponentUtils.createComponent(facesContext, UIButton.COMPONENT_TYPE, RendererTypes.Button, "command");
+    ComponentUtils.setAttribute(command, Attributes.popupClose, "immediate");
+
+    map.setClick(new Command(
+        "ns:actionId",
+        false,
+        "_blank",
+        StringUtils.join(Arrays.asList("id1", "id2"), ' '),
+        StringUtils.join(Arrays.asList("id1", "id2"), ' '),
+        "id_focus",
+        "Really?", 1000, new Collapse(Collapse.Action.show, "myId"), true));
+    final String expected = (
+        "{"
+            + "'click':{"
+            + "'action':'ns:actionId',"
+            + "'transition':false,"
+            + "'target':'_blank',"
+            + "'execute':'id1 id2',"
+            + "'render':'id1 id2',"
+            + "'collapse':{"
+            + "'transition':'show',"
+            + "'forId':'myId'"
+            + "},"
+            + "'focus':'id_focus',"
+            + "'confirmation':'Really?',"
+            + "'delay':1000,"
+            + "'omit':true"
+            + "}"
+            + "}").replaceAll("'", "\"");
+    Assert.assertEquals(expected, JsonUtils.encode(map));
+  }
+
+  @Test
+  public void monthNames() {
+    final DateTimeI18n dateTimeI18n = DateTimeI18n.valueOf(Locale.GERMANY);
+    final String marchShort = dateTimeI18n.getMonthNamesShort()[2]; // different with JDK 1.8.0_51 and 1.8.0_60
+    final String expected
+        = ("{'monthNames':['Januar','Februar','März','April','Mai','Juni',"
+        + "'Juli','August','September','Oktober','November','Dezember'],"
+        + "'monthNamesShort':['Jan','Feb','" + marchShort + "','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'],"
+        + "'dayNames':['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],"
+        + "'dayNamesShort':['So','Mo','Di','Mi','Do','Fr','Sa'],"
+        + "'dayNamesMin':['So','Mo','Di','Mi','Do','Fr','Sa'],"
+        + "'firstDay':1}").replaceAll("'", "\"");
+
+    Assert.assertEquals(expected, JsonUtils.encode(dateTimeI18n));
+  }
+
+  @Test
+  public void decodeIntegerArray() {
+
+    Assert.assertEquals(Arrays.asList(1, 2, 3, 4), JsonUtils.decodeIntegerArray("[1,2,3,4]"));
+
+    Assert.assertEquals(Arrays.asList(1, 2, 3, 4), JsonUtils.decodeIntegerArray(" [ 1 , 2 , 3 , 4 ] "));
+
+    Assert.assertEquals(Arrays.asList(1), JsonUtils.decodeIntegerArray("[1]"));
+
+    Assert.assertEquals(Arrays.asList(), JsonUtils.decodeIntegerArray("[]"));
+
+    Assert.assertEquals(Arrays.asList(1000000000, 2, 3, 4), JsonUtils.decodeIntegerArray("[1000000000,2,3,4]"));
+
+    Assert.assertEquals(Arrays.asList(2, 3, 4), JsonUtils.decodeIntegerArray("[null,2,3,4]"));
+
+    Assert.assertEquals(Arrays.asList(), JsonUtils.decodeIntegerArray("1,2,3,4"));
+  }
+
+  @Test
+  public void encodeStringArray() {
+    Assert.assertEquals("[\"A-rập Xê-út (Tiếng A-rập)\"]", JsonUtils.encode(new String[]{"A-rập Xê-út (Tiếng A-rập)"}));
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/MimeTypeUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/MimeTypeUtilsUnitTest.java
new file mode 100644
index 0000000..9196be3
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/MimeTypeUtilsUnitTest.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MimeTypeUtilsUnitTest extends AbstractTobagoTestBase {
+
+  public static final String GIF = "http:///localhost:8080/demo/demo.gif";
+  public static final String PNG = "http:///localhost:8080/demo/demo.png";
+  public static final String JPG = "http:///localhost:8080/demo/demo.jpg";
+  public static final String JS = "http:///localhost:8080/demo/demo.js";
+  public static final String CSS = "http:///localhost:8080/demo/demo.css";
+  public static final String ICO = "http:///localhost:8080/demo/demo.ico";
+  public static final String HTML = "http:///localhost:8080/demo/demo.html";
+  public static final String HTM = "http:///localhost:8080/demo/demo.htm";
+  public static final String MAP = "http:///localhost:8080/demo/demo.map";
+  public static final String WOFF = "http:///localhost:8080/demo/demo.woff";
+  public static final String WOFF2 = "http:///localhost:8080/demo/demo.woff2";
+  public static final String TTF = "http:///localhost:8080/demo/demo.ttf";
+  public static final String EOT = "http:///localhost:8080/demo/demo.eot";
+  public static final String SVG = "http:///localhost:8080/demo/demo.svg";
+  public static final String ODT = "http:///localhost:8080/demo/demo.odt";
+
+  public static final String UNKNOWN0 = "http:///localhost:8080/demo/demo.PNG";
+  public static final String UNKNOWN1 = "http:///localhost:8080/demo/demos._png";
+  public static final String UNKNOWN2 = "http:///localhost:8080/demo/demo.ggif";
+  public static final String UNKNOWN3 = "http:///localhost:8080/demo/demos.ppg";
+  public static final String UNKNOWN4 = "http:///localhost:8080/demo/demos.pngx";
+  public static final String UNKNOWN5 = "http:///localhost:8080/demo/demos.png.";
+
+  @Test
+  public void testMimeTypes() {
+
+    Assert.assertEquals("image/gif", MimeTypeUtils.getMimeTypeForFile(GIF));
+    Assert.assertEquals("image/png", MimeTypeUtils.getMimeTypeForFile(PNG));
+    Assert.assertEquals("image/jpeg", MimeTypeUtils.getMimeTypeForFile(JPG));
+    Assert.assertEquals("text/javascript", MimeTypeUtils.getMimeTypeForFile(JS));
+    Assert.assertEquals("text/css", MimeTypeUtils.getMimeTypeForFile(CSS));
+    Assert.assertEquals("image/vnd.microsoft.icon", MimeTypeUtils.getMimeTypeForFile(ICO));
+    Assert.assertEquals("text/html", MimeTypeUtils.getMimeTypeForFile(HTML));
+    Assert.assertEquals("text/html", MimeTypeUtils.getMimeTypeForFile(HTM));
+    Assert.assertEquals("application/json", MimeTypeUtils.getMimeTypeForFile(MAP));
+    Assert.assertEquals("application/font-woff", MimeTypeUtils.getMimeTypeForFile(WOFF));
+    Assert.assertEquals("application/font-woff2", MimeTypeUtils.getMimeTypeForFile(WOFF2));
+    Assert.assertEquals("application/x-font-ttf", MimeTypeUtils.getMimeTypeForFile(TTF));
+    Assert.assertEquals("application/vnd.ms-fontobject", MimeTypeUtils.getMimeTypeForFile(EOT));
+    Assert.assertEquals("image/svg+xml", MimeTypeUtils.getMimeTypeForFile(SVG));
+  }
+
+  @Test
+  public void testMimeTypesUnknown() {
+
+    Assert.assertEquals(null, MimeTypeUtils.getMimeTypeForFile(UNKNOWN0));
+    Assert.assertEquals(null, MimeTypeUtils.getMimeTypeForFile(UNKNOWN1));
+    Assert.assertEquals(null, MimeTypeUtils.getMimeTypeForFile(UNKNOWN2));
+    Assert.assertEquals(null, MimeTypeUtils.getMimeTypeForFile(UNKNOWN3));
+    Assert.assertEquals(null, MimeTypeUtils.getMimeTypeForFile(UNKNOWN4));
+    Assert.assertEquals(null, MimeTypeUtils.getMimeTypeForFile(UNKNOWN5));
+  }
+
+  @Test
+  public void testMimeTypesConfigured() {
+    // comes from tobago-config-for-unit-tests.xml
+    Assert.assertEquals("application/vnd.oasis.opendocument.text", MimeTypeUtils.getMimeTypeForFile(ODT));
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/PartUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/PartUtilsUnitTest.java
new file mode 100644
index 0000000..b94faef
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/PartUtilsUnitTest.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collection;
+
+public class PartUtilsUnitTest {
+
+  @Test
+  public void testGetSubmittedFileName() throws Exception {
+
+    final String dc0 = "form-data; name=\"page:file\"; filename=\"foo.jpg\"";
+    Assert.assertEquals("foo.jpg", PartUtils.getSubmittedFileName(new PartMock(dc0)));
+
+    final String dc1 = "form-data; name=\"page:file\"; filename=\"foo;bar=\\\"boo\\\"-bar.jpg\"";
+    Assert.assertEquals("foo;bar=\"boo\"-bar.jpg", PartUtils.getSubmittedFileName(new PartMock(dc1)));
+
+/* XXX will fail, because a / will be encoded as a :
+    final String dc2
+        = "form-data; name=\"page:file1\"; filename=\"semicolon;doublequote\\\"backslash\\"
+        + "slash:doublebackslash\\\\quote'umlautsäöüumlautsäöüeuro€tilde~muµspace hiraganaぁ.jpg\"";
+    Assert.assertEquals(
+        "semicolon;doublequote\"backslash\\slash/doublebackslash\\\\quote'umlautsäöüumlautsäöüeuro€tilde~muµspace "
+            + "hiraganaぁ.jpg", PartUtils.getSubmittedFileName(new PartMock(dc2)));
+*/
+  }
+
+  private static final class PartMock implements Part {
+
+    private String contentDisposition;
+
+    public PartMock(String contentDisposition) {
+      this.contentDisposition = contentDisposition;
+    }
+
+    @Override
+    public void delete() throws IOException {
+
+    }
+
+    @Override
+    public String getContentType() {
+      return null;
+    }
+
+    @Override
+    public String getHeader(String headerName) {
+      if (headerName.equals("Content-Disposition")) {
+        return contentDisposition;
+      } else {
+        return null;
+      }
+    }
+
+    @Override
+    public Collection<String> getHeaderNames() {
+      return null;
+    }
+
+    @Override
+    public Collection<String> getHeaders(String headerName) {
+      return null;
+    }
+
+    @Override
+    public InputStream getInputStream() throws IOException {
+      return null;
+    }
+
+    @Override
+    public String getName() {
+      return null;
+    }
+
+    @Override
+    public long getSize() {
+      return 0;
+    }
+
+    @Override
+    public void write(String fileName) throws IOException {
+
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/StringUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/StringUtilsUnitTest.java
new file mode 100644
index 0000000..aa8c6a7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/internal/util/StringUtilsUnitTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StringUtilsUnitTest {
+
+  @Test
+  public void testEqualsIgnoreCaseAndWhitespace() {
+    Assert.assertTrue(StringUtils.equalsIgnoreCaseAndWhitespace(null, null));
+    Assert.assertTrue(StringUtils.equalsIgnoreCaseAndWhitespace("", ""));
+    Assert.assertTrue(StringUtils.equalsIgnoreCaseAndWhitespace("", " "));
+    Assert.assertTrue(StringUtils.equalsIgnoreCaseAndWhitespace(" ", " "));
+    Assert.assertTrue(StringUtils.equalsIgnoreCaseAndWhitespace(
+        "text/html;charset=utf-8", "  text/HTML;  charset=UTF-8  "));
+
+    Assert.assertFalse(StringUtils.equalsIgnoreCaseAndWhitespace(";", ""));
+    Assert.assertFalse(StringUtils.equalsIgnoreCaseAndWhitespace(";", ";;"));
+    Assert.assertFalse(StringUtils.equalsIgnoreCaseAndWhitespace(" a ", " ä "));
+  }
+
+  @Test
+  public void testIsUrl() {
+    Assert.assertTrue(StringUtils.isUrl("http://www.apache.org/"));
+    Assert.assertTrue(StringUtils.isUrl("http:"));
+    Assert.assertTrue(StringUtils.isUrl("ftp:"));
+    Assert.assertTrue(StringUtils.isUrl("abc:fjdskal:fdsa"));
+
+    Assert.assertFalse(StringUtils.isUrl(null));
+    Assert.assertFalse(StringUtils.isUrl("null"));
+    Assert.assertFalse(StringUtils.isUrl("/test"));
+    Assert.assertFalse(StringUtils.isUrl("test.xhtml?id=#page:input"));
+    Assert.assertFalse(StringUtils.isUrl(":test"));
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/AlignItemsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/AlignItemsUnitTest.java
new file mode 100644
index 0000000..797b6bd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/AlignItemsUnitTest.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class AlignItemsUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(AlignItems.class);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/ColumnPartitionUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/ColumnPartitionUnitTest.java
new file mode 100644
index 0000000..1a633d6
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/ColumnPartitionUnitTest.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ColumnPartitionUnitTest {
+
+  @Test
+  public void testArray() {
+    Assert.assertArrayEquals(
+        new Integer[]{12}, new ColumnPartition().getParts()); // will be fixed
+    Assert.assertArrayEquals(
+        new Integer[]{12}, new ColumnPartition(12).getParts());
+    Assert.assertArrayEquals(
+        new Integer[]{1, 11}, new ColumnPartition(1, 11).getParts());
+    Assert.assertArrayEquals(
+        new Integer[]{1, 11}, new ColumnPartition(1, 12).getParts()); // will be fixed
+    Assert.assertArrayEquals(
+        new Integer[]{1, 2, 3, 4, 2}, new ColumnPartition(1, 2, 3, 4, 5).getParts()); // will be fixed
+    Assert.assertArrayEquals(
+        new Integer[]{1, 1, 1, 1, 1, 7}, new ColumnPartition(-1, -2, -3, -4, -5).getParts()); // will be fixed
+  }
+
+  @Test
+  public void testString() {
+    Assert.assertArrayEquals(
+        new Integer[]{12}, ColumnPartition.valueOf("").getParts()); // will be fixed
+    Assert.assertArrayEquals(
+        new Integer[]{12}, ColumnPartition.valueOf("12").getParts());
+    Assert.assertArrayEquals(
+        new Integer[]{1, 11}, ColumnPartition.valueOf("1;11").getParts());
+    Assert.assertArrayEquals(
+        new Integer[]{1, 11}, ColumnPartition.valueOf("1;12").getParts()); // will be fixed
+    Assert.assertArrayEquals(
+        new Integer[]{1, 2, 3, 4, 2}, ColumnPartition.valueOf("1;2;3;4;5").getParts()); // will be fixed
+    Assert.assertArrayEquals(
+        new Integer[]{1, 1, 1, 1, 1, 7}, ColumnPartition.valueOf("-1;-2;-3;-4;-5").getParts()); // will be fixed
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/DisplayUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/DisplayUnitTest.java
new file mode 100644
index 0000000..85477de
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/DisplayUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class DisplayUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(Display.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/JustifyContentUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/JustifyContentUnitTest.java
new file mode 100644
index 0000000..3827c2a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/JustifyContentUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class JustifyContentUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(JustifyContent.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/LayoutTokensUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/LayoutTokensUnitTest.java
new file mode 100644
index 0000000..96d8a7b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/LayoutTokensUnitTest.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LayoutTokensUnitTest {
+
+  @Test
+  public void testIsRelativeToken() {
+    Assert.assertTrue(LayoutTokens.isRelativeToken("3*"));
+  }
+
+  @Test
+  public void testIsNumberAndSuffix() {
+    Assert.assertTrue(LayoutTokens.isNumberAndSuffix("34cm", "cm"));
+    Assert.assertFalse(LayoutTokens.isNumberAndSuffix("acm", "cm"));
+    Assert.assertFalse(LayoutTokens.isNumberAndSuffix("cm", "cm"));
+  }
+
+  @Test
+  public void testParseToken() {
+    Assert.assertEquals(AutoLayoutToken.INSTANCE, LayoutTokens.parseToken(null));
+    Assert.assertEquals(RelativeLayoutToken.DEFAULT_INSTANCE, LayoutTokens.parseToken("*"));
+    Assert.assertEquals(new RelativeLayoutToken(3), LayoutTokens.parseToken("3*"));
+    Assert.assertEquals(new MeasureLayoutToken("33%"), LayoutTokens.parseToken("33%"));
+    Assert.assertEquals(new MeasureLayoutToken("120px"), LayoutTokens.parseToken("120px"));
+    Assert.assertEquals(new MeasureLayoutToken("0px"), LayoutTokens.parseToken("0px"));
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/MeasureUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/MeasureUnitTest.java
new file mode 100644
index 0000000..0eeaa8d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/MeasureUnitTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class MeasureUnitTest {
+
+  @Test
+  public void testDecimal() {
+    Assert.assertEquals("13.3px", "" + Measure.valueOf("13.3px"));
+    Assert.assertEquals("13.7px", "" + Measure.valueOf("13.7px"));
+    Assert.assertEquals("13.3px", "" + Measure.valueOf("13.3"));
+    Assert.assertEquals("13.7px", "" + Measure.valueOf("13.7"));
+    Assert.assertEquals("0.7px", "" + Measure.valueOf(".7"));
+    Assert.assertEquals("0px", "" + Measure.valueOf("0"));
+    Assert.assertEquals(null, Measure.valueOf(""));
+  }
+
+  @Test
+  public void testOther() {
+    Assert.assertEquals("13.3cm", "" + Measure.valueOf("13.3cm"));
+    Assert.assertEquals("13.7mm", "" + Measure.valueOf("13.7mm"));
+    Assert.assertEquals("13.7ex", "" + Measure.valueOf("13.7ex"));
+    Assert.assertEquals("13.7em", "" + Measure.valueOf("13.7em"));
+    Assert.assertEquals("13.7in", "" + Measure.valueOf("13.7in"));
+    Assert.assertEquals("13.7%", "" + Measure.valueOf("13.7%"));
+  }
+
+  @Test
+  public void testWrong() {
+    Assert.assertNull("Not parsable, so get null", Measure.valueOf("13.3xx"));
+    Assert.assertNull("Not parsable, so get null", Measure.valueOf("13.3x"));
+    Assert.assertNull("Not parsable, so get null", Measure.valueOf("13.3mmm"));
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OrderByUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OrderByUnitTest.java
new file mode 100644
index 0000000..1b1bff1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OrderByUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class OrderByUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(OrderBy.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OrientationUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OrientationUnitTest.java
new file mode 100644
index 0000000..2120dde
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OrientationUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class OrientationUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(Orientation.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OverflowUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OverflowUnitTest.java
new file mode 100644
index 0000000..c93f2b0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/OverflowUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class OverflowUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(Overflow.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/PositionUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/PositionUnitTest.java
new file mode 100644
index 0000000..3437e21
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/PositionUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class PositionUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(Position.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/ShowPositionUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/ShowPositionUnitTest.java
new file mode 100644
index 0000000..ba26971
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/ShowPositionUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class ShowPositionUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(ShowPosition.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/TextAlignUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/TextAlignUnitTest.java
new file mode 100644
index 0000000..c68f403
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/layout/TextAlignUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.layout;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class TextAlignUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(TextAlign.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/CollapseModeUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/CollapseModeUnitTest.java
new file mode 100644
index 0000000..79ec234
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/CollapseModeUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class CollapseModeUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(CollapseMode.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/ExpandedStateUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/ExpandedStateUnitTest.java
new file mode 100644
index 0000000..2bd8199
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/ExpandedStateUnitTest.java
@@ -0,0 +1,339 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class ExpandedStateUnitTest {
+
+  private static final DefaultMutableTreeNode ROOT = new DefaultMutableTreeNode("root");
+  private static final DefaultMutableTreeNode A = new DefaultMutableTreeNode("a");
+  private static final DefaultMutableTreeNode B = new DefaultMutableTreeNode("b");
+  private static final DefaultMutableTreeNode C = new DefaultMutableTreeNode("c");
+  private static final DefaultMutableTreeNode A1 = new DefaultMutableTreeNode("a1");
+  private static final DefaultMutableTreeNode A2 = new DefaultMutableTreeNode("a2");
+  private static final DefaultMutableTreeNode A3 = new DefaultMutableTreeNode("a3");
+  private static final DefaultMutableTreeNode B1 = new DefaultMutableTreeNode("b1");
+  private static final DefaultMutableTreeNode B2 = new DefaultMutableTreeNode("b2");
+  private static final DefaultMutableTreeNode B3 = new DefaultMutableTreeNode("b3");
+  private static final DefaultMutableTreeNode C1 = new DefaultMutableTreeNode("c1");
+  private static final DefaultMutableTreeNode C2 = new DefaultMutableTreeNode("c2");
+  private static final DefaultMutableTreeNode C3 = new DefaultMutableTreeNode("c3");
+
+  @BeforeClass
+  public static void setup() {
+    ROOT.add(A);
+    ROOT.add(B);
+    ROOT.add(C);
+    A.add(A1);
+    A.add(A2);
+    A.add(A3);
+    B.add(B1);
+    B.add(B2);
+    B.add(B3);
+    C.add(C1);
+    C.add(C2);
+    C.add(C3);
+  }
+
+  /**
+   * <pre>
+   *  + root
+   *  |
+   *  +-+ a
+   *  | |
+   *  | +-+ a1
+   *  | |
+   *  | +-+ a2
+   *  | |
+   *  | +-+ a3
+   *  |
+   *  +-+ b
+   *  | |
+   *  | +-+ b1
+   *  | |
+   *  | +-+ b2
+   *  | |
+   *  | +-+ b3
+   *  |
+   *  +-+ c
+   *    |
+   *    +-+ c1
+   *    |
+   *    +-+ c2
+   *    |
+   *    +-+ c3
+   *
+   * </pre>
+   */
+  @Test
+  public void test() {
+
+    final ExpandedState state = new ExpandedState(2);
+
+    final TreePath root = new TreePath(ROOT);
+    final TreePath a = new TreePath(A);
+    final TreePath b = new TreePath(B);
+    final TreePath c = new TreePath(C);
+    final TreePath a1 = new TreePath(A1);
+    final TreePath a2 = new TreePath(A2);
+    final TreePath a3 = new TreePath(A3);
+    final TreePath b1 = new TreePath(B1);
+    final TreePath b2 = new TreePath(B2);
+    final TreePath b3 = new TreePath(B3);
+    final TreePath c1 = new TreePath(C1);
+    final TreePath c2 = new TreePath(C2);
+    final TreePath c3 = new TreePath(C3);
+
+    Assert.assertTrue(state.isExpanded(ROOT));
+
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertTrue(state.isExpanded(a));
+    Assert.assertTrue(state.isExpanded(b));
+    Assert.assertTrue(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+
+    state.expand(a);
+    state.expand(a1);
+    state.expand(a2);
+    state.expand(c);
+
+    state.collapse(root);
+    state.collapse(b);
+    state.collapse(b3);
+    state.collapse(a2);
+    state.collapse(c);
+
+    Assert.assertFalse(state.isExpanded(root));
+    Assert.assertTrue(state.isExpanded(a));
+    Assert.assertFalse(state.isExpanded(b));
+    Assert.assertFalse(state.isExpanded(c));
+    Assert.assertTrue(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(1, state.getExpandedSet().size());
+    Assert.assertEquals(3, state.getCollapsedSet().size());
+
+    // expand(1) should only expand the root node
+    state.expand(1);
+
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertTrue(state.isExpanded(a));
+    Assert.assertFalse(state.isExpanded(b));
+    Assert.assertFalse(state.isExpanded(c));
+    Assert.assertTrue(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(1, state.getExpandedSet().size());
+    Assert.assertEquals(2, state.getCollapsedSet().size());
+
+    // collapse(3) should collapse a1 only
+    state.collapse(3);
+
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertTrue(state.isExpanded(a));
+    Assert.assertFalse(state.isExpanded(b));
+    Assert.assertFalse(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(2, state.getCollapsedSet().size());
+
+    // expand(2) should expand b and c
+    state.expand(2);
+
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertTrue(state.isExpanded(a));
+    Assert.assertTrue(state.isExpanded(b));
+    Assert.assertTrue(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(0, state.getCollapsedSet().size());
+
+    // collapse(2) should expand b and c
+    state.collapse(2);
+
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertFalse(state.isExpanded(a));
+    Assert.assertFalse(state.isExpanded(b));
+    Assert.assertFalse(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(0, state.getCollapsedSet().size());
+
+    // expand(2) should expand b and c
+    state.expand(a);
+    state.expand(b);
+    state.expand(2);
+
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertTrue(state.isExpanded(a));
+    Assert.assertTrue(state.isExpanded(b));
+    Assert.assertTrue(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(0, state.getCollapsedSet().size());
+
+    // collapse(2) should expand b and c
+    state.collapse(a);
+    state.collapse(b);
+    state.collapse(2);
+
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertFalse(state.isExpanded(a));
+    Assert.assertFalse(state.isExpanded(b));
+    Assert.assertFalse(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(0, state.getCollapsedSet().size());
+
+    state.expand(2);
+    state.expand(b); // do something noise
+    state.expand(c1); // do something noise
+    state.collapseAll();
+    Assert.assertFalse(state.isExpanded(root));
+    Assert.assertFalse(state.isExpanded(a));
+    Assert.assertFalse(state.isExpanded(b));
+    Assert.assertFalse(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(0, state.getCollapsedSet().size());
+
+    state.expand(2);
+    state.expand(b); // do something noise
+    state.expand(c1); // do something noise
+    state.expandAll();
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertTrue(state.isExpanded(a));
+    Assert.assertTrue(state.isExpanded(b));
+    Assert.assertTrue(state.isExpanded(c));
+    Assert.assertTrue(state.isExpanded(a1));
+    Assert.assertTrue(state.isExpanded(a2));
+    Assert.assertTrue(state.isExpanded(a3));
+    Assert.assertTrue(state.isExpanded(b1));
+    Assert.assertTrue(state.isExpanded(b2));
+    Assert.assertTrue(state.isExpanded(b3));
+    Assert.assertTrue(state.isExpanded(c1));
+    Assert.assertTrue(state.isExpanded(c2));
+    Assert.assertTrue(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(0, state.getCollapsedSet().size());
+
+    state.expand(2);
+    state.expand(b); // do something noise
+    state.expand(c1); // do something noise
+    state.collapseAllButRoot();
+    Assert.assertTrue(state.isExpanded(root));
+    Assert.assertFalse(state.isExpanded(a));
+    Assert.assertFalse(state.isExpanded(b));
+    Assert.assertFalse(state.isExpanded(c));
+    Assert.assertFalse(state.isExpanded(a1));
+    Assert.assertFalse(state.isExpanded(a2));
+    Assert.assertFalse(state.isExpanded(a3));
+    Assert.assertFalse(state.isExpanded(b1));
+    Assert.assertFalse(state.isExpanded(b2));
+    Assert.assertFalse(state.isExpanded(b3));
+    Assert.assertFalse(state.isExpanded(c1));
+    Assert.assertFalse(state.isExpanded(c2));
+    Assert.assertFalse(state.isExpanded(c3));
+    Assert.assertEquals(0, state.getExpandedSet().size());
+    Assert.assertEquals(0, state.getCollapsedSet().size());
+
+    // text TreeNode
+
+    state.expand(A);
+    Assert.assertTrue(state.isExpanded(A));
+    state.collapse(A);
+    Assert.assertFalse(state.isExpanded(A));
+
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SelectableUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SelectableUnitTest.java
new file mode 100644
index 0000000..74d0e67
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SelectableUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class SelectableUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(Selectable.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SuggestFilterUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SuggestFilterUnitTest.java
new file mode 100644
index 0000000..04a423c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SuggestFilterUnitTest.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SuggestFilterUnitTest {
+
+  @Test
+  public void testConstants() {
+    Assert.assertEquals(SuggestFilter.ALL.getValue(), SuggestFilter.STRING_ALL);
+    Assert.assertEquals(SuggestFilter.PREFIX.getValue(), SuggestFilter.STRING_PREFIX);
+    Assert.assertEquals(SuggestFilter.CONTAINS.getValue(), SuggestFilter.STRING_CONTAINS);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SwitchTypeUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SwitchTypeUnitTest.java
new file mode 100644
index 0000000..a53fb63
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/SwitchTypeUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class SwitchTypeUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(SwitchType.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/TreePathUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/TreePathUnitTest.java
new file mode 100644
index 0000000..8ed22d5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/model/TreePathUnitTest.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.model;
+
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.util.Arrays;
+
+/*
+ * <pre>
+ *  + Root               Path: []
+ *  |
+ *  +-+ Node             Path: [0]
+ *  | |
+ *  | +-+ Sub-Node       Path: [0, 0]
+ *  | |
+ *  | +-+ Sub-Node       Path: [0, 1]
+ *  |
+ *  +-+ Node             Path: [1]
+ *    |
+ *    +-+ Sub-Node       Path: [1, 0]
+ *    |
+ *    +-+ Sub-Node       Path: [1, 1]
+ *    |
+ *    +-+ Sub-Node       Path: [1, 2]
+ * </pre>
+ */
+public class TreePathUnitTest {
+
+  private static final DefaultMutableTreeNode ROOT = new DefaultMutableTreeNode("root");
+  private static final DefaultMutableTreeNode A = new DefaultMutableTreeNode("a");
+  private static final DefaultMutableTreeNode B = new DefaultMutableTreeNode("b");
+  private static final DefaultMutableTreeNode A1 = new DefaultMutableTreeNode("a1");
+  private static final DefaultMutableTreeNode A2 = new DefaultMutableTreeNode("a2");
+  private static final DefaultMutableTreeNode B1 = new DefaultMutableTreeNode("b1");
+  private static final DefaultMutableTreeNode B2 = new DefaultMutableTreeNode("b2");
+  private static final DefaultMutableTreeNode B3 = new DefaultMutableTreeNode("b3");
+
+  @BeforeClass
+  public static void setup() {
+    ROOT.add(A);
+    ROOT.add(B);
+    A.add(A1);
+    A.add(A2);
+    B.add(B1);
+    B.add(B2);
+    B.add(B3);
+  }
+
+  @Test
+  public void test() {
+
+    final TreePath root = new TreePath(ROOT);
+    final TreePath a = new TreePath(A);
+    final TreePath b = new TreePath(B);
+    final TreePath a1 = new TreePath(A1);
+    final TreePath a2 = new TreePath(A2);
+    final TreePath b1 = new TreePath(B1);
+    final TreePath b2 = new TreePath(B2);
+    final TreePath b3 = new TreePath(B3);
+
+    Assert.assertEquals(0, root.getPath().length);
+    Assert.assertEquals(1, a.getPath().length);
+    Assert.assertEquals(0, a.getPath()[0]);
+    Assert.assertEquals(1, b.getPath().length);
+    Assert.assertEquals(1, b.getPath()[0]);
+    Assert.assertEquals(2, a1.getPath().length);
+    Assert.assertEquals(0, a1.getPath()[0]);
+    Assert.assertEquals(0, a1.getPath()[1]);
+    Assert.assertEquals(2, a2.getPath().length);
+    Assert.assertEquals(0, a2.getPath()[0]);
+    Assert.assertEquals(1, a2.getPath()[1]);
+    Assert.assertEquals(2, b1.getPath().length);
+    Assert.assertEquals(1, b1.getPath()[0]);
+    Assert.assertEquals(0, b1.getPath()[1]);
+    Assert.assertEquals(2, b2.getPath().length);
+    Assert.assertEquals(1, b2.getPath()[0]);
+    Assert.assertEquals(1, b2.getPath()[1]);
+    Assert.assertEquals(2, b3.getPath().length);
+    Assert.assertEquals(1, b3.getPath()[0]);
+    Assert.assertEquals(2, b3.getPath()[1]);
+  }
+
+  @Test
+  public void testGetPath() {
+    final TreePath treePath = new TreePath(0, 1, 2);
+    Assert.assertTrue(Arrays.equals(new int[]{0, 1, 2}, treePath.getPath()));
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/LabelWithAccessKeyUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/LabelWithAccessKeyUnitTest.java
new file mode 100644
index 0000000..17ad0de
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/LabelWithAccessKeyUnitTest.java
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit;
+
+import org.apache.myfaces.tobago.component.UILabel;
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class LabelWithAccessKeyUnitTest extends AbstractTobagoTestBase {
+
+  @Test
+  public void testSimple() {
+    final UILabel component = new UILabel();
+    component.setValue("Save");
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Save", label.getLabel());
+    Assert.assertEquals(-1, label.getPos());
+    Assert.assertEquals(null, label.getAccessKey());
+  }
+
+  @Test
+  public void testUmlauts() {
+    // Umlauts are not supported as accessKey
+    final UILabel component = new UILabel();
+    component.setValue("Löschen");
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Löschen", label.getLabel());
+    Assert.assertEquals(-1, label.getPos());
+    Assert.assertEquals(null, label.getAccessKey());
+  }
+
+  @Test
+  public void testKey() {
+    final UILabel component = new UILabel();
+    component.setValue("Save");
+    component.setAccessKey('a');
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Save", label.getLabel());
+    Assert.assertEquals(1, label.getPos());
+    Assert.assertEquals((Character) 'a', label.getAccessKey());
+  }
+
+  @Test
+  public void testKeyWithWongCase() {
+    final UILabel component = new UILabel();
+    component.setValue("Save");
+    component.setAccessKey('A');
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Save", label.getLabel());
+    Assert.assertEquals(1, label.getPos());
+    Assert.assertEquals((Character) 'a', label.getAccessKey());
+  }
+
+  @Test
+  public void testNumberKey() {
+    final UILabel component = new UILabel();
+    component.setValue("Save");
+    component.setAccessKey('5');
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Save", label.getLabel());
+    Assert.assertEquals(-1, label.getPos());
+    Assert.assertEquals((Character) '5', label.getAccessKey());
+  }
+
+  @Test
+  public void testForbiddenKey() {
+    final UILabel component = new UILabel();
+    component.setValue("Save");
+    component.setAccessKey('#');
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Save", label.getLabel());
+    Assert.assertEquals(-1, label.getPos());
+    Assert.assertEquals(null, label.getAccessKey());
+  }
+
+  @Test
+  public void testForbiddenKey2() {
+    final UILabel component = new UILabel();
+    component.setValue("Save");
+    component.setAccessKey('á');
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Save", label.getLabel());
+    Assert.assertEquals(-1, label.getPos());
+    Assert.assertEquals(null, label.getAccessKey());
+  }
+
+  @Test
+  public void testForbiddenKey3() {
+    final UILabel component = new UILabel();
+    component.setValue("Save");
+    component.setAccessKey('ä');
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals("Save", label.getLabel());
+    Assert.assertEquals(-1, label.getPos());
+    Assert.assertEquals(null, label.getAccessKey());
+  }
+
+  @Test
+  public void testNull() {
+    final UILabel component = new UILabel();
+    final LabelWithAccessKey label = new LabelWithAccessKey(component);
+    Assert.assertEquals(null, label.getLabel());
+    Assert.assertEquals(-1, label.getPos());
+    Assert.assertEquals(null, label.getAccessKey());
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/ClassesUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/ClassesUnitTest.java
new file mode 100644
index 0000000..ad6605a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/ClassesUnitTest.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.UIIn;
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.faces.component.UIComponent;
+
+public class ClassesUnitTest extends AbstractTobagoTestBase {
+
+  @Test
+  public void testSimple() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    Assert.assertEquals("tobago-in-simple", Classes.create(in, "simple").getName());
+  }
+
+  @Test
+  public void testFull() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    Assert.assertEquals("tobago-in", Classes.create(in).getName());
+  }
+
+  @Test
+  public void testDisabled() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    in.setDisabled(true);
+    updateMarkup(in);
+    Assert.assertEquals("tobago-in tobago-in-markup-disabled", Classes.create(in).getName());
+  }
+
+  @Test
+  public void testReadonly() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    in.setReadonly(true);
+    updateMarkup(in);
+    Assert.assertEquals("tobago-in tobago-in-markup-readonly", Classes.create(in).getName());
+  }
+
+  @Test
+  public void testDisabledReadonly() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    in.setDisabled(true);
+    in.setReadonly(true);
+    updateMarkup(in);
+    Assert.assertEquals(
+        "tobago-in tobago-in-markup-disabled tobago-in-markup-readonly", Classes.create(in).getName());
+  }
+
+  @Test
+  public void testError() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    in.setValid(false);
+    updateMarkup(in);
+    Assert.assertEquals("tobago-in tobago-in-markup-error", Classes.create(in).getName());
+  }
+
+  @Test
+  public void testMarkup() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    in.setMarkup(Markup.valueOf("important"));
+    updateMarkup(in);
+    Assert.assertEquals("tobago-in tobago-in-markup-important", Classes.create(in).getName());
+  }
+
+  @Test
+  public void testSub() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    Assert.assertEquals("tobago-in-sub", Classes.create(in, "sub").getName());
+  }
+
+  @Test
+  public void testMixed() {
+    final UIIn in = (UIIn) ComponentUtils.createComponent(
+        getFacesContext(), UIIn.COMPONENT_TYPE, RendererTypes.In, "in");
+    in.setDisabled(true);
+    in.setReadonly(true);
+    in.setValid(false);
+    in.setMarkup(Markup.valueOf("important,deleted"));
+    updateMarkup(in);
+    Assert.assertEquals("tobago-in-sub tobago-in-sub-markup-important tobago-in-sub-markup-deleted "
+        + "tobago-in-sub-markup-disabled tobago-in-sub-markup-readonly tobago-in-sub-markup-error",
+        Classes.create(in, "sub").getName());
+  }
+
+  private void updateMarkup(final UIComponent component) {
+    final Visual m = (Visual) component;
+    m.setMarkup(ComponentUtils.updateMarkup(component, m.getMarkup()));
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/CustomClassUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/CustomClassUnitTest.java
new file mode 100644
index 0000000..447bd50
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/CustomClassUnitTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class CustomClassUnitTest {
+
+  @Test
+  public void test() {
+    Assert.assertEquals("simple", "test", CustomClass.valueOf("test").getName());
+    Assert.assertEquals("number", "test2", CustomClass.valueOf("test2").getName());
+    Assert.assertEquals("list", "test3 and test4", CustomClass.valueOf("test3 and test4").getName());
+    Assert.assertEquals("space", "test5 test6", CustomClass.valueOf("     test5     test6       ").getName());
+    Assert.assertEquals("double", "test7", CustomClass.valueOf("test7 test7").getName());
+    Assert.assertEquals("-", "test-8", CustomClass.valueOf("test-8").getName());
+    Assert.assertEquals("_", "__t_e_s_t-9 _d", CustomClass.valueOf("__t_e_s_t-9 _d").getName());
+
+    Assert.assertEquals(".", null, CustomClass.valueOf("test.10"));
+    Assert.assertEquals("tab", null, CustomClass.valueOf("test\t11"));
+    Assert.assertEquals(":", null, CustomClass.valueOf("test:12"));
+
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/StyleUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/StyleUnitTest.java
new file mode 100644
index 0000000..a385a4e
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/StyleUnitTest.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.apache.myfaces.tobago.layout.Display;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.Overflow;
+import org.apache.myfaces.tobago.layout.Position;
+import org.apache.myfaces.tobago.layout.TextAlign;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StyleUnitTest {
+
+  @Test
+  public void testEncodedEmpty() {
+    Style style = new Style();
+    Assert.assertEquals("Check encoder", "", style.encode());
+    Assert.assertEquals("Check encoder JSON", "{}", style.encodeJson());
+  }
+
+  @Test
+  public void testEncodedFull() {
+    Style style = new Style();
+
+    style.setWidth(Measure.valueOf(110));
+    style.setHeight(Measure.valueOf(220));
+
+    style.setMinWidth(Measure.valueOf(100));
+    style.setMinHeight(Measure.valueOf(200));
+    style.setMaxWidth(Measure.valueOf(111));
+    style.setMaxHeight(Measure.valueOf(222));
+
+    style.setLeft(Measure.valueOf(44));
+    style.setRight(Measure.valueOf(55));
+    style.setTop(Measure.valueOf(66));
+    style.setBottom(Measure.valueOf(77));
+
+    style.setPaddingLeft(Measure.valueOf(333));
+    style.setPaddingRight(Measure.valueOf(444));
+    style.setPaddingTop(Measure.valueOf(555));
+    style.setPaddingBottom(Measure.valueOf(666));
+
+    style.setMarginLeft(Measure.valueOf(3333));
+    style.setMarginRight(Measure.valueOf(4444));
+    style.setMarginTop(Measure.valueOf(5555));
+    style.setMarginBottom(Measure.valueOf(6666));
+
+    style.setOverflowX(Overflow.auto);
+    style.setOverflowX(Overflow.scroll);
+    style.setDisplay(Display.block);
+    style.setPosition(Position.absolute);
+
+    style.setBackgroundImage("url('icon.pgn')");
+    style.setBackgroundPosition("center");
+    style.setZIndex(2);
+    style.setTextAlign(TextAlign.justify);
+
+    final String encoded = style.encode();
+    final String json = style.encodeJson();
+
+    final String manually = ("{\"" + encoded
+        .replaceAll(":", "\":\"")
+        .replaceAll(";", "\",\"")
+        .replaceAll("-h", "H")
+        .replaceAll("-w", "W")
+        .replaceAll("-l", "L")
+        .replaceAll("-r", "R")
+        .replaceAll("-t", "T")
+        .replaceAll("-b", "B")
+        .replaceAll("-x", "X")
+        .replaceAll("-y", "Y")
+        .replaceAll("-i", "I")
+        .replaceAll("-a", "A")
+        .replaceAll("-p", "P")
+        .replaceAll("\"2\"", "2")
+        + "\"}")
+        .replaceAll(",\"\"}", "}");
+
+    Assert.assertEquals("Check different encoders", manually, json);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/TobagoClassUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/TobagoClassUnitTest.java
new file mode 100644
index 0000000..ef2d0c7
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/css/TobagoClassUnitTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.css;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TobagoClassUnitTest {
+
+  @Test
+  public void testNames() throws NoSuchFieldException {
+    final String fieldRegex = "[A-Z_]*[A-Z]";
+    final String nameRegex = "[a-z][a-zA-Z\\-]*[a-z]";
+
+    for (TobagoClass value : TobagoClass.values()) {
+      boolean ignoreByTest = TobagoClass.class.getField(value.name()).isAnnotationPresent(Deprecated.class);
+      if (!ignoreByTest) {
+        final String field = value.toString();
+        final String name = value.getName();
+
+        Assert.assertTrue(field.matches(fieldRegex));
+        Assert.assertTrue(name.matches(nameRegex));
+
+        StringBuilder calculatedName = new StringBuilder();
+        calculatedName.append("tobago-");
+        for (int i = 0; i < field.length(); i++) {
+          char c = field.charAt(i);
+          if (c == '_') {
+            char nextChar = field.charAt(i + 1);
+            if (nextChar == '_') {
+              calculatedName.append("-");
+            } else {
+              calculatedName.append(nextChar);
+            }
+            i++;
+          } else {
+            calculatedName.append(Character.toLowerCase(c));
+          }
+        }
+
+        Assert.assertEquals(field, calculatedName.toString(), name);
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/AriasUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/AriasUnitTest.java
new file mode 100644
index 0000000..23f3fb4
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/AriasUnitTest.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+
+public class AriasUnitTest {
+
+  @Test
+  public void testAttributeNames() throws IllegalAccessException {
+    for (final Field field : Arias.class.getFields()) {
+
+      final Arias aria = (Arias) field.get(null);
+      final String value = aria.getValue();
+      Assert.assertTrue("Regexp check: value='" + aria + "'", value.matches("aria-[a-z0-9]+"));
+
+      final String extension = value.substring("aria-".length());
+      final String name = field.getName();
+      Assert.assertEquals(name, extension.toUpperCase());
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/DataAttributesUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/DataAttributesUnitTest.java
new file mode 100644
index 0000000..adaaf15
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/DataAttributesUnitTest.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class DataAttributesUnitTest {
+
+  @Test
+  public void testAttributeNames() throws IllegalAccessException {
+    for (final DataAttributes d : DataAttributes.values()) {
+
+// todo      if (d.getAnnotation(Deprecated.class) != null) {
+//        // ignore the check for deprecated fields
+//        continue;
+//      }
+      final String value = d.getValue();
+      Assert.assertTrue("Regexp check: value='" + value + "'", value.matches("data(-tobago)?(-[a-z0-9]+)*-[a-z0-9]+"));
+
+      final String extension
+          = value.startsWith("data-tobago-")
+          ? value.substring("data-tobago-".length())
+          : value.substring("data-".length());
+      final String name = d.name();
+      Assert.assertEquals(name, extension.toUpperCase().replaceAll("-", "_"));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/HtmlElementsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/HtmlElementsUnitTest.java
new file mode 100644
index 0000000..42699e8
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/renderkit/html/HtmlElementsUnitTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+
+public class HtmlElementsUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException {
+    for (final Field field : HtmlElements.class.getFields()) {
+
+      final HtmlElements element = (HtmlElements) field.get(null);
+      final String value = element.getValue();
+      Assert.assertEquals("Check to lower: '" + element + "'", value, element.name().toLowerCase());
+      Assert.assertEquals("Check to upper: '" + element + "'", value.toUpperCase(), element.name());
+    }
+  }
+
+  @Test
+  public void testVoid() throws IllegalAccessException {
+
+    // list from spec.
+    List<String> voids = Arrays.asList(
+        "area", "base", "br", "col", "command", "embed",
+        "hr", "img", "input", "keygen", "link", "meta",
+        "param", "source", "track", "wbr");
+
+    for (final Field field : HtmlElements.class.getFields()) {
+      final HtmlElements element = (HtmlElements) field.get(null);
+
+      Assert.assertEquals("Check void: '" + element + "'", voids.contains(element.getValue()),  element.isVoid());
+    }
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/sanitizer/SanitizeModeUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/sanitizer/SanitizeModeUnitTest.java
new file mode 100644
index 0000000..ac6de00
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/sanitizer/SanitizeModeUnitTest.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.sanitizer;
+
+import org.apache.myfaces.tobago.util.EnumUnitTest;
+import org.junit.Test;
+
+public class SanitizeModeUnitTest extends EnumUnitTest {
+
+  @Test
+  public void testNames() throws IllegalAccessException, NoSuchFieldException {
+    testNames(SanitizeMode.class);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/ComponentUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/ComponentUtilsUnitTest.java
new file mode 100644
index 0000000..2947c5f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/ComponentUtilsUnitTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.component.RendererTypes;
+import org.apache.myfaces.tobago.component.UIIn;
+import org.apache.myfaces.tobago.component.UIPanel;
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+
+public class ComponentUtilsUnitTest extends AbstractTobagoTestBase {
+
+  @Test
+  public void testSplitList() {
+    Assert.assertArrayEquals(new String[]{"ab", "cd"}, ComponentUtils.splitList("ab cd"));
+    Assert.assertArrayEquals(new String[]{"ab", "cd"}, ComponentUtils.splitList("ab  cd"));
+    Assert.assertArrayEquals(new String[]{"ab", "cd"}, ComponentUtils.splitList("ab,  cd"));
+    Assert.assertArrayEquals(new String[]{"ab", "cd"}, ComponentUtils.splitList("ab , cd"));
+    Assert.assertArrayEquals(new String[]{"ab", "cd"}, ComponentUtils.splitList("ab,,cd"));
+  }
+
+  @Test
+  public void testFindDescendant() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final UIComponent p = ComponentUtils.createComponent(
+        facesContext, UIPanel.COMPONENT_TYPE, RendererTypes.Panel, "p");
+    final UIComponent i = ComponentUtils.createComponent(
+        facesContext, UIIn.COMPONENT_TYPE, RendererTypes.In, "i");
+    p.getChildren().add(i);
+
+    final UIIn in = ComponentUtils.findDescendant(p, UIIn.class);
+    Assert.assertEquals(i, in);
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/EnumUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/EnumUnitTest.java
new file mode 100644
index 0000000..47a8330
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/EnumUnitTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.junit.Assert;
+
+import java.lang.reflect.Field;
+
+public abstract class EnumUnitTest {
+
+  protected String getEnumRegexp() {
+    return "[a-z][a-zA-Z]*";
+  }
+
+  protected String constantCaseToEnum(String constant) {
+    return StringUtils.constantToLowerCamelCase(constant);
+  }
+
+  public <E extends Enum<E>> void testNames(Class<E> enumType)
+      throws NoSuchFieldException, IllegalAccessException {
+
+    final Field[] fields = enumType.getFields();
+    final E[] values = enumType.getEnumConstants();
+
+    Assert.assertEquals("Is for every enum a string constant defined?", fields.length, 2 * values.length);
+
+    for (final Field field : fields) {
+      final Object object = field.get(null);
+      final String fieldName = field.getName();
+      if (object instanceof String) {
+        // case String constant
+        final String value = (String) object;
+        final String expected = constantCaseToEnum(fieldName);
+        Assert.assertEquals(expected, value);
+        Assert.assertNotNull("exists", enumType.getField(value));
+      } else if (object.getClass().isAssignableFrom(enumType)) {
+        // case enum
+        Assert.assertTrue("value='" + fieldName + "'", fieldName.matches(getEnumRegexp()));
+      } else {
+        Assert.fail();
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/HtmlWriterUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/HtmlWriterUtilsUnitTest.java
new file mode 100644
index 0000000..8806d89
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/HtmlWriterUtilsUnitTest.java
@@ -0,0 +1,122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.internal.util.HtmlWriterUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.CharArrayWriter;
+import java.io.IOException;
+
+public class HtmlWriterUtilsUnitTest {
+
+  // some chars must escaped in attribute values other than in text
+  // put them at beginning of raw texts and in both escaped texts
+
+  // HTML 4.0, section B.7.1: ampersands followed by
+  // an open brace don't get escaped
+  public static final String[] RAW_TEXTS = {
+      "oeffnende spitze klammern werden in attributen doch escaped <tagname >",
+      "& followed by an { -> &{ don't get escaped in attributes",
+      "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",
+      "\u00a0\u00a1\u00a2\u00a3\u00a4\u00a5\u00a6\u00a7\u00a8\u00a9\u00aa\u00ab\u00ac\u00ad\u00ae\u00af",
+      "\u00b0\u00b1\u00b2\u00b3\u00b4\u00b5\u00b6\u00b7\u00b8\u00b9\u00ba\u00bb\u00bc\u00bd\u00be\u00bf",
+      "\u00c0\u00c1\u00c2\u00c3\u00c4\u00c5\u00c6\u00c7\u00c8\u00c9\u00ca\u00cb\u00cc\u00cd\u00ce\u00cf",
+      "\u00d0\u00d1\u00d2\u00d3\u00d4\u00d5\u00d6\u00d7\u00d8\u00d9\u00da\u00db\u00dc\u00dd\u00de\u00df",
+      "\u00e0\u00e1\u00e2\u00e3\u00e4\u00e5\u00e6\u00e7\u00e8\u00e9\u00ea\u00eb\u00ec\u00ed\u00ee\u00ef",
+      "\u00f0\u00f1\u00f2\u00f3\u00f4\u00f5\u00f6\u00f7\u00f8\u00f9\u00fa\u00fb\u00fc\u00fd\u00fe\u00ff"
+
+  };
+  public static final String[] ESCAPED_TEXTS = {
+      "oeffnende spitze klammern werden in attributen doch escaped &lt;tagname &gt;",
+      "&amp; followed by an { -&gt; &amp;{ don&#x27;t get escaped in attributes",
+      RAW_TEXTS[2], // no escape needed
+      "&nbsp;&iexcl;&cent;&pound;&curren;&yen;&brvbar;&sect;&uml;&copy;&ordf;&laquo;&not;&shy;&reg;&macr;",
+      "&deg;&plusmn;&sup2;&sup3;&acute;&micro;&para;&middot;&cedil;&sup1;&ordm;&raquo;&frac14;&frac12;"
+          + "&frac34;&iquest;",
+      "&Agrave;&Aacute;&Acirc;&Atilde;&Auml;&Aring;&AElig;&Ccedil;&Egrave;&Eacute;&Ecirc;&Euml;&Igrave;&Iacute;"
+          + "&Icirc;&Iuml;",
+      "&ETH;&Ntilde;&Ograve;&Oacute;&Ocirc;&Otilde;&Ouml;&times;&Oslash;&Ugrave;&Uacute;&Ucirc;&Uuml;&Yacute;"
+          + "&THORN;&szlig;",
+      "&agrave;&aacute;&acirc;&atilde;&auml;&aring;&aelig;&ccedil;&egrave;&eacute;&ecirc;&euml;&igrave;&iacute;"
+          + "&icirc;&iuml;",
+      "&eth;&ntilde;&ograve;&oacute;&ocirc;&otilde;&ouml;&divide;&oslash;&ugrave;&uacute;&ucirc;&uuml;&yacute;"
+          + "&thorn;&yuml;"
+  };
+
+  public static final String[] ESCAPED_ATTRIBUTES = {
+      ESCAPED_TEXTS[0], // same as in texts
+      "&amp; followed by an { -&gt; &{ don&#x27;t get escaped in attributes",
+      ESCAPED_TEXTS[2], // same as in texts
+      ESCAPED_TEXTS[3], // same as in texts
+      ESCAPED_TEXTS[4], // same as in texts
+      ESCAPED_TEXTS[5], // same as in texts
+      ESCAPED_TEXTS[6], // same as in texts
+      ESCAPED_TEXTS[7], // same as in texts
+      ESCAPED_TEXTS[8] // same as in texts
+  };
+
+  @Test
+  public void testTexts() {
+    final CharArrayWriter writer = new CharArrayWriter();
+    final HtmlWriterUtils helper = new HtmlWriterUtils(writer, "");
+
+    for (int i = 0; i < ESCAPED_TEXTS.length; i++) {
+      testText(helper, writer, RAW_TEXTS[i], ESCAPED_TEXTS[i]);
+    }
+  }
+
+  @Test
+  public void testAttributes() {
+    final CharArrayWriter writer = new CharArrayWriter();
+    final HtmlWriterUtils helper = new HtmlWriterUtils(writer, "");
+
+    for (int i = 0; i < ESCAPED_ATTRIBUTES.length; i++) {
+      testAttributeValue(helper, writer, RAW_TEXTS[i], ESCAPED_ATTRIBUTES[i]);
+    }
+  }
+
+  private void testText(
+      final HtmlWriterUtils writerUtil, final CharArrayWriter writer, final String text, final String escaped) {
+    try {
+      writer.reset();
+      writerUtil.writeText(text);
+      final String result = String.valueOf(writer.toCharArray());
+      Assert.assertEquals(escaped, result);
+
+    } catch (final IOException e) {
+      // could not occur with CharArrayWriter
+    }
+  }
+
+  private void testAttributeValue(
+      final HtmlWriterUtils writerUtil, final CharArrayWriter writer, final String text, final String escaped) {
+    try {
+      writer.reset();
+      writerUtil.writeAttributeValue(text);
+      final String result = String.valueOf(writer.toCharArray());
+      Assert.assertEquals(escaped, result);
+
+    } catch (final IOException e) {
+      // could not occur with CharArrayWriter
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/JavascriptWriterUtilsTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/JavascriptWriterUtilsTest.java
new file mode 100644
index 0000000..35cc9a1
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/JavascriptWriterUtilsTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+
+import org.apache.myfaces.tobago.internal.util.JavascriptWriterUtils;
+import org.apache.myfaces.tobago.internal.util.WriterUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.io.CharArrayWriter;
+import java.io.IOException;
+
+public class JavascriptWriterUtilsTest {
+
+  @Test
+  public void test() {
+    final CharArrayWriter writer = new CharArrayWriter();
+    final JavascriptWriterUtils helper = new JavascriptWriterUtils(writer, "");
+    String text = "\"";
+    String result = "\\\"";
+
+    testText(helper, writer, text, result);
+    text = "\\\"";
+    result = "\\\\\\\"";
+    testText(helper, writer, text, result);
+  }
+
+  private void testText(
+      final WriterUtils writerUtil, final CharArrayWriter writer, final String text, final String escaped) {
+    try {
+      writer.reset();
+      writerUtil.writeText(text);
+      final String result = String.valueOf(writer.toCharArray());
+      Assert.assertEquals(escaped, result);
+
+    } catch (final IOException e) {
+      // could not occur with CharArrayWriter
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/LocaleUtilsUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/LocaleUtilsUnitTest.java
new file mode 100644
index 0000000..c69e259
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/LocaleUtilsUnitTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Locale;
+
+public class LocaleUtilsUnitTest {
+
+  private static final Locale D1 = new Locale("de");
+  private static final Locale D2 = new Locale("de", "DE");
+  private static final Locale D3 = new Locale("de", "DE", "NS");
+
+  private static final String S1 = "de";
+  private static final String S2 = "de_DE";
+  private static final String S3 = "de_DE_NS";
+
+  private static final String D = "default";
+
+  @Test
+  public void testCreateLocale() {
+    Assert.assertEquals(D1, LocaleUtils.createLocale(S1));
+    Assert.assertEquals(D2, LocaleUtils.createLocale(S2));
+    Assert.assertEquals(D3, LocaleUtils.createLocale(S3));
+  }
+
+  @Test
+  public void testLocaleList() {
+    Assert.assertArrayEquals(new Locale[]{D1}, LocaleUtils.getLocaleList(D1).toArray());
+    Assert.assertArrayEquals(new Locale[]{D2, D1}, LocaleUtils.getLocaleList(D2).toArray());
+    Assert.assertArrayEquals(new Locale[]{D3, D2, D1}, LocaleUtils.getLocaleList(D3).toArray());
+  }
+
+  @Test
+  public void testLocaleSuffixList() {
+    Assert.assertArrayEquals(new String[]{'_' + S1, ""}, LocaleUtils.getLocaleSuffixList(D1).toArray());
+    Assert.assertArrayEquals(new String[]{'_' + S2, '_' + S1, ""}, LocaleUtils.getLocaleSuffixList(D2).toArray());
+    Assert.assertArrayEquals(new String[]{'_' + S3, '_' + S2, '_' + S1, ""},
+        LocaleUtils.getLocaleSuffixList(D3).toArray());
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/RangeParserUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/RangeParserUnitTest.java
new file mode 100644
index 0000000..48bbe84
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/util/RangeParserUnitTest.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.util;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class RangeParserUnitTest {
+
+  @Test
+  public void test() {
+
+    int[] ints =  {0, 5, 10};
+    String s = "0,5,10";
+    checkEquals(ints, StringUtils.getIndices(s));
+    s = "0, 5, 10";
+    checkEquals(ints, StringUtils.getIndices(s));
+    s = " 0 , 5 , 10 ";
+    checkEquals(ints, StringUtils.getIndices(s));
+
+    ints = new int[] {3, 4, 5, 6, 7, 15, 16, 17};
+    s = "3-7,15-17";
+    checkEquals(ints, StringUtils.getIndices(s));
+    s = "3-5,6,7,15,16-17";
+    checkEquals(ints, StringUtils.getIndices(s));
+    s = "3-5, 6, 7, 15, 16 - 17 ";
+    checkEquals(ints, StringUtils.getIndices(s));
+
+    ints = new int[] {3, 4, 5, 6, 7, 15, 14, 13};
+    s = "3-7,15-13";
+    checkEquals(ints, StringUtils.getIndices(s));
+    s = "3 - 7, 15 - 13";
+    checkEquals(ints, StringUtils.getIndices(s));
+  }
+
+  private void checkEquals(final int[] ints, final int[] indices) {
+    Assert.assertTrue(ints.length == indices.length);
+    for (int i = 0; i < ints.length; i++) {
+       Assert.assertTrue(ints[i] == indices[i]);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java
new file mode 100644
index 0000000..051d8f9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/java/org/apache/myfaces/tobago/webapp/TobagoResponseWriterUnitTest.java
@@ -0,0 +1,151 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.webapp;
+
+import org.apache.myfaces.test.base.junit4.AbstractJsfTestCase;
+import org.apache.myfaces.tobago.internal.webapp.HtmlResponseWriter;
+import org.apache.myfaces.tobago.internal.webapp.XmlResponseWriter;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+public class TobagoResponseWriterUnitTest extends AbstractJsfTestCase {
+
+  private StringWriter stringWriter;
+  private TobagoResponseWriter writer;
+
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+    stringWriter = new StringWriter();
+    writer = new HtmlResponseWriter(stringWriter, "", "UTF-8");
+  }
+
+  @Test
+  public void testDocument() throws IOException {
+    writer.startDocument();
+    writer.endDocument();
+    Assert.assertEquals("content expected", "<!DOCTYPE html>\n", stringWriter.toString());
+  }
+
+  @Test
+  public void testEmptyTag() throws IOException {
+    writer.startElement(HtmlElements.INPUT);
+    writer.endElement(HtmlElements.INPUT);
+    Assert.assertEquals("empty tag", "\n<input>", stringWriter.toString());
+  }
+
+  @Test
+  public void testNormalTag() throws IOException {
+    writer.startElement(HtmlElements.SELECT);
+    writer.endElement(HtmlElements.SELECT);
+    Assert.assertEquals("normal tag", "\n<select></select>", stringWriter.toString());
+  }
+
+  @Test
+  public void testAttribute() throws IOException {
+    writer.startElement(HtmlElements.SELECT);
+    writer.writeAttribute(HtmlAttributes.VALUE, 0);
+    writer.endElement(HtmlElements.SELECT);
+    Assert.assertEquals("attr tag", "\n<select value='0'></select>", stringWriter.toString());
+  }
+
+  @Test
+  public void testURIAttribute() throws IOException {
+    writer.startElement(HtmlElements.A);
+    writer.writeURIAttribute(HtmlAttributes.HREF, "http://example.org/web?text=äöüß");
+    writer.endElement(HtmlElements.A);
+    Assert.assertEquals(
+        "uri attr tag",
+        "\n<a href='http:&#x2F;&#x2F;example.org&#x2F;web?text=%C3%A4%C3%B6%C3%BC%C3%9F'></a>",
+        stringWriter.toString());
+  }
+
+  @Test
+  public void testAttributeQuoting() throws IOException {
+    writer.startElement(HtmlElements.SELECT);
+    writer.writeAttribute(HtmlAttributes.VALUE, "-<->-ü-€-", true);
+    writer.endElement(HtmlElements.SELECT);
+    Assert.assertEquals("attr tag", "\n<select value='-&lt;-&gt;-ü-€-'></select>", stringWriter.toString());
+  }
+
+  @Test
+  public void testTextQuoting() throws IOException {
+    writer.startElement(HtmlElements.TEXTAREA);
+    writer.writeText("-<->-ü-€-");
+    writer.endElement(HtmlElements.TEXTAREA);
+    Assert.assertEquals("attr tag", "\n<textarea>-&lt;-&gt;-ü-€-</textarea>", stringWriter.toString());
+  }
+
+  @Test
+  public void testStringWriter() throws IOException {
+    stringWriter.write("-ü-€-");
+    Assert.assertEquals("-ü-€-", stringWriter.toString());
+  }
+
+  @Test
+  public void testManyChars() throws IOException {
+    writer.startElement(HtmlElements.SELECT);
+    final StringBuilder buffer = new StringBuilder();
+    for (char c = 0x20; c < 0x7F; c++) {
+      buffer.append(c);
+    }
+    for (char c = 0xA0; c < 0x1ff; c++) {
+      buffer.append(c);
+    }
+    writer.writeAttribute(HtmlAttributes.VALUE, buffer.toString(), true);
+    writer.writeText(buffer.toString());
+    writer.endElement(HtmlElements.SELECT);
+
+    String result = buffer.toString(); // all the same but this 4 items
+    result = result.replace("&", "&amp;");
+    result = result.replace("'", "&#x27;");
+    result = result.replace("\"", "&quot;");
+    result = result.replace("/", "&#x2F;");
+    result = result.replace("<", "&lt;");
+    result = result.replace(">", "&gt;");
+    Assert.assertEquals("all chars", "\n<select value='" + result + "'>" + result + "</select>",
+        stringWriter.toString());
+  }
+
+  @Test
+  public void testNonUtf8() throws IOException {
+    final TobagoResponseWriter writer1 = new HtmlResponseWriter(stringWriter, "", "ISO-8859-1");
+    writer1.startElement(HtmlElements.INPUT);
+    writer1.writeAttribute(HtmlAttributes.VALUE, "Gutschein über 100 €.", true);
+    writer1.writeAttribute(HtmlAttributes.READONLY, true);
+    writer1.endElement(HtmlElements.INPUT);
+    writer1.close();
+    Assert.assertEquals("\n<input value='Gutschein &uuml;ber 100 &euro;.' readonly='readonly'>",
+        stringWriter.toString());
+  }
+
+  @Test
+  public void testCharArray() throws IOException {
+    final TobagoResponseWriter writer = new XmlResponseWriter(stringWriter, "text/xml", "ISO-8859-1");
+    writer.writeText("123".toCharArray(), 0, 3);
+    Assert.assertEquals("123", stringWriter.toString());
+  }
+}
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/logback-test.xml b/tobago-3.0.x/tobago-core/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..431deef
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/logback-test.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- Schema is NOT official from logback -->
+<configuration
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="https://raw.github.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{ISO8601} [%-16.16thread] %-5level %-50.50logger{50}:%-20.20method:%-4.4line [%mdc] %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <logger name="org.apache.myfaces.tobago" level="debug"/>
+
+  <root level="info">
+    <appender-ref ref="console"/>
+  </root>
+</configuration>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/theme-config.xml b/tobago-3.0.x/tobago-core/src/test/resources/theme-config.xml
new file mode 100644
index 0000000..36705dd
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/theme-config.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+  <theme-definitions>
+    <theme-definition>
+      <name>test</name>
+      <display-name>Test</display-name>
+      <resource-path>Test</resource-path>
+      <resources production="true">
+        <script name="script/tobago.min.js"/>
+        <style name="tobago.css"/>
+      </resources>
+      <resources production="false">
+        <script name="script/tobago.js"/>
+        <!-- console is moved to production -->
+        <!--<script name="script/tobago-console.js"/>-->
+        <style name="tobago.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/theme-config2.xml b/tobago-3.0.x/tobago-core/src/test/resources/theme-config2.xml
new file mode 100644
index 0000000..b8615eb
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/theme-config2.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+  <theme-definitions>
+    <theme-definition>
+      <name>test2</name>
+      <display-name>Test2</display-name>
+      <resource-path>Test2</resource-path>
+      <fallback>test</fallback>
+      <resources production="false">
+        <script name="script/test.js"/>
+        <style name="tobago.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/theme-config3.xml b/tobago-3.0.x/tobago-core/src/test/resources/theme-config3.xml
new file mode 100644
index 0000000..288f40d
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/theme-config3.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+  <theme-definitions>
+    <theme-definition>
+      <name>test3</name>
+      <display-name>Test3</display-name>
+      <resource-path>Test3</resource-path>
+      <fallback>test2</fallback>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/theme-config4.xml b/tobago-3.0.x/tobago-core/src/test/resources/theme-config4.xml
new file mode 100644
index 0000000..bcaab1c
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/theme-config4.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+  <theme-definitions>
+    <theme-definition>
+      <name>test4</name>
+      <display-name>Test4</display-name>
+      <resource-path>Test4</resource-path>
+      <fallback>test3</fallback>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-1.0.30.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-1.0.30.xml
new file mode 100644
index 0000000..044a11a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-1.0.30.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE tobago-config PUBLIC
+    "-//The Apache Software Foundation//DTD Tobago Config 1.0.30//EN"
+    "http://myfaces.apache.org/tobago/tobago-config-1.0.30.dtd">
+
+<tobago-config>
+  <theme-config>
+    <default-theme>speyside</default-theme>
+  </theme-config>
+  <fix-resource-order>true</fix-resource-order>
+  <fix-layout-transparency>true</fix-layout-transparency>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-1.5.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-1.5.xml
new file mode 100644
index 0000000..ac872c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-1.5.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-1.5.xsd"
+    version="1.5">
+
+  <name>my-name</name>
+
+  <ordering>
+    <after>
+      <name>my-after</name>
+    </after>
+    <before>
+      <name>my-before-1</name>
+      <name>my-before-2</name>
+    </before>
+  </ordering>
+
+  <theme-config>
+    <default-theme>speyside</default-theme>
+    <supported-theme>scarborough</supported-theme>
+    <supported-theme>standard</supported-theme>
+  </theme-config>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-2.0.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-2.0.xml
new file mode 100644
index 0000000..35f89c5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-2.0.xml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+
+  <name>my-name</name>
+
+  <ordering>
+    <after>
+      <name>my-after</name>
+    </after>
+    <before>
+      <name>my-before-1</name>
+      <name>my-before-2</name>
+    </before>
+  </ordering>
+
+  <theme-config>
+    <default-theme>speyside</default-theme>
+    <supported-theme>scarborough</supported-theme>
+    <supported-theme>standard</supported-theme>
+  </theme-config>
+
+  <resource-dir>my-resource-1</resource-dir>
+  <resource-dir>my-resource-2</resource-dir>
+
+  <create-session-secret>false</create-session-secret>
+  <check-session-secret>false</check-session-secret>
+  <prevent-frame-attacks>false</prevent-frame-attacks>
+  <set-nosniff-header>false</set-nosniff-header>
+
+  <content-security-policy mode="on">
+    <directive>default-src 'self'</directive>
+    <directive>frame-src http://apache.org</directive>
+  </content-security-policy>
+
+  <renderers>
+    <renderer>
+      <name>MyRenderer-1</name>
+      <supported-markup>
+        <markup>my-markup-1</markup>
+      </supported-markup>
+    </renderer>
+    <renderer>
+      <name>MyRenderer-2</name>
+      <supported-markup>
+        <markup>my-markup-2-1</markup>
+        <markup>my-markup-2-2</markup>
+      </supported-markup>
+    </renderer>
+  </renderers>
+
+  <theme-definitions>
+    <theme-definition>
+      <name>my-theme-1</name>
+      <display-name>My Theme 1</display-name>
+      <resource-path>/my/path-1</resource-path>
+      <versioned>true</versioned>
+      <renderers>
+        <renderer>
+          <name>ThemeRenderer</name>
+          <supported-markup>
+            <markup>theme-markup</markup>
+          </supported-markup>
+        </renderer>
+      </renderers>
+      <resources production="true">
+        <script name="script.js"/>
+        <style name="style.css"/>
+      </resources>
+    </theme-definition>
+
+    <theme-definition>
+      <name>my-theme-2</name>
+      <resource-path>/my/path-2</resource-path>
+      <fallback>my-theme-1</fallback>
+      <resources production="false"/>
+    </theme-definition>
+
+  </theme-definitions>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-1.0.30.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-1.0.30.xml
new file mode 100644
index 0000000..52a0171
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-1.0.30.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE tobago-config PUBLIC
+    "-//The Apache Software Foundation//DTD Tobago Config 1.0.30//EN"
+    "http://myfaces.apache.org/tobago/tobago-config-1.0.30.dtd">
+
+<tobago-config>
+  <theme-config>
+  </theme-config>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-1.5.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-1.5.xml
new file mode 100644
index 0000000..d0d3c6a
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-1.5.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-1.5.xsd"
+    version="1.5">
+
+  <content-security-policy>
+    <directive>default-src 'self'</directive>
+  </content-security-policy>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-2.0.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-2.0.xml
new file mode 100644
index 0000000..504eb1f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-2.0.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+
+  <content-security-policy disabled="peng">
+  </content-security-policy>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-unknown-version.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-unknown-version.xml
new file mode 100644
index 0000000..13c73d0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-fail-unknown-version.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="unknown-version">
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-for-unit-tests.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-for-unit-tests.xml
new file mode 100644
index 0000000..a81a0ec
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-for-unit-tests.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.6.xsd"
+    version="2.0.6">
+
+  <mime-types>
+    <mime-type>
+      <extension>odt</extension>
+      <type>application/vnd.oasis.opendocument.text</type>
+    </mime-type>
+  </mime-types>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-0.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-0.xml
new file mode 100644
index 0000000..25342d5
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-0.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+
+  <name>name-0</name>
+
+  <prevent-frame-attacks>false</prevent-frame-attacks>
+
+  <content-security-policy mode="on">
+    <directive>default-src 'self'</directive>
+  </content-security-policy>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-1.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-1.xml
new file mode 100644
index 0000000..7ec3dae
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-1.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.6.xsd"
+    version="2.0.6">
+
+  <name>name-1</name>
+
+  <ordering>
+    <after>
+      <name>name-0</name>
+    </after>
+  </ordering>
+
+  <content-security-policy mode="report-only">
+    <directive>image-src http://apache.org</directive>
+  </content-security-policy>
+
+  <mime-types>
+    <mime-type>
+      <extension>test-1</extension>
+      <type>test/one</type>
+    </mime-type>
+    <mime-type>
+      <extension>test-2</extension>
+      <type>test/two</type>
+    </mime-type>
+    <mime-type>
+      <extension>test-3</extension>
+      <type>test/three</type>
+    </mime-type>
+  </mime-types>
+  
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-2.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-2.xml
new file mode 100644
index 0000000..526230b
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-merge-2.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.6.xsd"
+    version="2.0.6">
+
+  <name>name-2</name>
+
+  <ordering>
+    <after>
+      <name>name-1</name>
+    </after>
+  </ordering>
+
+  <content-security-policy mode="off"/>
+
+  <mime-types>
+    <mime-type>
+      <extension>test-2</extension>
+      <type>test/zwei</type>
+    </mime-type>
+  </mime-types>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-untidy-2.0.xml b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-untidy-2.0.xml
new file mode 100644
index 0000000..bbef4f0
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/tobago-config-untidy-2.0.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+
+  <name>
+    <!-- comment -->
+    <!-- comment -->
+    my-name
+    <!-- comment -->
+    <!-- comment -->
+  </name>
+
+  <!-- comment -->
+
+  <ordering>
+    <after>
+      <name>
+        <!-- comment -->
+        my-after
+        <!-- comment -->
+      </name>
+      <!-- comment -->
+    </after>
+    <!-- comment -->
+    <before>
+      <!-- comment -->
+      <name>
+        my-before-1
+      </name>
+      <name>my-before-2</name>
+    </before>
+  </ordering>
+
+  <theme-config>
+    <!-- comment -->
+    <default-theme>
+      <!-- comment -->
+      speyside
+      <!-- comment -->
+    </default-theme>
+    <!-- comment -->
+    <supported-theme>
+      scarborough
+    </supported-theme>
+    <supported-theme>
+      standard
+    </supported-theme>
+  </theme-config>
+
+  <resource-dir
+      >my-resource-1
+  </resource-dir>
+  <resource-dir>
+    my-resource-2
+  </resource-dir>
+
+  <create-session-secret>
+    false
+  </create-session-secret>
+  <check-session-secret>
+    false
+  </check-session-secret>
+  <prevent-frame-attacks>
+    false
+  </prevent-frame-attacks>
+  <set-nosniff-header>
+    false  </set-nosniff-header>
+
+  <content-security-policy mode="on">
+    <directive>
+      default-src 'self'
+    </directive>
+    <directive>
+      frame-src http://apache.org
+    </directive>
+  </content-security-policy>
+
+  <renderers>
+    <renderer>
+      <name>
+        MyRenderer-1
+      </name>
+      <supported-markup>
+        <markup>
+          my-markup-1
+        </markup>
+      </supported-markup>
+    </renderer>
+    <renderer>
+      <name>
+        MyRenderer-2
+      </name>
+      <supported-markup>
+        <markup>
+          my-markup-2-1
+        </markup>
+        <markup>
+          my-markup-2-2
+        </markup>
+      </supported-markup>
+    </renderer>
+  </renderers>
+
+  <theme-definitions>
+    <theme-definition>
+      <name>
+        <!-- comment -->
+        my-theme-1
+        <!-- comment -->
+      </name>
+      <!-- comment -->
+      <display-name>
+        <!-- comment -->
+        <!-- comment -->
+        <!-- comment -->
+        My Theme 1
+        <!-- comment -->
+      </display-name>
+      <resource-path>
+        /my/path-1
+      </resource-path>
+      <versioned>
+        true
+      </versioned>
+      <renderers>
+        <renderer>
+          <name>
+            ThemeRenderer
+          </name>
+          <supported-markup>
+            <!-- comment -->
+            <markup>
+              <!-- comment -->
+              theme-markup
+              <!-- comment -->
+            </markup>
+            <!-- comment -->
+          </supported-markup>
+          <!-- comment -->
+        </renderer>
+      </renderers>
+      <resources production="true">
+        <script name="script.js"/>
+        <style name="style.css"/>
+      </resources>
+    </theme-definition>
+
+    <theme-definition>
+      <name>
+        <!-- comment -->
+        my-theme-2
+        <!-- comment -->
+      </name>
+      <resource-path>
+        /my/path-2
+      </resource-path>
+      <fallback>
+        my-theme-1
+      </fallback>
+      <resources production="false"/>
+    </theme-definition>
+
+  </theme-definitions>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-core/src/test/resources/web-jsptaglibrary_1_2.dtd b/tobago-3.0.x/tobago-core/src/test/resources/web-jsptaglibrary_1_2.dtd
new file mode 100644
index 0000000..4b6fb7f
--- /dev/null
+++ b/tobago-3.0.x/tobago-core/src/test/resources/web-jsptaglibrary_1_2.dtd
@@ -0,0 +1,108 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+-->
+
+<!--
+
+   This is the DTD defining the JavaServer Pages 1.2 Tag Library
+   descriptor (.tld) (XML) file format/syntax.
+
+   A Tag Library is a JAR file containing a valid instance of a Tag Library
+   Descriptor (taglib.tld) file in the META-INF subdirectory, along with the
+   appropriate implementing classes, and other resources required to
+   implement the tags defined therein.
+
+  -->
+
+<!NOTATION WEB-JSPTAGLIB.1_2 PUBLIC
+          "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN">
+
+<!--
+This is the XML DTD for the JSP 1.2 Tag Library Descriptor.
+All JSP 1.2 tag library descriptors must include a DOCTYPE
+of the following form:
+
+  <!DOCTYPE taglib
+        PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
+	"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
+
+-->
+
+<!ELEMENT taglib (tlib-version, jsp-version, short-name, uri?,
+                  display-name?, small-icon?, large-icon?, description?,
+                  validator?, listener*, tag+) >
+
+<!ATTLIST taglib id ID #IMPLIED
+	  xmlns CDATA #FIXED
+		"http://java.sun.com/JSP/TagLibraryDescriptor">
+
+<!ELEMENT tlib-version (#PCDATA) >
+<!ELEMENT jsp-version  (#PCDATA) >
+<!ELEMENT short-name      (#PCDATA) >
+<!ELEMENT uri	 (#PCDATA) >
+<!ELEMENT description	(#PCDATA) >
+<!ELEMENT validator (validator-class, init-param*, description?) >
+<!ELEMENT validator-class (#PCDATA) >
+<!ELEMENT init-param (param-name, param-value, description?)>
+<!ELEMENT param-name (#PCDATA)>
+<!ELEMENT param-value (#PCDATA)>
+<!ELEMENT listener (listener-class) >
+<!ELEMENT listener-class (#PCDATA) >
+<!ELEMENT tag (name, tag-class, tei-class?, body-content?, display-name?,
+               small-icon?, large-icon?, description?, variable*, attribute*,
+               example?) >
+<!ELEMENT tag-class (#PCDATA) >
+<!ELEMENT tei-class (#PCDATA) >
+<!ELEMENT body-content (#PCDATA) >
+<!ELEMENT display-name (#PCDATA) >
+<!ELEMENT large-icon (#PCDATA) >
+<!ELEMENT small-icon (#PCDATA) >
+<!ELEMENT example (#PCDATA) >
+<!ELEMENT variable ( (name-given | name-from-attribute), variable-class?,
+                    declare?, scope?, description?) >
+<!ELEMENT name-given (#PCDATA) >
+<!ELEMENT name-from-attribute (#PCDATA) >
+<!ELEMENT variable-class (#PCDATA) >
+<!ELEMENT declare (#PCDATA) >
+<!ELEMENT scope (#PCDATA) >
+<!ELEMENT attribute (name, required? , rtexprvalue?, type?, description?) >
+<!ELEMENT name	(#PCDATA) >
+<!ELEMENT required    (#PCDATA) >
+<!ELEMENT rtexprvalue (#PCDATA) >
+<!ELEMENT type (#PCDATA) >
+
+<!-- ID attributes -->
+
+<!ATTLIST tlib-version id ID #IMPLIED>
+<!ATTLIST jsp-version id ID #IMPLIED>
+<!ATTLIST short-name id ID #IMPLIED>
+<!ATTLIST uri id ID #IMPLIED>
+<!ATTLIST description id ID #IMPLIED>
+<!ATTLIST example id ID #IMPLIED>
+<!ATTLIST tag id ID #IMPLIED>
+<!ATTLIST tag-class id ID #IMPLIED>
+<!ATTLIST tei-class id ID #IMPLIED>
+<!ATTLIST body-content id ID #IMPLIED>
+<!ATTLIST attribute id ID #IMPLIED>
+<!ATTLIST name id ID #IMPLIED>
+<!ATTLIST required id ID #IMPLIED>
+<!ATTLIST rtexprvalue id ID #IMPLIED>
+<!ATTLIST param-name id ID #IMPLIED>
+<!ATTLIST param-value id ID #IMPLIED>
+<!ATTLIST listener id ID #IMPLIED>
+<!ATTLIST listener-class id ID #IMPLIED>
diff --git a/tobago-3.0.x/tobago-example/pom.xml b/tobago-3.0.x/tobago-example/pom.xml
new file mode 100644
index 0000000..1c27111
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/pom.xml
@@ -0,0 +1,462 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <packaging>pom</packaging>
+  <name>Tobago Examples</name>
+  <artifactId>tobago-example</artifactId>
+
+  <modules>
+    <!--<module>tobago-example-addressbook</module>-->
+    <module>tobago-example-blank</module>
+    <module>tobago-example-data</module>
+    <module>tobago-example-demo</module>
+    <module>tobago-example-portlet</module>
+    <!--<module>tobago-example-test</module>-->
+    <module>tobago-example-assembly</module>
+  </modules>
+
+  <build>
+    <!-- NOTE The addressbook run only with mvn jetty:run-exploded.
+         For the other examples mvn jetty:run should work.
+         For Debugging with jetty set following options
+            MAVEN_OPTS="-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"
+     -->
+    <plugins>
+      <plugin>
+        <groupId>org.apache.tomcat.maven</groupId>
+        <artifactId>tomcat7-maven-plugin</artifactId>
+        <version>2.2</version>
+      </plugin>
+      <plugin>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-maven-plugin</artifactId>
+          <configuration>
+            <!-- use this to change the context path: -->
+<!--
+            <webApp>
+              <contextPath>/example</contextPath>
+            </webApp>
+-->
+            <!-- use this to change the port: -->
+<!--
+            <httpConnector>
+              <port>7080</port>
+            </httpConnector>
+-->
+          </configuration>
+      </plugin>
+      <plugin>
+        <!-- usage: mvn clean package tomee:run -Djsf=provided -->
+        <groupId>org.apache.openejb.maven</groupId>
+        <artifactId>tomee-maven-plugin</artifactId>
+        <version>1.7.4</version>
+        <configuration>
+          <tomeeVersion>1.7.4</tomeeVersion>
+          <tomeeClassifier>plus</tomeeClassifier>
+          <!--<tomeeHttpPort>9090</tomeeHttpPort>-->
+          <!--<context>/demo</context>-->
+          <config>${project.basedir}/src/test/tomee/conf</config>
+        </configuration>
+      </plugin>
+
+    </plugins>
+
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.eclipse.jetty</groupId>
+          <artifactId>jetty-maven-plugin</artifactId>
+          <version>9.2.13.v20150730</version>
+          <!-- Jetty 9.3 requires Java 1.8 -->
+          <!--<version>9.3.3.v20150827</version>-->
+          <configuration>
+            <scanIntervalSeconds>5</scanIntervalSeconds>
+            <webAppConfig>
+              <overrideDescriptor>${override-web-xml}</overrideDescriptor>
+            </webAppConfig>
+<!--
+            <systemProperties>
+              <systemProperty>
+                <name>logback.configurationFile</name>
+                <value>/Users/lofwyr/t/logback.xml</value>
+              </systemProperty>
+              <systemProperty>
+                <name>java.util.logging.config.file</name>
+                <value>logging.properties</value>
+              </systemProperty>
+            </systemProperties>
+-->
+          </configuration>
+<!--
+          <dependencies>
+            <dependency>
+              <groupId>org.slf4j</groupId>
+              <artifactId>jul-to-slf4j</artifactId>
+              <version>${slf4j.version}</version>
+            </dependency>
+            <dependency>
+              <groupId>ch.qos.logback</groupId>
+              <artifactId>logback-classic</artifactId>
+              <version>${logback.version}</version>
+              <scope>runtime</scope>
+            </dependency>
+          </dependencies>
+-->
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-speyside</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-standard</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-classic</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+    <dependency>
+      <groupId>ch.qos.logback</groupId>
+      <artifactId>logback-core</artifactId>
+      <scope>runtime</scope>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+
+    <profile>
+      <id>all-modules</id>
+      <modules>
+        <module>tobago-example-addressbook</module>
+        <module>tobago-example-test</module>
+      </modules>
+
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.myfaces.tobago</groupId>
+          <artifactId>tobago-theme-charlotteville</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.myfaces.tobago</groupId>
+          <artifactId>tobago-theme-scarborough</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.myfaces.tobago</groupId>
+          <artifactId>tobago-theme-richmond</artifactId>
+          <version>${project.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>jsf-provided</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>provided</value>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-api</artifactId>
+          <version>${myfaces20.version}</version>
+          <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-impl</artifactId>
+          <version>${myfaces20.version}</version>
+          <scope>provided</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.0</id>
+      <activation>
+        <property>
+          <name>!jsf</name>
+        </property>
+      </activation>
+      <properties>
+        <override-web-xml>../src/test/jetty/override-myfaces-web.xml</override-web-xml>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-api</artifactId>
+          <version>${myfaces20.version}</version>
+          <scope>compile</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-impl</artifactId>
+          <version>${myfaces20.version}</version>
+          <scope>runtime</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.1</value>
+        </property>
+      </activation>
+      <properties>
+        <override-web-xml>../src/test/jetty/override-myfaces-web.xml</override-web-xml>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-api</artifactId>
+          <version>${myfaces21.version}</version>
+          <scope>compile</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-impl</artifactId>
+          <version>${myfaces21.version}</version>
+          <scope>runtime</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.2</value>
+        </property>
+      </activation>
+      <properties>
+        <override-web-xml>../src/test/jetty/override-myfaces-web.xml</override-web-xml>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-api</artifactId>
+          <version>${myfaces22.version}</version>
+          <scope>compile</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.myfaces.core</groupId>
+          <artifactId>myfaces-impl</artifactId>
+          <version>${myfaces22.version}</version>
+          <scope>runtime</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.0</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.0</value>
+        </property>
+      </activation>
+      <properties>
+        <override-web-xml>../src/test/jetty/override-mojarra-web.xml</override-web-xml>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>com.sun.faces</groupId>
+          <artifactId>jsf-api</artifactId>
+          <version>${mojarra20.version}</version>
+          <scope>compile</scope>
+        </dependency>
+        <dependency>
+          <groupId>com.sun.faces</groupId>
+          <artifactId>jsf-impl</artifactId>
+          <version>${mojarra20.version}</version>
+          <scope>runtime</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.1</value>
+        </property>
+      </activation>
+      <properties>
+        <override-web-xml>../src/test/jetty/override-mojarra-web.xml</override-web-xml>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>com.sun.faces</groupId>
+          <artifactId>jsf-api</artifactId>
+          <version>${mojarra21.version}</version>
+          <scope>compile</scope>
+        </dependency>
+        <dependency>
+          <groupId>com.sun.faces</groupId>
+          <artifactId>jsf-impl</artifactId>
+          <version>${mojarra21.version}</version>
+          <scope>runtime</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.2</value>
+        </property>
+      </activation>
+      <properties>
+        <override-web-xml>../src/test/jetty/override-mojarra-web.xml</override-web-xml>
+      </properties>
+      <dependencies>
+        <dependency>
+          <groupId>com.sun.faces</groupId>
+          <artifactId>jsf-api</artifactId>
+          <version>${mojarra22.version}</version>
+          <scope>compile</scope>
+        </dependency>
+        <dependency>
+          <groupId>com.sun.faces</groupId>
+          <artifactId>jsf-impl</artifactId>
+          <version>${mojarra22.version}</version>
+          <scope>runtime</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>liberty</id>
+<!--
+      <properties>
+        <jsf>provided</jsf>
+      </properties>
+-->
+      <build>
+        <plugins>
+          <plugin>
+            <!-- The usage is documented in the FAQ -->
+            <groupId>com.ibm.websphere.wlp.maven.plugins</groupId>
+            <artifactId>liberty-maven-plugin</artifactId>
+            <version>1.1</version>
+            <configuration>
+              <serverHome>${wlp.directory}</serverHome>
+              <appArchive>${project.build.directory}/${project.build.finalName}.war</appArchive>
+              <serverName>tobago</serverName>
+              <!-- default debugging port is 7777 -->
+              <!--<debug>true</debug>-->
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+      <pluginRepositories>
+        <pluginRepository>
+          <!-- For IBM Websphere Liberty Profile (WLP) -->
+          <id>Liberty</id>
+          <name>Liberty Repository</name>
+          <url>http://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/wasdev/maven/repository/</url>
+          <layout>default</layout>
+          <snapshots>
+            <enabled>false</enabled>
+          </snapshots>
+          <releases>
+            <enabled>true</enabled>
+          </releases>
+        </pluginRepository>
+      </pluginRepositories>
+    </profile>
+
+    <profile>
+      <id>jboss</id>
+      <build>
+        <plugins>
+          <plugin>
+            <!--
+              Running examples with JBoss AS, try:
+              mvn -Pjboss clean jboss-as:run -Djsf=provided
+             -->
+            <groupId>org.jboss.as.plugins</groupId>
+            <artifactId>jboss-as-maven-plugin</artifactId>
+            <version>7.6.Final</version>
+          </plugin>
+          <plugin>
+            <!--
+              Running examples with Wildfly, try:
+              try: mvn -Pjboss clean wildfly:run -Djsf=provided
+             -->
+            <groupId>org.wildfly.plugins</groupId>
+            <artifactId>wildfly-maven-plugin</artifactId>
+            <version>1.0.2.Final</version>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+<!-- TBD: be needed for which cases?
+    <profile>
+      <id>303off</id>
+      <dependencies>
+        <dependency>
+          <groupId>javax.validation</groupId>
+          <artifactId>validation-api</artifactId>
+          <version>1.0.0.GA</version>
+          <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.hibernate</groupId>
+          <artifactId>hibernate-validator</artifactId>
+          <version>4.2.0.Final</version>
+          <scope>provided</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+-->
+
+  </profiles>
+  
+
+</project>
diff --git a/tobago-3.0.x/tobago-example/src/test/jetty/override-mojarra-web.xml b/tobago-3.0.x/tobago-example/src/test/jetty/override-mojarra-web.xml
new file mode 100644
index 0000000..f75d69f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/src/test/jetty/override-mojarra-web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+  <context-param>
+    <param-name>javax.faces.PROJECT_STAGE</param-name>
+    <param-value>Development</param-value>
+    <!--<param-value>Production</param-value>-->
+  </context-param>
+
+  <listener>
+    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
+  </listener>
+
+</web-app>
diff --git a/tobago-3.0.x/tobago-example/src/test/jetty/override-myfaces-web.xml b/tobago-3.0.x/tobago-example/src/test/jetty/override-myfaces-web.xml
new file mode 100644
index 0000000..c7de889
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/src/test/jetty/override-myfaces-web.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
+
+  <context-param>
+    <param-name>javax.faces.PROJECT_STAGE</param-name>
+    <param-value>Development</param-value>
+    <!--<param-value>Production</param-value>-->
+  </context-param>
+
+  <listener>
+    <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
+  </listener>
+
+</web-app>
diff --git a/tobago-3.0.x/tobago-example/src/test/resources/jettykeystore b/tobago-3.0.x/tobago-example/src/test/resources/jettykeystore
new file mode 100644
index 0000000..59c204f
Binary files /dev/null and b/tobago-3.0.x/tobago-example/src/test/resources/jettykeystore differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/pom.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/pom.xml
new file mode 100644
index 0000000..4c151fa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/pom.xml
@@ -0,0 +1,402 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-example</artifactId>
+    <version>3.0.3-SNAPSHOT</version>
+  </parent>
+  <artifactId>tobago-example-addressbook</artifactId>
+  <packaging>war</packaging>
+  <name>Tobago Example Addressbook (Java EE 6)</name>
+  <description>A simple, but full functional application with persistence.</description>
+
+  <properties>
+    <openjpa.version>2.3.0</openjpa.version>
+    <openwebbeans.version>1.2.8</openwebbeans.version>
+    <deltaspike.version>1.7.1</deltaspike.version>
+  </properties>
+
+  <build>
+    <finalName>tobago-example-addressbook</finalName>
+    <plugins>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <phase>process-classes</phase>
+            <configuration>
+              <tasks>
+                <java classname="org.apache.openjpa.enhance.PCEnhancer" classpathref="maven.runtime.classpath" dir="target/classes" fork="true" />
+              </tasks>
+            </configuration>
+            <goals>
+              <goal>run</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-maven-plugin</artifactId>
+        <configuration>
+          <loginServices>
+            <loginService implementation="org.eclipse.jetty.security.HashLoginService">
+              <name>addressbook-realm</name>
+              <config>src/test/resources/realm.properties</config>
+            </loginService>
+          </loginServices>
+          <stopKey>stopKey</stopKey>
+          <stopPort>9999</stopPort>
+          <systemProperties>
+            <systemProperty>
+              <name>derby.stream.error.file</name>
+              <value>target/derby.log</value>
+            </systemProperty>
+          </systemProperties>
+        </configuration>
+        <dependencies>
+       </dependencies>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+      <version>1.0</version>
+      <!-- XXX websphere-provided -->
+<!--
+        <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-validation_1.0_spec</artifactId>
+      <version>1.1</version>
+      <!-- XXX websphere-provided -->
+<!--
+        <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-atinject_1.0_spec</artifactId>
+      <version>1.0</version>
+      <!-- XXX websphere-provided -->
+<!--
+        <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+      <version>1.0</version>
+      <!-- XXX websphere-provided -->
+<!--
+        <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-annotation_1.1_spec</artifactId>
+      <version>1.0.1</version>
+      <scope>provided</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.openwebbeans</groupId>
+      <artifactId>openwebbeans-impl</artifactId>
+      <version>${openwebbeans.version}</version>
+    <!-- XXX websphere-provided -->
+<!--
+      <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>javassist</groupId>
+      <artifactId>javassist</artifactId>
+      <version>3.12.1.GA</version>
+    <!-- XXX websphere-provided -->
+<!--
+      <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openwebbeans</groupId>
+      <artifactId>openwebbeans-spi</artifactId>
+      <version>${openwebbeans.version}</version>
+    <!-- XXX websphere-provided -->
+<!--
+      <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openwebbeans</groupId>
+      <artifactId>openwebbeans-web</artifactId>
+      <version>${openwebbeans.version}</version>
+    <!-- XXX websphere-provided -->
+<!--
+      <scope>provided</scope>
+-->
+    </dependency>
+    <dependency>
+      <groupId>org.apache.openwebbeans</groupId>
+      <artifactId>openwebbeans-resource</artifactId>
+      <version>${openwebbeans.version}</version>
+      <!-- XXX websphere-provided -->
+<!--
+        <scope>provided</scope>
+-->
+    </dependency>
+
+    <!-- DeltaSpike -->
+    <dependency>
+      <groupId>org.apache.deltaspike.modules</groupId>
+      <artifactId>deltaspike-jsf-module-impl</artifactId>
+      <version>${deltaspike.version}</version>
+    </dependency>
+
+    <dependency>
+    	<groupId>org.apache.geronimo.specs</groupId>
+    	<artifactId>geronimo-jpa_3.0_spec</artifactId>
+    	<version>1.1.1</version>
+      <scope>provided</scope>
+    </dependency>
+    <!-- <dependency>
+      <groupId>org.apache.openjpa</groupId>
+      <artifactId>openjpa</artifactId>
+      <version>${openjpa.version}</version>
+    </dependency>-->
+    <!--dependency>
+      <groupId>org.apache.openjpa</groupId>
+      <artifactId>openjpa-persistence</artifactId>
+      <version>${openjpa.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>hsqldb</groupId>
+          <artifactId>hsqldb</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>ant</groupId>
+          <artifactId>ant</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency-->
+    <dependency>
+      <groupId>org.apache.openjpa</groupId>
+      <artifactId>openjpa-persistence-jdbc</artifactId>
+      <version>${openjpa.version}</version>
+    </dependency>
+    <!--dependency>
+      <groupId>org.apache.openjpa</groupId>
+      <artifactId>openjpa-xmlstore</artifactId>
+      <version>${openjpa.version}</version>
+      <exclusions>
+        <exclusion>
+          <groupId>ant</groupId>
+          <artifactId>ant</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency-->
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.derby</groupId>
+      <artifactId>derby</artifactId>
+      <version>10.12.1.1</version>
+    </dependency>
+    <dependency>
+       <groupId>org.apache.geronimo.specs</groupId>
+       <artifactId>geronimo-servlet_3.0_spec</artifactId>
+       <version>1.0</version>
+       <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+
+    <profile>
+      <id>jsf-provided</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>provided</value>
+        </property>
+      </activation>
+    </profile>
+
+    <profile>
+      <id>default</id>
+      <activation>
+        <property>
+          <name>!jsf</name>
+        </property>
+      </activation>
+      <dependencies>
+
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+
+        <!-- OWB -->
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-web</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-resource</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.0</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.0</value>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.1</value>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.2</value>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.0</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.0</value>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.1</value>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.2</value>
+        </property>
+      </activation>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+      </dependencies>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/appended-resources/META-INF/LICENSE b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/appended-resources/META-INF/LICENSE
new file mode 100644
index 0000000..ebb9643
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/appended-resources/META-INF/LICENSE
@@ -0,0 +1,4 @@
+For the FLAG ICONS
+
+   These flag icons are available for free use
+   for any purpose with no requirement for attribution.
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..2eedc19
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,2 @@
+This product includes flag icons developed by
+Mark James (http://www.famfamfam.com/lab/icons/flags/)
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Address.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Address.java
new file mode 100644
index 0000000..b8266b4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Address.java
@@ -0,0 +1,327 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToOne;
+import javax.persistence.PostLoad;
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+import javax.persistence.Version;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Locale;
+
+@Entity
+public class Address implements Serializable {
+  private static final long serialVersionUID = 1833416321633117657L;
+  private static final Logger LOG = LoggerFactory.getLogger(Address.class);
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  private Integer id;
+  @Version
+  private Integer revision;
+  private String firstName;
+  private String lastName;
+  private String street;
+  private String houseNumber;
+  private String city;
+  private String zipCode;
+  @Transient
+  private Locale country;
+  private String languageCode;
+  private String countryCode;
+  private String phone;
+  private String mobile;
+  private String fax;
+  @Transient
+  private EmailAddress email;
+  private String emailStr;
+  private String icq;
+  private String homePage;
+  @Temporal(TemporalType.DATE)
+  private Date dayOfBirth;
+  private String note;
+  private String company;
+  private String jobTitle;
+  private String jobPhone;
+  @Transient
+  private EmailAddress jobEmail;
+  private String jobEmailStr;
+  private String jobHomePage;
+  @OneToOne(cascade = {CascadeType.ALL})
+  private Picture picture;
+
+
+  public Address() {
+    LOG.debug("Creating new Address");
+  }
+
+  public void fill(final Address fromAddress) {
+    id = fromAddress.getId();
+    firstName = fromAddress.getFirstName();
+    lastName = fromAddress.getLastName();
+    street = fromAddress.getStreet();
+    houseNumber = fromAddress.getHouseNumber();
+    city = fromAddress.getCity();
+    zipCode = fromAddress.getZipCode();
+    country = fromAddress.getCountry();
+    phone = fromAddress.getPhone();
+    mobile = fromAddress.getMobile();
+    fax = fromAddress.getFax();
+    email = fromAddress.getEmail();
+    dayOfBirth = fromAddress.getDayOfBirth();
+    homePage = fromAddress.getHomePage();
+    note = fromAddress.getNote();
+    company = fromAddress.getCompany();
+    jobTitle = fromAddress.getJobTitle();
+    jobPhone = fromAddress.getJobPhone();
+    jobEmail = fromAddress.getJobEmail();
+    jobHomePage = fromAddress.getJobHomePage();
+  }
+
+  @PrePersist
+  @PreUpdate
+  private void store() {
+    if (country != null) {
+      countryCode = country.getCountry();
+      languageCode = country.getLanguage();
+    }
+    if (email != null) {
+      emailStr = email.getEmail();
+    }
+    if (jobEmail != null) {
+      jobEmailStr = jobEmail.getEmail();
+    }
+  }
+  
+  @PostLoad
+  private void load() {
+    if (countryCode != null && languageCode != null) {
+      country = new Locale(languageCode, countryCode);
+    }
+    if (emailStr != null) {
+      email = new EmailAddress(emailStr);
+    }
+    if (jobEmailStr != null) {
+      jobEmail = new EmailAddress(jobEmailStr);
+    }
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public void setId(final Integer id) {
+    this.id = id;
+  }
+
+  public String getFirstName() {
+    return firstName;
+  }
+
+  public void setFirstName(final String firstName) {
+    this.firstName = firstName;
+  }
+
+  public String getLastName() {
+    return lastName;
+  }
+
+  public void setLastName(final String lastName) {
+    this.lastName = lastName;
+  }
+
+  public String getStreet() {
+    return street;
+  }
+
+  public void setStreet(final String street) {
+    this.street = street;
+  }
+
+  public String getHouseNumber() {
+    return houseNumber;
+  }
+
+  public void setHouseNumber(final String houseNumber) {
+    this.houseNumber = houseNumber;
+  }
+
+  public String getCity() {
+    return city;
+  }
+
+  public void setCity(final String city) {
+    this.city = city;
+  }
+
+  public String getZipCode() {
+    return zipCode;
+  }
+
+  public void setZipCode(final String zipCode) {
+    this.zipCode = zipCode;
+  }
+
+  public Locale getCountry() {
+    return country;
+  }
+
+  public void setCountry(final Locale country) {
+    this.country = country;
+  }
+
+  public String getPhone() {
+    return phone;
+  }
+
+  public void setPhone(final String phone) {
+    this.phone = phone;
+  }
+
+  public String getMobile() {
+    return mobile;
+  }
+
+  public void setMobile(final String mobile) {
+    this.mobile = mobile;
+  }
+
+  public String getFax() {
+    return fax;
+  }
+
+  public void setFax(final String fax) {
+    this.fax = fax;
+  }
+
+  public EmailAddress getEmail() {
+    return email;
+  }
+
+  public void setEmail(final EmailAddress email) {
+    if (email != null) {
+      emailStr = email.getEmail();
+    }
+    this.email = email;
+  }
+
+  public String getIcq() {
+    return icq;
+  }
+
+  public void setIcq(final String icq) {
+    this.icq = icq;
+  }
+
+  public String getHomePage() {
+    return homePage;
+  }
+
+  public void setHomePage(final String homePage) {
+    this.homePage = homePage;
+  }
+
+  public Date getDayOfBirth() {
+    return dayOfBirth;
+  }
+
+  public void setDayOfBirth(final Date dayOfBirth) {
+    this.dayOfBirth = dayOfBirth;
+  }
+
+  public String getNote() {
+    return note;
+  }
+
+  public void setNote(final String note) {
+    this.note = note;
+  }
+
+  public String getCompany() {
+    return company;
+  }
+
+  public void setCompany(final String company) {
+    this.company = company;
+  }
+
+  public String getJobTitle() {
+    return jobTitle;
+  }
+
+  public void setJobTitle(final String jobTitle) {
+    this.jobTitle = jobTitle;
+  }
+
+  public String getJobPhone() {
+    return jobPhone;
+  }
+
+  public void setJobPhone(final String jobPhone) {
+    this.jobPhone = jobPhone;
+  }
+
+  public EmailAddress getJobEmail() {
+    return jobEmail;
+  }
+
+  public void setJobEmail(final EmailAddress jobEmail) {
+    if (jobEmail != null) {
+      jobEmailStr = jobEmail.getEmail();
+    }
+    this.jobEmail = jobEmail;
+  }
+
+  public String getJobHomePage() {
+    return jobHomePage;
+  }
+
+  public void setJobHomePage(final String jobHomePage) {
+    this.jobHomePage = jobHomePage;
+  }
+
+  public boolean hasPicture() {
+    return picture != null;
+  }
+
+  public Picture getPicture() {
+    return picture;
+  }
+
+  public void setPicture(final Picture picture) {
+    this.picture = picture;
+  }
+
+  public String toString() {
+    return id + ": " + firstName + " " + lastName;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/AddressDao.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/AddressDao.java
new file mode 100644
index 0000000..51d750d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/AddressDao.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+import java.util.List;
+
+public interface AddressDao {
+
+  Address updateAddress(Address address);
+
+  List<Address> findAddresses(String filter);
+
+  List<Address> findAddresses(String filter, String column, boolean order);
+
+  void removeAddress(Address address);
+
+  Address getAddress(Integer id);
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/DerbyShutdownServletContextListener.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/DerbyShutdownServletContextListener.java
new file mode 100644
index 0000000..24a0fc5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/DerbyShutdownServletContextListener.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.servlet.annotation.WebListener;
+import java.sql.DriverManager;
+
+@WebListener
+public class DerbyShutdownServletContextListener implements ServletContextListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DerbyShutdownServletContextListener.class);
+
+  @Override
+  public void contextInitialized(final ServletContextEvent servletContextEvent) {
+
+  }
+
+  // todo: should not be shut down in case of the "InMemoryAddressDao" alternative
+
+  @Override
+  public void contextDestroyed(final ServletContextEvent servletContextEvent) {
+    try {
+      DriverManager.getConnection("jdbc:derby:target/addressDB;shutdown=true");
+    } catch (final Exception e) {
+      LOG.error("", e); 
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/EmailAddress.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/EmailAddress.java
new file mode 100644
index 0000000..25ab961
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/EmailAddress.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+
+public class EmailAddress {
+
+  private String email;
+
+  public EmailAddress(final String email) {
+    this.email = email;
+  }
+
+  public String getEmail() {
+    return email;
+  }
+
+  public void setEmail(final String email) {
+    this.email = email;
+  }
+
+  public String getLocalPart() {
+    final String[] parts = email.split("@");
+    return parts[0];
+  }
+
+  public String getDomain() {
+    final String[] parts = email.split("@");
+    return parts[1];
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    final EmailAddress that = (EmailAddress) o;
+
+    if (email != null ? !email.equals(that.email) : that.email != null) {
+      return false;
+    }
+
+    return true;
+  }
+
+  public int hashCode() {
+    return (email != null ? email.hashCode() : 0);
+  }
+
+  @Override
+  public String toString() {
+     return email;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/InMemoryAddressDao.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/InMemoryAddressDao.java
new file mode 100644
index 0000000..9fb9c04
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/InMemoryAddressDao.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.inject.Alternative;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+@Alternative
+@ApplicationScoped
+public class InMemoryAddressDao implements AddressDao, Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(InMemoryAddressDao.class);
+
+  private List<Address> addresses;
+
+  public InMemoryAddressDao() {
+    addresses = new ArrayList<Address>();
+  }
+
+  @Override
+  public synchronized Address updateAddress(final Address address) {
+    LOG.debug("Trying address: "+address);
+    final Address storedAddress = getAddress(address.getId());
+    if (storedAddress == null) {
+      address.setId(addresses.size()+1);
+      LOG.debug("Creating address: "+address);
+      addresses.add(address);
+    } else {
+      LOG.debug("Updating address : "+address);
+      LOG.debug("Stored address is: "+storedAddress);
+      storedAddress.fill(address);
+    }
+    return address;
+  }
+
+  @Override
+  public List<Address> findAddresses(final String filter, final String column, final boolean order) {
+    return findAddresses(filter);
+  }
+
+  @Override
+  public synchronized List<Address> findAddresses(final String filter) {
+    LOG.debug("Find addresses: "+addresses);
+    return Collections.unmodifiableList(addresses);
+  }
+
+  @Override
+  public synchronized void removeAddress(final Address address) {
+    final Iterator<Address> it = addresses.iterator();
+    while (it.hasNext()) {
+      if (it.next().getId().equals(address.getId())) {
+        it.remove();
+      }
+    }
+  }
+
+  @Override
+  public Address getAddress(final Integer id) {
+    for (final Address address : addresses) {
+      if (address.getId().equals(id)) {
+        return address;
+      }
+    }
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/JpaAddressDao.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/JpaAddressDao.java
new file mode 100644
index 0000000..eb8ca3c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/JpaAddressDao.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+//import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.sql.DataSourceDefinition;
+import javax.enterprise.context.ApplicationScoped;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import java.io.Serializable;
+import java.util.List;
+
+@DataSourceDefinition(
+    name = "addressBookDataSource",
+    url = "jdbc:derby:target/addressDB;create=true",
+    className = "org.apache.derby.jdbc.EmbeddedDriver"
+)
+//@Transactional
+@ApplicationScoped
+public class JpaAddressDao implements AddressDao, Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(JpaAddressDao.class);
+
+  @PersistenceContext(unitName = "addressBook")
+  private EntityManager entityManager;
+
+  @Override
+  public Address updateAddress(final Address address) {
+    if (address.getId() == null) {
+      entityManager.persist(address);
+    } else {
+      final Picture picture = address.getPicture();
+      if (picture != null && picture.getId() == null) {
+        entityManager.persist(picture);
+      }
+      entityManager.merge(address);
+    }
+    return address;
+  }
+//  @Transactional(readOnly = true)
+  @Override
+  public List<Address> findAddresses(final String filter) {
+    return findAddresses(filter, null, true);
+  }
+
+//  @Transactional(readOnly = true)
+  @Override
+  @SuppressWarnings("unchecked")
+  public List<Address> findAddresses(String filter, final String column, final boolean order) {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("select a from Address a");
+    if (filter != null) {
+      if (filter.indexOf('_') == -1 && filter.indexOf('%') == -1) {
+        filter = "%" + filter + "%";
+      }
+      builder.append(" where a.firstName like '");
+      builder.append(filter);
+      builder.append("' or a.lastName like '");
+      builder.append(filter);
+      builder.append("'");
+    }
+    if (column != null) {
+      builder.append(" order by a.");
+      builder.append(column);
+      builder.append(order ? " desc" : " asc");
+    }
+    final Query query = entityManager.createQuery(builder.toString());
+    return query.getResultList();
+  }
+
+  @Override
+  public void removeAddress(Address address) {
+    address = getAddress(address.getId());
+    entityManager.remove(address);
+  }
+//  @Transactional(readOnly = true)
+  @Override
+  public Address getAddress(final Integer id) {
+    return entityManager.find(Address.class, id);
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/KillSession.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/KillSession.java
new file mode 100644
index 0000000..82cbc33
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/KillSession.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+@WebServlet("/KillSession")
+public class KillSession extends HttpServlet {
+
+  private static final Logger LOG = LoggerFactory.getLogger(KillSession.class);
+
+  @Override
+  protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+      throws ServletException, IOException {
+    final HttpSession session = request.getSession(false);
+    if (session != null) {
+       session.invalidate();
+      LOG.info("session killed");
+    } else {
+      LOG.info("no session to kill");
+    }
+    response.getOutputStream().write("session killed".getBytes());
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/OpenJpaLoadTimeWeaver.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/OpenJpaLoadTimeWeaver.java
new file mode 100644
index 0000000..7929acd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/OpenJpaLoadTimeWeaver.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+//import org.springframework.instrument.classloading.SimpleInstrumentableClassLoader;
+//import org.springframework.instrument.classloading.SimpleLoadTimeWeaver;
+
+
+/**
+ * <a href ="https://issues.apache.org/jira/browse/OPENJPA-40">COPY FROM OPENJPA-40</a>
+ * OpenJPA-specific SimpleLoadTimeWeaver which excludes all the core
+ * <em>org.apache.openjpa</em> packages from being instrumented. This
+ * is important, since enhanced classes will wind up implementing
+ * <em>org.apache.openjpa.enhance.PersistenceCapable</em>, so it there
+ * is a mismatch between the PersistenceCapable that is loaded by the
+ * system classloader and the one that is loaded by the 
+ * instrumenting ClassLoader, then OpenJPA will not function properly.
+ *
+ * <p>
+ *
+ * This loader can be specific by including the following in the 
+ * spring configuration XML as follows:
+ *
+ * <p>
+ *
+ * <code>
+ *  &lt;bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"&rt;
+ *  ...
+ *    &lt;property name="loadTimeWeaver"&rt;
+ *        &lt;bean class="org.apache.myfaces.tobago.example.addressbook.OpenJpaLoadTimeWeaver"/&rt;
+ *    &lt;/property&rt;
+ *    &lt;/bean&rt;
+ * </code>
+ * 
+ * author Marc Prud'hommeaux
+ * @since 2.0
+ */
+/*
+public class OpenJpaLoadTimeWeaver extends SimpleLoadTimeWeaver {
+
+    public OpenJpaLoadTimeWeaver() {
+        super();
+        ((SimpleInstrumentableClassLoader) getInstrumentableClassLoader()).
+            excludePackage("org.apache.openjpa");
+    }
+
+    public OpenJpaLoadTimeWeaver(SimpleInstrumentableClassLoader loader) {
+        super(loader);
+        ((SimpleInstrumentableClassLoader) getInstrumentableClassLoader()).
+            excludePackage("org.apache.openjpa");
+    }
+}
+*/
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
new file mode 100644
index 0000000..7f60763
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/Picture.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook;
+
+import org.apache.commons.io.IOUtils;
+
+import javax.persistence.Basic;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Lob;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+
+@Entity
+public class Picture implements Serializable {
+  private static final long serialVersionUID = -7637551581782102682L;
+  @Id
+  @GeneratedValue(strategy = GenerationType.IDENTITY)
+  private Integer id;
+  private String contentType;
+  @Lob
+  @Basic(fetch = FetchType.EAGER)
+  private byte [] content;
+
+
+  public Picture() {
+  }
+
+  public Picture(final String contentType, final InputStream inputStream) throws IOException {
+    this.contentType = contentType;
+    this.content = IOUtils.toByteArray(inputStream);
+  }
+
+  public Integer getId() {
+    return id;
+  }
+
+  public String getContentType() {
+    return contentType;
+  }
+
+  public byte[] getContent() {
+    return content;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/AdminController.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/AdminController.java
new file mode 100644
index 0000000..e319040
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/AdminController.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.security.RolesAllowed;
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+import javax.swing.BoundedRangeModel;
+import javax.swing.DefaultBoundedRangeModel;
+import java.io.Serializable;
+import java.lang.management.ManagementFactory;
+import java.lang.management.MemoryMXBean;
+import java.lang.management.MemoryUsage;
+
+@Named("admin")
+@ApplicationScoped
+public class AdminController implements Serializable {
+
+  private static final String OUTCOME_ADMIN = "admin";
+
+  private BoundedRangeModel memoryUsage;
+  private String state;
+
+  @RolesAllowed("admin")
+  public String admin() {
+    return OUTCOME_ADMIN;
+  }
+
+  @PostConstruct
+  public void update() {
+    final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();
+    final MemoryUsage memory = memoryBean.getHeapMemoryUsage();
+    memoryUsage = new DefaultBoundedRangeModel(Long.valueOf(memory.getUsed() / 1024).intValue(),
+        0, 0, Long.valueOf(memory.getMax() / 1024).intValue());
+    final int percentValue = memoryUsage.getValue() / (memoryUsage.getMaximum() * 100);
+    if (percentValue <= 80) {
+      state = "ok";
+    } else if (percentValue > 95) {
+      state = "error";
+    } else {
+      state = "warn";
+    }
+  }
+
+  public boolean getUpdateMemory() {
+    update();
+    return true;
+  }
+
+  public BoundedRangeModel getMemory() {
+    return memoryUsage;
+  }
+
+  public String getState() {
+    return state;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
new file mode 100644
index 0000000..1e117fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Controller.java
@@ -0,0 +1,433 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import org.apache.deltaspike.core.api.scope.WindowScoped;
+import org.apache.myfaces.tobago.component.UIColumn;
+import org.apache.myfaces.tobago.component.UISheet;
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.TobagoContext;
+import org.apache.myfaces.tobago.event.SortActionEvent;
+import org.apache.myfaces.tobago.example.addressbook.Address;
+import org.apache.myfaces.tobago.example.addressbook.AddressDao;
+import org.apache.myfaces.tobago.example.addressbook.Picture;
+import org.apache.myfaces.tobago.model.SelectItem;
+import org.apache.myfaces.tobago.model.SheetState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.PostConstruct;
+import javax.faces.application.Application;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+import javax.faces.validator.ValidatorException;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.Part;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+@Named("controller")
+@WindowScoped
+public class Controller implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Controller.class);
+
+  private static final String OUTCOME_LIST = "list";
+  private static final String OUTCOME_EDITOR = "editor";
+
+  public static final Map<Locale, String> FLAGS;
+
+  private List<Address> currentAddressList;
+  private Address currentAddress;
+  private SheetState selectedAddresses;
+
+  private String searchCriterion;
+
+  private Locale language;
+
+  private List<SelectItem> languages = new ArrayList<SelectItem>();
+
+  @Inject
+  private Countries countries;
+
+  private Theme theme;
+
+  private List<SelectItem> themeItems = new ArrayList<SelectItem>();
+
+  private boolean simple;
+
+  private boolean renderPopup;
+  private boolean renderFirstName = true;
+  private boolean renderLastName = true;
+  private boolean renderDayOfBirth = true;
+
+  @Inject
+  private AddressDao addressDao;
+
+  private Part part;
+  private boolean renderFileUploadPopup;
+
+  static {
+    FLAGS = new HashMap<Locale, String>(3);
+    FLAGS.put(Locale.GERMAN, "image/addressbook/icon/flag-de.png");
+    FLAGS.put(Locale.UK, "image/addressbook/icon/flag-gb.png");
+    FLAGS.put(Locale.US, "image/addressbook/icon/flag-us.png");
+  }
+
+  @PostConstruct
+  public void init() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final Application application = facesContext.getApplication();
+    language = application.getDefaultLocale();
+    countries.init(language);
+    facesContext.getExternalContext().getSession(true);
+    initLanguages();
+
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(facesContext);
+    final List<Theme> themes = new ArrayList<Theme>(tobagoConfig.getSupportedThemes());
+    themes.add(0, tobagoConfig.getDefaultTheme());
+    themeItems = new ArrayList<SelectItem>();
+    for (final Theme theme : themes) {
+      themeItems.add(new SelectItem(theme, theme.getDisplayName()));
+    }
+
+    theme = TobagoContext.getInstance(facesContext).getTheme();
+    currentAddressList = addressDao.findAddresses(searchCriterion);
+  }
+
+  public void setAddressDao(final AddressDao addressDao) {
+    this.addressDao = addressDao;
+  }
+
+  public void sheetSorter(final ActionEvent event) {
+    if (event instanceof SortActionEvent) {
+      final SortActionEvent sortEvent = (SortActionEvent) event;
+      final UIColumn column = (UIColumn) sortEvent.getColumn();
+
+      final SheetState sheetState = ((UISheet) sortEvent.getSheet()).getSheetState(FacesContext.getCurrentInstance());
+      currentAddressList = addressDao.findAddresses(searchCriterion, column.getId(), sheetState.isAscending());
+    }
+  }
+
+  public String search() {
+    currentAddressList = addressDao.findAddresses(searchCriterion);
+    return OUTCOME_LIST;
+  }
+
+  public String createAddress() {
+    LOG.debug("action: createAddress");
+    currentAddress = new Address();
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    Locale locale = facesContext.getViewRoot().getLocale();
+    // XXX use better datatype for countries than Locale
+    if (Locale.GERMAN.equals(locale)) {
+      locale = Locale.GERMANY;
+    }
+    currentAddress.setCountry(locale);
+    return OUTCOME_EDITOR;
+  }
+
+  public String addDummyAddresses() throws IOException {
+    for (int i=0; i<100; ++i) {
+      currentAddress = RandomAddressGenerator.generateAddress();
+      store();
+    }
+    return OUTCOME_LIST;
+  }
+
+  public String editAddress() {
+    LOG.debug("action: editAddress");
+    final List<Integer> selection = selectedAddresses.getSelectedRows();
+    if (selection.size() != 1) {
+      final FacesMessage error
+          = new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please select exactly one address!", null);
+      FacesContext.getCurrentInstance().addMessage(null, error);
+      return null;
+    }
+    currentAddress = currentAddressList.get(selection.get(0));
+    return OUTCOME_EDITOR;
+  }
+
+  public String deleteAddresses() {
+    final List<Integer> selection = selectedAddresses.getSelectedRows();
+    if (selection.size() < 1) {
+      final FacesMessage error = new FacesMessage("Please select at least one address.");
+      FacesContext.getCurrentInstance().addMessage(null, error);
+      return null;
+    }
+    Collections.sort(selection); // why?
+    for (int i = selection.size() - 1; i >= 0; i--) {
+      final Address address = currentAddressList.get(selection.get(i));
+      addressDao.removeAddress(address);
+    }
+    selectedAddresses.resetSelected();
+    currentAddressList = addressDao.findAddresses(searchCriterion);
+    return OUTCOME_LIST;
+  }
+
+  public String store() {
+    LOG.debug("action: storeAddress");
+    currentAddress = addressDao.updateAddress(currentAddress);
+    selectedAddresses.resetSelected();
+    currentAddressList = addressDao.findAddresses(searchCriterion);
+    return OUTCOME_LIST;
+  }
+
+  public String cancel() {
+    currentAddressList = addressDao.findAddresses(searchCriterion);
+    return OUTCOME_LIST;
+  }
+
+  public String languageChangedList() {
+    initLanguages();
+    return OUTCOME_LIST;
+  }
+
+  public String themeChanged() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final TobagoContext tobagoContext = TobagoContext.getInstance(facesContext);
+    tobagoContext.setTheme(theme);
+    return null;
+  }
+
+  public String getCurrentAddressPictureUrl() {
+     return (currentAddress != null && currentAddress.getPicture() != null)
+         ? FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath() + "/faces/picture?id=XXXX"
+         :"image/empty-portrait.png";
+
+   }
+  
+  public void validatePhoneNumber(
+      final FacesContext context, final UIComponent component, final Object value) {
+    final String phoneNumber = (String) value;
+    if (phoneNumber == null || phoneNumber.length() == 0) {
+      return;
+    }
+    if (!phoneNumber.matches("\\+?[0-9 ]*(\\([0-9 ]*\\))?[0-9 ]*")) {
+      throw new ValidatorException(MessageUtils.createErrorMessage(
+          "validatorPhone", context));
+    }
+  }
+
+  public List getCurrentAddressList() {
+    return currentAddressList;
+  }
+
+  public Address getCurrentAddress() {
+    return currentAddress;
+  }
+
+  public SheetState getSelectedAddresses() {
+    return selectedAddresses;
+  }
+
+  public void setSelectedAddresses(final SheetState selectedAddresses) {
+    this.selectedAddresses = selectedAddresses;
+  }
+
+  public boolean isRenderFileUploadPopup() {
+    return renderFileUploadPopup;
+  }
+
+  public void setRenderFileUploadPopup(final boolean renderFileUploadPopup) {
+    LOG.debug(">>> " + renderFileUploadPopup);
+    this.renderFileUploadPopup = renderFileUploadPopup;
+  }
+
+  public String cancelFileUploadPopup() {
+    setRenderFileUploadPopup(false);
+    return null;
+  }
+
+  public void setRenderPopup(final boolean renderPopup) {
+    this.renderPopup = renderPopup;
+  }
+
+  public boolean isRenderPopup() {
+    return renderPopup;
+  }
+
+  public String selectColumns() {
+    setRenderPopup(true);
+    return OUTCOME_LIST;
+  }
+
+  public String okFileUpload() throws IOException {
+    setRenderFileUploadPopup(false);
+    final Picture picture = new Picture(part.getContentType(), part.getInputStream());
+    currentAddress.setPicture(picture);
+    return null;
+  }
+
+  public String cancelFileUpload() {
+    setRenderFileUploadPopup(false);
+    return null;
+  }
+
+  public String cancelPopup() {
+    setRenderPopup(false);
+    return OUTCOME_LIST;
+  }
+
+  public String logout() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
+    if (session != null) {
+      session.invalidate();
+    }
+    return "logout";
+  }
+
+  public String getVersion() {
+    return getClass().getPackage().getImplementationVersion();
+  }
+
+  public Locale getLanguage() {
+    return language;
+  }
+
+  public String getDisplayLanguage() {
+    return language.getDisplayName(language);
+  }
+
+  public void setLanguage(final Locale language) {
+    this.language = language;
+  }
+
+  public List<SelectItem> getLanguages() {
+    return languages;
+  }
+
+  public void setLanguages(final List<SelectItem> languages) {
+    this.languages = languages;
+  }
+
+  public Countries getCountries() {
+    return countries;
+  }
+
+  public List<SelectItem> getThemeItems() {
+    return themeItems;
+  }
+
+  public Theme getTheme() {
+    return theme;
+  }
+
+  public void setTheme(final Theme theme) {
+    this.theme = theme;
+  }
+
+  public boolean isSimple() {
+    return simple;
+  }
+
+  public void setSimple(final boolean simple) {
+    this.simple = simple;
+  }
+
+  public boolean isRenderFirstName() {
+    return renderFirstName;
+  }
+
+  public void setRenderFirstName(final boolean renderFirstName) {
+    this.renderFirstName = renderFirstName;
+  }
+
+  public boolean isRenderLastName() {
+    return renderLastName;
+  }
+
+  public void setRenderLastName(final boolean renderLastName) {
+    this.renderLastName = renderLastName;
+  }
+
+  public boolean isRenderDayOfBirth() {
+    return renderDayOfBirth;
+  }
+
+  public void setRenderDayOfBirth(final boolean renderDayOfBirth) {
+    this.renderDayOfBirth = renderDayOfBirth;
+  }
+
+  public Part getPart() {
+    return part;
+  }
+
+  public void setPart(final Part part) {
+    this.part = part;
+  }
+
+  public String getSearchCriterion() {
+    return searchCriterion;
+  }
+
+  public void setSearchCriterion(final String searchCriterion) {
+    this.searchCriterion = searchCriterion;
+  }
+
+  public String popupFileUpload() {
+    setRenderFileUploadPopup(true);
+    return null;
+  }
+
+  public String languageChanged() {
+    countries.init(language);
+    initLanguages();
+/*
+    // reinit date converter
+    FacesContext facesContext = FacesContext.getCurrentInstance();
+    UIViewRoot viewRoot = facesContext.getViewRoot();
+    EditableValueHolder component = (EditableValueHolder)
+        viewRoot.findComponent(":page:dayOfBirth");
+    if (component != null) {
+      DateTimeConverter converter = (DateTimeConverter) component.getConverter();
+      converter.setPattern(MessageUtils.getLocalizedString(facesContext, "editor_date_pattern"));
+    }
+*/
+    return null;
+  }
+
+  private void initLanguages() {
+    languages.clear();
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final Application application = facesContext.getApplication();
+    final Iterator supportedLocales = application.getSupportedLocales();
+    while (supportedLocales.hasNext()) {
+      final Locale locale = (Locale) supportedLocales.next();
+      final SelectItem item = new SelectItem(locale, locale.getDisplayName(language), null, FLAGS.get(locale));
+      languages.add(item);
+    }
+    Collections.sort(languages, new SelectItemComparator());
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Countries.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Countries.java
new file mode 100644
index 0000000..c52d6d7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/Countries.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.model.SelectItem;
+import javax.inject.Named;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Locale;
+
+@Named
+@SessionScoped
+public class Countries extends ArrayList<SelectItem> {
+
+  public void init(final Locale language) {
+    clear();
+    final Locale[] availableLocales = Locale.getAvailableLocales();
+    for (final Locale locale : availableLocales) {
+      final String displayCountry = locale.getDisplayCountry(language);
+      if (displayCountry != null && displayCountry.length() > 0) {
+        add(new SelectItem(locale, displayCountry));
+      }
+    }
+    Collections.sort(this, new SelectItemComparator());
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/EmailAddressConverter.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/EmailAddressConverter.java
new file mode 100644
index 0000000..75135e1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/EmailAddressConverter.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.myfaces.tobago.example.addressbook.EmailAddress;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.convert.FacesConverter;
+
+@FacesConverter(forClass = EmailAddress.class)
+public class EmailAddressConverter implements Converter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(EmailAddressConverter.class);
+
+  @Override
+  public Object getAsObject(
+      final FacesContext facesContext, final UIComponent component, final String reference) {
+    if (reference == null || reference.length() == 0) {
+      return null;
+    }
+    final String[] parts = reference.split("@");
+    if (parts == null || parts.length != 2) {
+      throw new ConverterException(MessageUtils.createErrorMessage("converterEmailParts", facesContext));
+    }
+    return new EmailAddress(reference);
+  }
+
+  @Override
+  public String getAsString(final FacesContext facesContext, final UIComponent component, final Object object) {
+    return object.toString();
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/EmailAddressValidator.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/EmailAddressValidator.java
new file mode 100644
index 0000000..6087562
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/EmailAddressValidator.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import org.apache.myfaces.tobago.example.addressbook.EmailAddress;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.FacesValidator;
+import javax.faces.validator.Validator;
+import javax.faces.validator.ValidatorException;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@FacesValidator("EmailAddressValidator")
+public class EmailAddressValidator implements Validator {
+
+  private static final String EMAIL_ATOM = "[^()<>@,;:\\\\.\\[\\]\\\"]";
+  private static final String LOCAL_PART_SPEC = EMAIL_ATOM + "+(\\." + EMAIL_ATOM + "+)*";
+  private static final String DOMAIN_SPEC = EMAIL_ATOM + "+(\\." + EMAIL_ATOM + "+)+";
+
+  private static final Pattern LOCAL_PART_PATTERN = Pattern.compile(LOCAL_PART_SPEC);
+  private static final Pattern DOMAIN_PATTERN = Pattern.compile(DOMAIN_SPEC);
+
+  @Override
+  public void validate(final FacesContext facesContext, final UIComponent uiComponent, final Object value)
+      throws ValidatorException {
+
+    if (value == null) {
+      return;
+    }
+
+    final EmailAddress emailAddress = (EmailAddress) value;
+
+    Matcher matcher = LOCAL_PART_PATTERN.matcher(emailAddress.getLocalPart());
+    if (!matcher.matches()) {
+      throw new ValidatorException(MessageUtils.createErrorMessage(
+          "validatorEmailLocalPart", facesContext));
+    }
+
+    matcher = DOMAIN_PATTERN.matcher(emailAddress.getDomain());
+    if (!matcher.matches()) {
+      throw new ValidatorException(MessageUtils.createErrorMessage(
+          "validatorEmailDomain", facesContext));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/LocaleConverter.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/LocaleConverter.java
new file mode 100644
index 0000000..74a22bb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/LocaleConverter.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.convert.FacesConverter;
+import java.util.Locale;
+
+@FacesConverter(forClass = Locale.class)
+public class LocaleConverter implements Converter {
+
+  @Override
+  public Object getAsObject(
+      final FacesContext facesContext, final UIComponent component, final String value) {
+    final Locale locale = createLocale(value);
+    if (locale == null) {
+      throw new ConverterException(MessageUtils.getLocalizedString(
+          facesContext, "converterLocaleParserError", value));
+    }
+    return locale;
+  }
+
+  @Override
+  public String getAsString(
+      final FacesContext facesContext, final UIComponent component, final Object value) {
+    return value == null ? null : value.toString();
+  }
+
+  public static Locale createLocale(final String value) {
+    final String[] strings = value.split("_");
+    switch (strings.length) {
+      case 1:
+        return new Locale(strings[0]);
+      case 2:
+        return new Locale(strings[0], strings[1]);
+      case 3:
+        return new Locale(strings[0], strings[1], strings[2]);
+      default:
+        return null;
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/MessageUtils.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/MessageUtils.java
new file mode 100644
index 0000000..92478d3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/MessageUtils.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import java.text.MessageFormat;
+import java.util.ResourceBundle;
+
+public class MessageUtils {
+
+  private MessageUtils() {
+  }
+
+  public static String getLocalizedString(final FacesContext facesContext, final String key) {
+    final ResourceBundle bundle = ResourceBundle.getBundle(
+        facesContext.getApplication().getMessageBundle(),
+        facesContext.getViewRoot().getLocale());
+    return bundle.getString(key);
+  }
+
+  public static String getLocalizedString(final FacesContext facesContext,
+      final String key, final String value) {
+    return MessageFormat.format(
+        getLocalizedString(facesContext, key), value);
+  }
+
+  public static String getLocalizedString(final FacesContext facesContext,
+      final String key, final int value) {
+    return MessageFormat.format(
+        getLocalizedString(facesContext, key), value);
+  }
+
+  public static FacesMessage createErrorMessage(
+      final String key, final FacesContext facesContext) {
+    final FacesMessage message = new FacesMessage();
+    // TODO _detail
+    message.setDetail(getLocalizedString(facesContext, key));
+    message.setSummary(getLocalizedString(facesContext, key));
+    message.setSeverity(FacesMessage.SEVERITY_ERROR);
+    return message;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/PictureServlet.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/PictureServlet.java
new file mode 100644
index 0000000..ed3981f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/PictureServlet.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.myfaces.tobago.example.addressbook.Address;
+import org.apache.myfaces.tobago.example.addressbook.Picture;
+import org.apache.myfaces.tobago.servlet.NonFacesRequestServlet;
+import org.apache.myfaces.tobago.util.VariableResolverUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.servlet.annotation.WebServlet;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+
+@WebServlet("/faces/picture")
+public class PictureServlet extends NonFacesRequestServlet {
+  private static final Logger LOG = LoggerFactory.getLogger(PictureServlet.class);
+
+  @Override
+  public String invokeApplication(final FacesContext facesContext) {
+    final Controller controller = (Controller) VariableResolverUtils.resolveVariable(facesContext, "controller");
+    final Address address = controller.getCurrentAddress();
+    if (address.hasPicture()) {
+      final Picture picture = address.getPicture();
+      final byte[] content = picture.getContent();
+      final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
+      if (content != null && content.length > 0) {
+        response.setContentType(picture.getContentType());
+        final ByteArrayInputStream inputStream = new ByteArrayInputStream(content);
+        try {
+          IOUtils.copy(inputStream, response.getOutputStream());
+        } catch (final IOException e) {
+          LOG.error("", e);
+        } finally{
+          IOUtils.closeQuietly(inputStream);
+        }
+      }
+      facesContext.responseComplete();
+    }
+    return null;  
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/RandomAddressGenerator.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/RandomAddressGenerator.java
new file mode 100644
index 0000000..d2fe33b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/RandomAddressGenerator.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.apache.myfaces.tobago.example.addressbook.Address;
+
+import java.util.Calendar;
+import java.util.Locale;
+
+/**
+ * Tries to generate random, uncontroversial addresses.
+ *
+ * @see <a href="http://en.wikipedia.org/wiki/John_Doe">Wikipedia: John Doe</a>
+ * @see <a href="http://en.wikipedia.org/wiki/Alice_and_Bob">Wikipedia: Alice and Bob</a>
+ * @see <a href="http://en.wikipedia.org/wiki/Placeholder_name">Wikipedia: Placeholder name</a>
+ */
+public class RandomAddressGenerator {
+
+  private static final String[] MALE_FIRST_NAMES = {
+      "Alan", "Arvid", "Bernd", "Detlef", "Frank", "Hans",
+      "John", "Max", "Michael", "Otto", "Tom", "Udo"};
+  private static final String[] FEMALE_FIRST_NAMES = {
+      "Anna", "Erika", "Jane", "Kate", "Kerstin", "Maria",
+      "Polly", "Sabine", "Shirley", "Tanya", "Tracy", "Yvonne"};
+
+  private static final String[] GERMAN_LAST_NAMES = {
+      "Müller", "Meier", "Mustermann", "Schmidt", "Schulze"};
+  private static final String[] ENGLISH_LAST_NAMES = {
+      "Doe", "Jones", "Miller", "Public", "Raymond", "Smithee"
+  };
+
+  public static Address generateAddress() {
+    return generateAddress(RandomUtils.nextBoolean(), RandomUtils.nextBoolean());
+  }
+
+  public static Address generateAddress(final boolean female, final boolean german) {
+    final Address address = new Address();
+    address.setFirstName(female ? randomString(FEMALE_FIRST_NAMES) : randomString(MALE_FIRST_NAMES));
+    if (german) {
+      address.setLastName(randomString(GERMAN_LAST_NAMES));
+      address.setCountry(Locale.GERMANY);
+    } else {
+      address.setLastName(randomString(ENGLISH_LAST_NAMES));
+      address.setCountry(RandomUtils.nextBoolean() ? Locale.US : Locale.UK);
+    }
+    final Calendar calendar = Calendar.getInstance();
+    calendar.set(1920, 0, 1);
+    calendar.add(Calendar.DAY_OF_YEAR, RandomUtils.nextInt(70 * 365));
+    address.setDayOfBirth(calendar.getTime());
+    return address;
+  }
+
+  static String randomString(final String[] array) {
+    return array[RandomUtils.nextInt(array.length)];
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/SelectItemComparator.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/SelectItemComparator.java
new file mode 100644
index 0000000..e23f30e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/SelectItemComparator.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import javax.faces.model.SelectItem;
+import java.io.Serializable;
+import java.util.Comparator;
+
+public class SelectItemComparator implements Comparator<SelectItem>, Serializable {
+  private static final long serialVersionUID = -1581955960510873296L;
+
+  @Override
+  public int compare(final SelectItem s1, final SelectItem s2) {
+    return s1.getLabel().compareTo(s2.getLabel());
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/StartupPhaseListener.java b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/StartupPhaseListener.java
new file mode 100644
index 0000000..cda4309
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/java/org/apache/myfaces/tobago/example/addressbook/web/StartupPhaseListener.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.addressbook.web;
+
+import org.apache.commons.lang.BooleanUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.FacesException;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import java.io.IOException;
+
+public class StartupPhaseListener implements PhaseListener {
+
+  private static final Logger LOG = LoggerFactory.getLogger(StartupPhaseListener.class);
+  public static final String LOGGED_IN = StartupPhaseListener.class.getName() + ".LOGGED_IN";
+  public static final String PRINCIPAL = StartupPhaseListener.class.getName() + ".PRINCIPAL";
+
+  @Override
+  public PhaseId getPhaseId() {
+    return PhaseId.RESTORE_VIEW;
+  }
+
+  @Override
+  public void beforePhase(final PhaseEvent event) {
+
+    final FacesContext facesContext = event.getFacesContext();
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    final String pathInfo = externalContext.getRequestPathInfo();
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("externalContext.getRequestPathInfo() = '" + pathInfo + "'");
+    }
+
+    if (pathInfo.equals("/error.xhtml") || // todo: not nice, find a declarative way.
+        pathInfo.startsWith("/auth/")) {
+      final Object session = externalContext.getSession(false);
+      if (session != null) {
+        externalContext.getSessionMap().put(LOGGED_IN, Boolean.FALSE);
+      }
+      return; // nothing to do.
+    }
+
+    final Boolean loggedIn = (Boolean) // todo: not nice to get this object directly from the session
+        externalContext.getSessionMap().get(LOGGED_IN);
+
+    if (!BooleanUtils.toBoolean(loggedIn)) {
+      try {
+        externalContext.getSessionMap().put(LOGGED_IN, Boolean.TRUE);
+        final String forward = externalContext.getRequestContextPath() + "/faces/addressbook/start.xhtml";
+        externalContext.redirect(externalContext.encodeResourceURL(forward));
+      } catch (final Exception e) {
+        LOG.error("", e);
+        final String forward = externalContext.getRequestContextPath() + "/error.xhtml";
+        try {
+          externalContext.redirect(externalContext.encodeResourceURL(forward));
+        } catch (final IOException e2) {
+          LOG.error("", e2);
+          throw new FacesException("Can't redirect to errorpage '" + forward + "'");
+        }
+      }
+    }
+  }
+
+  @Override
+  public void afterPhase(final PhaseEvent event) {
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/resources/META-INF/persistence.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/resources/META-INF/persistence.xml
new file mode 100644
index 0000000..95c1648
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/resources/META-INF/persistence.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<persistence xmlns="http://java.sun.com/xml/ns/persistence"
+             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+             xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
+
+    <persistence-unit name="addressBook" transaction-type="RESOURCE_LOCAL">
+
+      <jta-data-source>addressBookDataSource</jta-data-source>
+<!--
+      <non-jta-data-source>addressBookDatabaseNotManaged</non-jta-data-source>
+-->
+
+      <class>org.apache.myfaces.tobago.example.addressbook.Address</class>
+      <class>org.apache.myfaces.tobago.example.addressbook.Picture</class>
+
+      <properties>
+        <property name="openjpa.RuntimeClassOptimization" value="false"/>
+        <property name="openjpa.Log" value="DefaultLevel=TRACE"/> 
+      </properties>
+
+    </persistence-unit>
+</persistence>
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/resources/logback.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/resources/logback.xml
new file mode 100644
index 0000000..65f657f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- Schema is NOT official from logback -->
+<configuration
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="https://raw.github.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{ISO8601} [%-16.16thread] %-5level %-50.50logger{50}:%-20.20method:%-4.4line [%mdc] %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <logger name="org.apache.myfaces.tobago.example.addressbook" level="debug"/>
+
+  <root level="info">
+    <appender-ref ref="console"/>
+  </root>
+</configuration>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/META-INF/context.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..e624eee
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+    This file is for Apache Tomcat.
+    The property "antiResourceLocking" is needed for proper redeploy under Windows.
+-->
+
+<Context antiResourceLocking="true" >
+</Context>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/beans.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..a956a0d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- marker file for CDI -->
+
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+
+  <interceptors>
+  </interceptors>
+
+  <decorators>
+  </decorators>
+
+  <alternatives>
+    <class>org.apache.myfaces.tobago.example.addressbook.InMemoryAddressDao</class>
+  </alternatives>
+
+</beans>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/faces-config.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..395aa51
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<faces-config
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
+    version="2.0">
+
+  <application>
+     <locale-config>
+      <default-locale>en_US</default-locale>
+      <supported-locale>de</supported-locale>
+      <supported-locale>en_GB</supported-locale>
+      <supported-locale>en_US</supported-locale>
+    </locale-config>
+    <action-listener>org.apache.myfaces.tobago.util.DebugActionListener</action-listener>
+    <navigation-handler>org.apache.myfaces.tobago.util.DebugNavigationHandler</navigation-handler>
+    <message-bundle>error.messages</message-bundle>
+  </application>
+
+  <lifecycle>
+<!--
+    <phase-listener>org.apache.myfaces.tobago.util.DebugPhaseListener</phase-listener>
+-->
+    <phase-listener>org.apache.myfaces.tobago.example.addressbook.web.StartupPhaseListener</phase-listener>
+  </lifecycle>
+
+  <navigation-rule>
+    <navigation-case>
+      <from-outcome>editor</from-outcome>
+      <to-view-id>/addressbook/editor.xhtml</to-view-id>
+    </navigation-case>
+    <navigation-case>
+      <from-outcome>list</from-outcome>
+      <to-view-id>/addressbook/list.xhtml</to-view-id>
+    </navigation-case>
+    <navigation-case>
+      <from-outcome>admin</from-outcome>
+      <to-view-id>/addressbook/admin/admin.xhtml</to-view-id>
+    </navigation-case>
+  </navigation-rule>
+
+  <navigation-rule>
+    <navigation-case>
+      <from-outcome>logout</from-outcome>
+      <to-view-id>/auth/logout.xhtml</to-view-id>
+    </navigation-case>
+  </navigation-rule>
+
+</faces-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/ibm-web-bnd.xmi b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/ibm-web-bnd.xmi
new file mode 100644
index 0000000..8eaf68b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/ibm-web-bnd.xmi
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<webappbnd:WebAppBinding xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:webappbnd="webappbnd.xmi" xmlns:webapplication="webapplication.xmi" xmi:id="WebAppBinding_1" virtualHostName="default_host">
+
+  <!-- Needed for WebSphere 8.5 auto deployment
+       Must match the display-name from the web.xml
+  -->
+
+  <webapp href="WEB-INF/web.xml#A simple address-book demo (Java EE 6)"/>
+</webappbnd:WebAppBinding>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/ibm-web-ext.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/ibm-web-ext.xml
new file mode 100644
index 0000000..441ef31
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/ibm-web-ext.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<web-ext
+      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+      xmlns="http://websphere.ibm.com/xml/ns/javaee"
+      xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-ext_1_0.xsd"
+      version="1.0">
+
+  <!-- Needed for WebSphere 8.5 auto deployment -->
+
+   <context-root uri="/tobago-example-addressbook-cdi"/>
+
+</web-ext>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/tobago-config.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/tobago-config.xml
new file mode 100644
index 0000000..3734af0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/tobago-config.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+
+  <theme-config>
+    <default-theme>standard</default-theme>
+    <supported-theme>speyside</supported-theme>
+    <supported-theme>scarborough</supported-theme>
+    <supported-theme>richmond</supported-theme>
+    <supported-theme>charlotteville</supported-theme>
+  </theme-config>
+
+  <resource-dir>addressbook-resource</resource-dir>
+  <renderers>
+    <renderer>
+      <name>Progress</name>
+      <supported-markup>
+        <markup>ok</markup>
+        <markup>warn</markup>
+        <markup>error</markup>
+      </supported-markup>
+    </renderer>
+  </renderers>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/web.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..fd98217
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<web-app
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+    version="3.0">
+
+  <display-name>A simple address-book demo (Java EE 6)</display-name>
+
+  <context-param>
+    <param-name>javax.faces.PROJECT_STAGE</param-name>
+    <param-value>Development</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
+    <param-value>org.apache.myfaces.tobago.facelets.MetaInfResourcesClasspathResourceResolver</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
+    <param-value>.xhtml</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <filter>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <filter-class>org.apache.myfaces.tobago.internal.webapp.LoggingMdcFilter</filter-class>
+  </filter>
+  <filter-mapping>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+  <!-- servlet -->
+
+  <servlet>
+    <servlet-name>FacesServlet</servlet-name>
+    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+    <load-on-startup>1</load-on-startup>
+    <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+    <multipart-config/>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>FacesServlet</servlet-name>
+    <url-pattern>/faces/*</url-pattern>
+  </servlet-mapping>
+
+  <!-- XXX websphere-provided -->
+  <listener>
+    <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class>
+  </listener>
+
+  <!-- Welcome File List -->
+
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+
+  <security-constraint>
+    <display-name>Security Constraint</display-name>
+    <web-resource-collection>
+      <web-resource-name>Application Area</web-resource-name>
+      <url-pattern>/faces/addressbook/*</url-pattern>
+      <url-pattern>/addressbook/*</url-pattern>
+    </web-resource-collection>
+    <auth-constraint>
+      <role-name>*</role-name>
+    </auth-constraint>
+  </security-constraint>
+
+  <login-config>
+    <auth-method>FORM</auth-method>
+    <realm-name>addressbook-realm</realm-name>
+    <form-login-config>
+      <form-login-page>/faces/auth/login.xhtml</form-login-page>
+      <form-error-page>/faces/auth/error.xhtml</form-error-page>
+    </form-login-config>
+  </login-config>
+
+  <security-role>
+    <role-name>addressbook-user</role-name>
+  </security-role>
+
+  <env-entry>
+    <description>
+      Set the size limit for uploaded files. Default value is 1 MB.
+        Format: 10 = 10 bytes
+        10k = 10 KB
+        10m = 10 MB
+        1g = 1 GB
+    </description>
+    <env-entry-name>uploadMaxFileSize</env-entry-name>
+    <env-entry-type>java.lang.String</env-entry-type>
+    <env-entry-value>1m</env-entry-value>
+  </env-entry>
+
+  <session-config>
+    <cookie-config>
+      <http-only>true</http-only>
+    </cookie-config>
+  </session-config>
+
+</web-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/scarborough/standard/style/tobago.css b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/scarborough/standard/style/tobago.css
new file mode 100644
index 0000000..5ba25f3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/scarborough/standard/style/tobago.css
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.tobago-progress-value-markup-ok {
+  background: green;
+}
+
+.tobago-progress-value-markup-warn {
+  background: yellow;
+}
+
+.tobago-progress-value-markup-error {
+  background: red;
+}
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/speyside/standard/style/tobago.css b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/speyside/standard/style/tobago.css
new file mode 100644
index 0000000..5ba25f3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/speyside/standard/style/tobago.css
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.tobago-progress-value-markup-ok {
+  background: green;
+}
+
+.tobago-progress-value-markup-warn {
+  background: yellow;
+}
+
+.tobago-progress-value-markup-error {
+  background: red;
+}
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-de.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-de.png
new file mode 100644
index 0000000..ac4a977
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-de.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-gb.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-gb.png
new file mode 100644
index 0000000..5c4d301
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-gb.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-us.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-us.png
new file mode 100644
index 0000000..10f451f
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/addressbook/icon/flag-us.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/empty-portrait.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/empty-portrait.png
new file mode 100644
index 0000000..7c12d59
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/empty-portrait.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/empty-portrait_de.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/empty-portrait_de.png
new file mode 100644
index 0000000..0614c22
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/empty-portrait_de.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/16x16/categories/preferences-systemDisabled.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/16x16/categories/preferences-systemDisabled.png
new file mode 100644
index 0000000..5711eda
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/16x16/categories/preferences-systemDisabled.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/32x32/categories/preferences-systemDisabled.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/32x32/categories/preferences-systemDisabled.png
new file mode 100644
index 0000000..11f0e6a
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/32x32/categories/preferences-systemDisabled.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/32x32/mimetypes/x-office-address-bookDisabled.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/32x32/mimetypes/x-office-address-bookDisabled.png
new file mode 100644
index 0000000..4c4a70f
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/32x32/mimetypes/x-office-address-bookDisabled.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/address-book-splash-screen.png b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/address-book-splash-screen.png
new file mode 100644
index 0000000..f12463f
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/image/org/tango-project/tango-icon-theme/address-book-splash-screen.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/addressbook.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/addressbook.properties.xml
new file mode 100644
index 0000000..dc3647d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/addressbook.properties.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+
+<properties>
+<!-- Editor -->
+  <entry key="editorTitle">Addressbook Editor</entry>
+  <entry key="editorBoxTitle">Address Editor</entry>
+  <entry key="editorTabPersonal">Personal</entry>
+  <entry key="editorTabBusiness">Business</entry>
+  <entry key="editorTabMisc">Misc</entry>
+  <entry key="editorFirstName">First Name:</entry>
+  <entry key="editorLastName">Last Name:</entry>
+  <entry key="editorStreet">Street / No.:</entry>
+  <entry key="editorCity">ZIP / City:</entry>
+  <entry key="editorCountry">Country:</entry>
+  <entry key="editorPhone">Phone:</entry>
+  <entry key="editorMobile">Mobile:</entry>
+  <entry key="editorFax">Fax:</entry>
+  <entry key="editorEmail">eMail:</entry>
+  <entry key="editorIcq">ICQ:</entry>
+  <entry key="editorHomepage">Homepage:</entry>
+  <entry key="editorBirthday">Day of Birth:</entry>
+  <entry key="editorJobCompany">Company:</entry>
+  <entry key="editorJobTitle">Job Title:</entry>
+  <entry key="editorNote">Note:</entry>
+  <entry key="editorStore">_Store</entry>
+  <entry key="editorCancel">_Cancel</entry>
+
+<!-- List -->
+
+  <entry key="listPageTitle">List of addresses</entry>
+  <entry key="listBoxTitle">Address Editor</entry>
+  <entry key="listNew">New</entry>
+  <entry key="listEdit">Edit</entry>
+  <entry key="listDelete">Delete</entry>
+  <entry key="listFirstName">First Name</entry>
+  <entry key="listLastName">Last Name</entry>
+  <entry key="listBirthday">Day of Birth</entry>
+  <entry key="listDeleteConfirmation">Do you want to delete the selected addresses?</entry>
+</properties>
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/addressbook_de.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/addressbook_de.properties.xml
new file mode 100644
index 0000000..b69bdfd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/addressbook_de.properties.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+
+
+<properties>
+
+  <!-- Editor -->
+
+  <entry key="editorTitle">Adressbuch Editor</entry>
+  <entry key="editorBoxTitle">Adressbuch Editor</entry>
+  <entry key="editorTabPersonal">Persönlich</entry>
+  <entry key="editorTabBusiness">Geschäftlich</entry>
+  <entry key="editorTabMisc">Weiteres</entry>  
+  <entry key="editorFirstName">Vorname:</entry>
+  <entry key="editorLastName">Nachname:</entry>
+  <entry key="editorStreet">Straße / Nr.:</entry>
+  <entry key="editorCity">PLZ / Ort:</entry>
+  <entry key="editorCountry">Land:</entry>
+  <entry key="editorPhone">Telefon:</entry>
+  <entry key="editorMobile">Handy:</entry>
+  <entry key="editorFax">Fax:</entry>
+  <entry key="editorEmail">eMail:</entry>
+  <entry key="editorBirthday">Geburtsdatum:</entry>
+  <entry key="editorJobCompany">Firma:</entry>
+  <entry key="editorJobTitle">Job Titel:</entry>
+  <entry key="editorNote">Bemerkungen:</entry>
+  <entry key="editorStore">_Speichern</entry>
+  <entry key="editorCancel">_Abbrechen</entry>
+
+  <!-- List -->
+
+  <entry key="listPageTitle">Adressen</entry>
+  <entry key="listBoxTitle">Adressen Editor</entry>
+  <entry key="listNew">Neu</entry>
+  <entry key="listEdit">Ändern</entry>
+  <entry key="listDelete">Löschen</entry>
+  <entry key="listFirstName">Vorname</entry>
+  <entry key="listLastName">Nachname</entry>
+  <entry key="listBirthday">Geburtsdatum</entry>
+  <entry key="listDeleteConfirmation">Wollen Sie diesen Eintrag wirklich
+    löschen?</entry>
+</properties>
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/error/messages.properties b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/error/messages.properties
new file mode 100644
index 0000000..e3edf62
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/error/messages.properties
@@ -0,0 +1,27 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# converter
+converterEmailParts=Exactly two eMail parts expected
+converterLocaleParserError=Cannot parse "{0}" to a locale.
+
+# validator
+validatorEmailLocalPart=eMail address is not valid: local part
+validatorEmailDomain=eMail address is not valid: domain
+validatorPhone=Invalid phone number
+
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource.properties b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource.properties
new file mode 100644
index 0000000..299e71c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource.properties
@@ -0,0 +1,98 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# editor
+admin=Admin
+editorPageTitle=Addressbook Editor
+editorTitle=Address Editor
+editorBoxTitle=Address Editor
+editorFirstName=First Name
+editorLastName=Last Name
+editorStreet=Street / No
+editorCity=ZIP / City
+editorCountry=Country
+editorPhone=Phone
+editorMobile=Mobile
+editorFax=Fax
+editorEmail=eMail
+editorIcq=ICQ
+editorHomepage=Homepage
+editorBirthday=Day of Birth
+editorDatePattern=MM/dd/yyyy
+editorJobCompany=Company
+editorJobTitle=Job Title
+editorJobPhone=Phone, business
+editorJobEmail=eMail, business
+editorJobHomepage=Company Homepage
+editorNote=Note
+editorStore=Store
+editorCancel=Cancel
+editorTabPersonal=Personal
+editorTabBusiness=Business
+editorTabMisc=Misc
+
+# address list
+listFilter=Filter
+listSearch=Search
+listPageTitle=List Of Addresses
+listBoxTitle=Addresses
+listNew=New
+listEdit=Edit
+listDelete=Delete
+listFirstName=First Name
+listLastName=Last Name
+listDeleteConfirmation=Do you want to delete the selected addresses?
+listFooter={0,choice,0#No addresses|1#1 Address|1<{0,number,integer} Addresses}
+listSelectColumns=Select Columns
+
+# footer
+footerLanguage=Language
+footerTheme=Theme
+footerFlag=Flag
+footerFlagIcon=image/addressbook/icon/flag-us.png
+
+# menu
+menuFile=_File
+menuFileNew=_New
+menuSettings=_Settings
+menuSettingsLanguage=_Language
+menuSettingsTheme=_Theme
+menuSettingsMode=Simple _Mode
+menuHelp=_Help
+menuHelpAbout=_About
+
+# toolbar
+toolbarAddressList=Address List
+toolbarAbout=About
+aboutMessage=Addressbook Demo
+
+# error
+errorPageTitle=Error
+errorTitle=Error
+errorPageOk=OK
+
+# login
+loginIntro=Use one of the following users to login.
+loginUser=Username
+loginPassword=Password
+loginLogin=Login
+loginError=The user name or password is wrong.
+
+loginLogoutTitle=Logout
+loginLogoutBox=Logout
+loginLogoutText=You are logged out.
+loginHomeButton=Login
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_de.properties b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_de.properties
new file mode 100644
index 0000000..966f2e9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_de.properties
@@ -0,0 +1,84 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# editor
+editorPageTitle=Adressbucheditor
+editorTitle=Adresseneditor
+editorFirstName=Vorname
+editorLastName=Nachname
+editorStreet=Stra\u00dfe / Nr.
+editorCity=PLZ / Stadt
+editorCountry=Land
+editorPhone=Telefon
+editorMobile=Handy
+editorFax=Fax
+editorEmail=eMail
+editorIcq=ICQ
+editorHomepage=Homepage
+editorBirthday=Geburtstag
+editorDatePattern=dd.MM.yyyy
+editorJobCompany=Firma
+editorJobTitle=Beruf
+editorJobPhone=Telefon, gesch\u00e4ftlich
+editorJobEmail=eMail, gesch\u00e4ftlich
+editorJobHomepage=Firmen-Homepage
+editorNote=Notiz
+editorStore=Speichern
+editorCancel=Abbrechen
+editorTabPersonal=Pers\u00f6nlich
+editorTabBusiness=Gesch\u00e4ftlich
+
+# address list
+listFilter=Filter
+listSearch=Suchen
+listPageTitle=Adressen
+listBoxTitle=Adressen
+listNew=Neu
+listEdit=Editieren
+listDelete=L\u00f6schen
+listFirstName=Vorname
+listLastName=Nachname
+listDeleteConfirmation=Wollen Sie diesen Eintrag wirklich l\u00f6schen?
+listFooter={0,choice,0#Keine Adresse|1#1 Adresse|1<{0,number,integer} Adressen}
+listSelectColumns=Spalten Selektieren
+
+# footer
+footerLanguage=Sprache
+footerTheme=Design
+footerFlag=Flagge
+footerFlagIcon=image/addressbook/icon/flag-de.png
+
+
+# menu
+menuFile=_Datei
+menuFileNew=_Neue Adresse
+menuSettings=_Einstellungen
+menuSettingsLanguage=_Sprache
+menuSettingsTheme=Des_ign
+menuSettingsMode=Einfacher Modus
+menuHelp=_Hilfe
+menuHelpAbout=_\u00dcber
+
+# toolbar
+toolbarAddressList=Adressliste
+toolbarAbout=\u00dcber
+aboutMessage=Adressbuch Demo
+
+# error
+errorPageTitle=Fehler
+errorTitle=Fehler
+errorPageOk=OK
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_en_GB.properties b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_en_GB.properties
new file mode 100644
index 0000000..ce11860
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_en_GB.properties
@@ -0,0 +1,22 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# editor
+editorDatePattern=dd/MM/yyyy
+
+# footer
+footerFlagIcon=image/addressbook/icon/flag-gb.png
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_en_US.properties b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_en_US.properties
new file mode 100644
index 0000000..e5f405e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook-resource/html/standard/standard/property/resource_en_US.properties
@@ -0,0 +1,17 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/admin/admin.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/admin/admin.xhtml
new file mode 100644
index 0000000..a94ef9c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/admin/admin.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/addressbook/layout/basic.xhtml"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="Administration"/>
+
+    <tc:tabGroup switchType="reloadPage">
+      <tc:tab label="Memory">
+        <ui:include src="memory.xhtml"/>
+      </tc:tab>
+      <tc:tab label="Logging (removed)" disabled="true">
+      </tc:tab>
+    </tc:tabGroup>
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto"/>
+      </f:facet>
+      <tc:panel/>
+      <tc:button label="Back" action="list"/>
+    </tc:panel>
+  </ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/admin/memory.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/admin/memory.xhtml
new file mode 100644
index 0000000..8d4c967
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/admin/memory.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:subview id="memory"
+           xmlns:tc="http://myfaces.apache.org/tobago/component"
+           xmlns:f="http://java.sun.com/jsf/core">
+  <tc:panel>
+
+    <f:facet name="layout">
+      <tc:gridLayout margin="10px" rows="auto;auto;auto" columns="300px"/>
+    </f:facet>
+    <f:facet name="reload">
+      <tc:reload frequency="5000" update="#{admin.updateMemory}"/>
+    </f:facet>
+
+    <tc:label value="Memory:"/>
+
+    <tc:progress value="#{admin.memory}" markup="#{admin.state}"/>
+
+    <tc:label value="Current: #{admin.memory.value} kB Max: #{admin.memory.maximum} kB"/>
+
+  </tc:panel>
+</f:subview>
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/editor.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/editor.xhtml
new file mode 100644
index 0000000..fb7e464
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/editor.xhtml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/addressbook/layout/basic.xhtml"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{bundle.editorTitle}"/>
+
+  <tc:flowLayout>
+
+    <tc:script file="bootstrap-datepicker.js"/>
+    <tc:style file="datepicker.css"/>
+
+
+    <tc:buttons> <!-- XXX merge with the other toolbar on list.xhtml !!! -->
+      <tc:button tip="Logout" action="#{controller.logout}" immediate="true"
+                 image="fa-question">
+        <tc:style customClass="btn-danger"/>
+      </tc:button>
+    </tc:buttons>
+
+    <tc:box label="#{bundle.editorBoxTitle}">
+      <tc:flexLayout rows="auto;*;auto">
+
+        <tc:messages/>
+
+        <!--
+              <tc:tabGroup switchType="reloadTab" immediate="true">
+                <tc:tab label="#{bundle.editorTabPersonal}">
+        -->
+        <ui:include src="tab/personal.xhtml"/>
+        <!--
+                </tc:tab>
+
+                <tc:tab label="#{bundle.editorTabBusiness}" rendered="#{!controller.simple}">
+                  <ui:include src="tab/business.xhtml"/>
+                </tc:tab>
+
+                <tc:tab label="#{bundle.editorTabMisc}" rendered="#{!controller.simple}">
+                  <ui:include src="tab/misc.xhtml"/>
+                </tc:tab>
+              </tc:tabGroup>
+        -->
+
+        <tc:panel>
+          <f:facet name="layout">
+            <tc:segmentLayout medium="2;10"/>
+          </f:facet>
+
+          <tc:out/>
+
+          <tc:flowLayout>
+            <tc:button action="#{controller.store}" label="#{bundle.editorStore}" defaultCommand="true"/>
+            <tc:button action="#{controller.cancel}" immediate="true" label="#{bundle.editorCancel}"/>
+          </tc:flowLayout>
+        </tc:panel>
+
+      </tc:flexLayout>
+    </tc:box>
+  </tc:flowLayout>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/layout/basic.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/layout/basic.xhtml
new file mode 100644
index 0000000..66c3722
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/layout/basic.xhtml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <f:view locale="#{controller.language}">
+
+    <tc:page applicationIcon="icon/favicon.ico" label="${title}" id="page">
+
+      <tc:flowLayout>
+
+        <tc:script file="auth/logout.js"/>
+
+<!--
+              <f:facet name="menuBar">
+                <tc:menuBar>
+                  <tc:form>
+                    <tc:menu label="#{bundle.menuFile}">
+                      <tc:menuCommand label="#{bundle.menuFileNew}" action="#{controller.createAddress}" immediate="true"
+                                   image="fa-question"/>
+                      <tc:menuCommand label="Add Dummy Addresses" action="#{controller.addDummyAddresses}" immediate="true"/>
+                      <tc:menuSeparator/>
+                      <tc:menuCommand label="#{bundle.admin}" action="#{admin.admin}"
+                                   image="fa-question"/>
+                      <tc:menuSeparator/>
+                      <tc:menuCommand label="Logout" action="#{controller.logout}"
+                                   image="fa-question"/>
+                    </tc:menu>
+
+                    <tc:menu label="#{bundle.menuSettings}">
+                      <tc:menu label="#{bundle.menuSettingsLanguage}">
+                        <tx:menuRadio action="#{controller.languageChanged}"
+                                      value="#{controller.language}">
+                          <f:selectItems value="#{controller.languages}"/>
+                        </tx:menuRadio>
+                      </tc:menu>
+                      <tc:menu label="#{bundle.menuSettingsTheme}">
+                        <tx:menuRadio action="#{controller.themeChanged}"
+                                      value="#{controller.theme}">
+                          <f:selectItems value="#{controller.themeItems}"/>
+                        </tx:menuRadio>
+                      </tc:menu>
+                      <tx:menuCheckbox label="#{bundle.menuSettingsMode}" value="#{controller.simple}"/>
+                    </tc:menu>
+
+                    <tc:menu label="#{bundle.menuHelp}">
+                      <tc:menuCommand label="#{bundle.menuHelpAbout}"
+                                   image="fa-question">
+                        <tc:popupReference for=":page:about"/>
+                      </tc:menuCommand>
+                    </tc:menu>
+                  </tc:form>
+                </tc:menuBar>
+              </f:facet>
+-->
+
+        <tc:flowLayout>
+          <ui:insert/>
+        </tc:flowLayout>
+
+        <tc:separator/>
+
+        <tc:panel>
+          <f:facet name="layout">
+            <tc:segmentLayout medium="2;3;1;2;3;1"/>
+          </f:facet>
+          <!--
+                <tc:form>
+          -->
+          <tc:selectOneChoice label="#{bundle.footerLanguage}"
+                              value="#{controller.language}">
+            <f:selectItems value="#{controller.languages}"/>
+            <tc:event action="#{controller.languageChangedList}"/>
+          </tc:selectOneChoice>
+          <!--
+                </tc:form>
+          -->
+          <tc:image alt="#{bundle.footerFlag}" width="16" height="11"
+                    value="#{bundle.footerFlagIcon}"/>
+          <!--
+                <tc:form>
+          -->
+          <tc:selectOneChoice label="#{bundle.footerTheme}" value="#{controller.theme}">
+            <f:selectItems value="#{controller.themeItems}"/>
+            <tc:event action="#{controller.themeChanged}"/>
+          </tc:selectOneChoice>
+          <!--
+                </tc:form>
+          -->
+          <tc:button label="Dummy" action="#{controller.addDummyAddresses}" immediate="true"
+                     image="fa-user"/>
+
+        </tc:panel>
+
+        <f:facet name="popup">
+          <tc:popup id="about" width="400" height="220" left="200" top="200">
+            <tc:box label="About">
+              <f:facet name="layout">
+                <tc:gridLayout rows="150px;*;auto" columns="150px;*"/>
+              </f:facet>
+
+              <tc:image value="fa-user">
+                <tc:style width="150" height="150"/>
+              </tc:image>
+              <tc:panel>
+                <f:facet name="layout">
+                  <tc:gridLayout rows="auto;auto;auto;*"/>
+                </f:facet>
+
+                <tc:out markup="strong" value="Addressbook Demo"/>
+                <tc:panel/>
+                <tc:out value="Version #{controller.version}"/>
+                <tc:panel/>
+              </tc:panel>
+
+              <tc:panel>
+                <tc:span column="2"/>
+              </tc:panel>
+
+              <tc:panel>
+                <tc:span column="2"/>
+                <tc:panel>
+                  <f:facet name="layout">
+                    <tc:gridLayout columns="*;auto"/>
+                  </f:facet>
+                  <tc:panel/>
+                  <tc:button label="OK">
+                    <tc:attribute name="popupClose" value="immediate"/>
+                  </tc:button>
+                </tc:panel>
+              </tc:panel>
+            </tc:box>
+          </tc:popup>
+        </f:facet>
+
+      </tc:flowLayout>
+    </tc:page>
+  </f:view>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/list.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/list.xhtml
new file mode 100644
index 0000000..fcb8c46
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/list.xhtml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/addressbook/layout/basic.xhtml"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{bundle.listPageTitle}"/>
+
+  <tc:flowLayout>
+    <tc:buttons>
+<!--
+      <tc:button label="#{bundle.toolbarAddressList}" action="#{controller.search}" immediate="true"
+                 image="fa-question"
+                 disabled="#{facesContext.viewRoot.viewId == '/addressbook/list.xhtml'}"/>
+-->
+      <tc:button label="#{bundle.listNew}" action="#{controller.createAddress}"
+                 image="fa-question"/>
+      <tc:button label="#{bundle.listEdit}" action="#{controller.editAddress}"
+                         image="fa-question"/>
+      <tc:button label="#{bundle.listDelete}" action="#{controller.deleteAddresses}"
+                         image="fa-question">
+        <f:facet name="confirmation">
+          <tc:out value="#{bundle.listDeleteConfirmation}"/>
+        </f:facet>
+        <tc:style customClass="btn-danger"/>
+      </tc:button>
+      <tc:button label="#{bundle.toolbarAbout}"
+                 image="fa-question">
+        <tc:popupReference for=":page:about"/>
+      </tc:button>
+      <tc:button label="#{bundle.admin}" action="#{admin.admin}"
+                 image="fa-question"/>
+
+      <tc:in value="#{controller.searchCriterion}" placeholder="#{bundle.listFilter}" tip="#{bundle.listFilter}"/>
+      <tc:button action="#{controller.search}" label="#{bundle.listSearch}"
+                 defaultCommand="true"/>
+      <tc:button tip="Logout" action="#{controller.logout}" immediate="true"
+                      image="fa-question"/>
+      <tc:style customClass="btn-danger"/>
+    </tc:buttons>
+
+    <tc:box label="#{bundle.listBoxTitle}">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;1*"/>
+      </f:facet>
+<!--
+      <f:facet name="toolBar">
+        <tc:toolBar>
+          <tc:toolBarCommand label="#{bundle.listNew}" action="#{controller.createAddress}"
+                             image="fa-question"/>
+          <tc:toolBarCommand label="#{bundle.listEdit}" action="#{controller.editAddress}"
+                             image="fa-question"/>
+          <tc:toolBarCommand label="#{bundle.listDelete}" action="#{controller.deleteAddresses}"
+                             image="fa-question">
+            <f:facet name="confirmation">
+              <tc:out value="#{bundle.listDeleteConfirmation}"/>
+            </f:facet>
+          </tc:toolBarCommand>
+          <tc:toolBarCommand label="Select Columns" action="#{controller.selectColumns}"
+                             image="fa-question">
+            <f:facet name="popup">
+              <tc:popup width="300" height="200" left="200" top="200"
+                        rendered="#{controller.renderPopup}" id="popup">
+                <tc:box label="Select Columns">
+                  <f:facet name="layout">
+                    <tc:gridLayout rows="auto;auto;auto;1*;auto" margin="10"/>
+                  </f:facet>
+
+                  <tc:selectBooleanCheckbox label="First Name" value="#{controller.renderFirstName}"/>
+                  <tc:selectBooleanCheckbox label="Last Name" value="#{controller.renderLastName}"/>
+                  <tc:selectBooleanCheckbox label="Birthday" value="#{controller.renderDayOfBirth}"/>
+                  <tc:panel/>
+                  <tc:panel>
+                    <f:facet name="layout">
+                      <tc:gridLayout columns="1*;100px;100px"/>
+                    </f:facet>
+                    <tc:panel/>
+                    <tc:button action="#{controller.cancelPopup}" label="OK" defaultCommand="true"/>
+                    <tc:button action="#{controller.cancelPopup}" label="Cancel" immediate="true"/>
+                  </tc:panel>
+                </tc:box>
+              </tc:popup>
+            </f:facet>
+          </tc:toolBarCommand>
+        </tc:toolBar>
+      </f:facet>
+-->
+
+      <tc:messages/>
+
+      <tc:sheet columns="1*;1*;1*" value="#{controller.currentAddressList}"
+                var="address" state="#{controller.selectedAddresses}"
+                sortActionListener="#{controller.sheetSorter}" rows="15"
+                showRowRange="left" showPageRange="right" showDirectLinks="center">
+        <tc:row>
+          <tc:event event="dblclick" action="#{controller.editAddress}"/>
+        </tc:row>
+        <tc:column id="firstName" label="#{bundle.listFirstName}" sortable="true"
+                   rendered="#{controller.renderFirstName}">
+          <tc:out value="#{address.firstName}"/>
+        </tc:column>
+        <tc:column id="lastName" label="#{bundle.listLastName}" sortable="true"
+                   rendered="#{controller.renderLastName}">
+          <tc:out value="#{address.lastName}"/>
+        </tc:column>
+        <tc:column id="dayOfBirth" label="Birthday" sortable="true"
+                   rendered="#{controller.renderDayOfBirth}">
+          <tc:out value="#{address.dayOfBirth}">
+            <f:convertDateTime pattern="#{bundle.editorDatePattern}"/>
+          </tc:out>
+        </tc:column>
+      </tc:sheet>
+
+    </tc:box>
+  </tc:flowLayout>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/start.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/start.xhtml
new file mode 100644
index 0000000..426f855
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/start.xhtml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page label="#{bundle.editorTitle}">
+    <f:facet name="load">
+      <tc:link action="list"/>
+    </f:facet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout margin="10px" rows="*;auto;*" columns="*;400px;*"/>
+      </f:facet>
+
+      <tc:panel>
+        <tc:span column="3"/>
+      </tc:panel>
+
+      <tc:panel/>
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout rows="150px" columns="150px;250px"/>
+        </f:facet>
+
+        <tc:image value="fa-address-book">
+          <tc:style width="150" height="150"/>
+        </tc:image>
+        <tc:panel>
+          <f:facet name="layout">
+            <tc:gridLayout rows="auto;auto;auto;*"/>
+          </f:facet>
+
+          <tc:out value="Addressbook Demo"/>
+          <tc:panel/>
+          <tc:out value="Initializing ..."/>
+          <tc:panel/>
+
+        </tc:panel>
+
+      </tc:panel>
+      <tc:panel/>
+
+      <tc:panel>
+        <tc:span column="3"/>
+      </tc:panel>
+
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/business.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/business.xhtml
new file mode 100644
index 0000000..8a2491b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/business.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto;auto;1*"/>
+    </f:facet>
+    <tc:in value="#{controller.currentAddress.company}"
+           label="#{bundle.editorJobCompany}"/>
+
+    <tc:in value="#{controller.currentAddress.jobTitle}"
+           label="#{bundle.editorJobTitle}"/>
+
+    <tc:in value="#{controller.currentAddress.jobPhone}"
+           label="#{bundle.editorPhone}"
+           validator="#{controller.validatePhoneNumber}"/>
+
+    <tc:in value="#{controller.currentAddress.jobEmail}"
+           label="#{bundle.editorEmail}">
+      <f:validator validatorId="EmailAddressValidator"/>
+    </tc:in>
+
+    <tc:in value="#{controller.currentAddress.jobHomePage}"
+           label="#{bundle.editorHomepage}"/>
+
+    <tc:panel/>
+
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/misc.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/misc.xhtml
new file mode 100644
index 0000000..c76bde3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/misc.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout rows="1*"/>
+    </f:facet>
+
+    <tc:textarea value="#{controller.currentAddress.note}"
+                 label="#{bundle.editorNote}"/>
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/personal.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/personal.xhtml
new file mode 100644
index 0000000..5dfcce0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/addressbook/tab/personal.xhtml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <tc:flowLayout>
+    <tc:panel>
+        <f:facet name="layout">
+          <tc:segmentLayout medium="2;10"/>
+        </f:facet>
+
+        <tc:in value="#{controller.currentAddress.firstName}"
+               label="#{bundle.editorFirstName}" required="true">
+          <f:validateLength minimum="2" maximum="20"/>
+        </tc:in>
+
+        <tc:in label="#{bundle.editorLastName}"
+               value="#{controller.currentAddress.lastName}" required="true"/>
+    </tc:panel>
+
+        <tc:panel>
+          <f:facet name="layout">
+            <tc:segmentLayout medium="2;8;2"/>
+          </f:facet>
+          <tc:in value="#{controller.currentAddress.street}"
+                 label="#{bundle.editorStreet}"/>
+          <tc:in value="#{controller.currentAddress.houseNumber}"/>
+        </tc:panel>
+
+        <tc:panel>
+          <f:facet name="layout">
+            <tc:segmentLayout medium="2;3;7"/>
+          </f:facet>
+          <tc:in value="#{controller.currentAddress.zipCode}"
+                 label="#{bundle.editorCity}"/>
+          <tc:in value="#{controller.currentAddress.city}"/>
+        </tc:panel>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:segmentLayout medium="2;10"/>
+      </f:facet>
+
+        <tc:selectOneChoice
+            value="#{controller.currentAddress.country}"
+            label="#{bundle.editorCountry}">
+          <f:selectItems value="#{countries}"/>
+        </tc:selectOneChoice>
+<!--
+      <tc:flexLayout rows="160px" columns="120px" rendered="#{!controller.simple}">
+        <tc:form>
+          <tc:button
+              image="#{controller.currentAddressPictureUrl}"
+              action="#{controller.popupFileUpload}">
+            <f:facet name="popup">
+              <tc:popup width="300" height="170" left="200"
+                        top="200" rendered="#{controller.renderFileUploadPopup}"
+                        id="popup-fileUpload">
+                <tc:box label="FileUpload">
+                  <tc:flexLayout rows="auto;1*;auto" margin="10"/>
+                    <tc:file value="#{controller.uploadedFile}" required="true">
+                      <tc:validateFileItem contentType="image/*"/>
+                    </tc:file>
+                    <tc:messages/>
+                    <tc:flexLayout columns="1*;100px;100px"/>
+                      <tc:panel/>
+                      <tc:button action="#{controller.okFileUpload}" label="OK"/>
+                      <tc:button action="#{controller.cancelFileUpload}" label="Cancel" immediate="true"/>
+                    </tc:flexLayout>
+                  </tc:flexLayout>
+                </tc:box>
+              </tc:popup>
+            </f:facet>
+          </tc:button>
+        </tc:form>
+      </tc:flexLayout>
+-->
+
+      <tc:in value="#{controller.currentAddress.phone}"
+             label="#{bundle.editorPhone}"
+             validator="#{controller.validatePhoneNumber}"/>
+
+      <tc:in value="#{controller.currentAddress.mobile}"
+             label="#{bundle.editorMobile}"
+             validator="#{controller.validatePhoneNumber}"/>
+
+      <tc:in value="#{controller.currentAddress.fax}"
+             label="#{bundle.editorFax}"
+             validator="#{controller.validatePhoneNumber}"/>
+
+      <tc:in value="#{controller.currentAddress.email}"
+             label="#{bundle.editorEmail}">
+        <f:validator validatorId="EmailAddressValidator"/>
+      </tc:in>
+
+      <tc:in value="#{controller.currentAddress.icq}"
+             label="#{bundle.editorIcq}">
+        <f:validateLongRange minimum="0"/>
+      </tc:in>
+      <tc:in value="#{controller.currentAddress.homePage}"
+             label="#{bundle.editorHomepage}"/>
+
+      <tc:date id="dayOfBirth" value="#{controller.currentAddress.dayOfBirth}"
+               label="#{bundle.editorBirthday}">
+        <f:convertDateTime pattern="#{bundle.editorDatePattern}"/>
+      </tc:date>
+    </tc:panel>
+  </tc:flowLayout>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/error.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/error.xhtml
new file mode 100644
index 0000000..cd17fcf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/error.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:f="http://java.sun.com/jsf/core"
+        locale="#{controller.language}">
+
+  <tc:page label="Login Error">
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;auto;*" columns="*;400px;*"/>
+    </f:facet>
+
+    <tc:panel>
+      <tc:span column="3"/>
+    </tc:panel>
+
+    <tc:panel/>
+    <tc:box label="Login Error">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto"/>
+      </f:facet>
+
+      <tc:out value="#{bundle.loginError}"/>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;auto"/>
+        </f:facet>
+
+        <tc:panel/>
+        <tc:button link="/index.html" label="Home"/>
+      </tc:panel>
+
+    </tc:box>
+    <tc:panel/>
+
+    <tc:panel>
+      <tc:span column="3"/>
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/login.js b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/login.js
new file mode 100644
index 0000000..551e321
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/login.js
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Addressbook = {};
+
+/**
+ * Copies the values from the data-login attribute to the username/password fields.
+ */
+Addressbook.prepareQuickLinks = function() {
+  jQuery("a[data-login]").click(function() {
+    var link = jQuery(this);
+    var login = link.data("login");
+    jQuery(Tobago.Utils.escapeClientId("page:j_username")).val(login.username);
+    jQuery(Tobago.Utils.escapeClientId("page:j_password")).val(login.password).focus();
+    return false;
+  });
+};
+
+/**
+ * This code is needed to "repair" the submit parameter names and url to use
+ * the names that a required for servlet authentication.
+ */
+Addressbook.prepareLoginForm = function() {
+  jQuery(Tobago.Utils.escapeClientId("page:j_username")).attr("name", "j_username");
+  jQuery(Tobago.Utils.escapeClientId("page:j_password")).attr("name", "j_password");
+  jQuery(Tobago.Utils.escapeClientId("page::form")).attr("action", jQuery("[data-tobago-context-path]").data("tobago-context-path") + "/j_security_check");
+};
+
+Tobago.registerListener(Addressbook.prepareQuickLinks, Tobago.Phase.DOCUMENT_READY);
+
+Tobago.registerListener(Addressbook.prepareLoginForm, Tobago.Phase.BEFORE_SUBMIT);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/login.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/login.xhtml
new file mode 100644
index 0000000..683a585
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/login.xhtml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:f="http://java.sun.com/jsf/core"
+        locale="#{controller.language}">
+
+  <tc:page id="page" label="Login">
+    <tc:flexLayout rows="*;auto;*">
+
+      <tc:out/>
+
+      <tc:panel>
+        <tc:flexLayout columns="*;auto;*">
+
+          <tc:out/>
+
+          <tc:box label="Login">
+            <f:facet name="layout">
+              <tc:gridLayout rows="auto;auto;auto;auto"/>
+            </f:facet>
+
+            <tc:flowLayout>
+              <tc:out value="#{bundle.loginIntro}"/>
+              (
+              <tc:link label="guest/guest" image="fa-user"
+                       omit="true">
+                <tc:dataAttribute name="login" value='{"username": "guest", "password": "guest"}'/>
+              </tc:link>
+              or
+              <tc:link label="admin/admin" image="fa-user"
+                       omit="true">
+                <tc:dataAttribute name="login" value='{"username": "admin", "password": "admin"}'/>
+              </tc:link>
+              )
+            </tc:flowLayout>
+
+            <tc:in id="j_username" label="#{bundle.loginUser}"/>
+            <tc:in id="j_password" password="true" label="#{bundle.loginPassword}"/>
+
+            <tc:panel>
+              <f:facet name="layout">
+                <tc:gridLayout columns="*;auto"/>
+              </f:facet>
+
+              <tc:panel/>
+              <tc:button label="#{bundle.loginLogin}" defaultCommand="true"/>
+            </tc:panel>
+          </tc:box>
+
+          <tc:out/>
+
+        </tc:flexLayout>
+      </tc:panel>
+
+      <tc:out/>
+
+    </tc:flexLayout>
+
+    <tc:script file="auth/login.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/logout.js b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/logout.js
new file mode 100644
index 0000000..9780212
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/logout.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+AddressbookLogout = {};
+
+/**
+ * Immediately log out. Is used by onexit the the browser window is closed.
+ */
+AddressbookLogout.logout = function() {
+  jQuery.ajax({url:"/KillSession",async:false});
+};
+
+Tobago.registerListener(AddressbookLogout.logout, Tobago.Phase.BEFORE_EXIT);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/logout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/logout.xhtml
new file mode 100644
index 0000000..705d5d7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/auth/logout.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:f="http://java.sun.com/jsf/core"
+        locale="#{controller.language}">
+
+  <tc:page label="#{bundle.loginLogoutTitle}">
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;auto;*" columns="*;400px;*"/>
+    </f:facet>
+
+    <tc:panel>
+      <tc:span column="3"/>
+    </tc:panel>
+
+    <tc:panel/>
+    <tc:box label="#{bundle.loginLogoutBox}">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto"/>
+      </f:facet>
+
+      <tc:out value="#{bundle.loginLogoutText}"/>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;auto"/>
+        </f:facet>
+        <tc:panel/>
+        <tc:button link="/index.html" label="#{bundle.loginHomeButton}"/>
+      </tc:panel>
+    </tc:box>
+    <tc:panel/>
+
+    <tc:panel>
+      <tc:span column="3"/>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/error.xhtml b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/error.xhtml
new file mode 100644
index 0000000..8a8fe0d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/error.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page label="Error">
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;auto;*" columns="*;400px;*"/>
+    </f:facet>
+
+    <tc:panel>
+      <tc:span column="3"/>
+    </tc:panel>
+
+    <tc:panel/>
+    <tc:box label="Error">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto"/>
+      </f:facet>
+
+      <tc:out value="Sorry, an error has occured."/>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;auto"/>
+        </f:facet>
+
+        <tc:panel/>
+        <tc:button link="/index.html" label="Home"/>
+      </tc:panel>
+
+    </tc:box>
+    <tc:panel/>
+
+    <tc:panel>
+      <tc:span column="3"/>
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/icon/favicon.ico b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/icon/favicon.ico
new file mode 100644
index 0000000..43dfec0
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/icon/favicon.ico differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/index.html b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/index.html
new file mode 100644
index 0000000..07beb6d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/main/webapp/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html>
+<head>
+  <meta http-equiv="Cache-Control" content="no-cache">
+  <meta http-equiv="Refresh" content="0; URL=faces/addressbook/start.xhtml">
+</head>
+<body>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/test/resources/realm.properties b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/test/resources/realm.properties
new file mode 100644
index 0000000..805d448
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-addressbook/src/test/resources/realm.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# username: password [,rolename ...]
+guest: guest,addressbook-user
+admin: admin,addressbook-user,admin
diff --git a/tobago-3.0.x/tobago-example/tobago-example-assembly/pom.xml b/tobago-3.0.x/tobago-example/tobago-example-assembly/pom.xml
new file mode 100644
index 0000000..6875482
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-assembly/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <artifactId>tobago-example-assembly</artifactId>
+  <packaging>pom</packaging>
+  <name>Tobago Example Assembly</name>
+  <description>Helps to build the Tobago releases,</description>
+
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-example</artifactId>
+    <version>3.0.3</version>
+  </parent>
+
+  <profiles>
+    <profile>
+      <id>generate-assembly</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <executions>
+
+              <execution>
+                <id>copy-example</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy</goal>
+                </goals>
+                <configuration>
+                  <artifactItems>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-example-demo</artifactId>
+                      <version>${project.version}</version>
+                      <type>war</type>
+                    </artifactItem>
+                    <artifactItem>
+                      <groupId>${project.groupId}</groupId>
+                      <artifactId>tobago-example-blank</artifactId>
+                      <version>${project.version}</version>
+                      <type>war</type>
+                    </artifactItem>
+                  </artifactItems>
+                  <outputDirectory>${project.build.directory}/webapp</outputDirectory>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+          <plugin>
+            <artifactId>maven-assembly-plugin</artifactId>
+            <executions>
+              <execution>
+                <phase>package</phase>
+                <id>generate-assembly</id>
+                <goals>
+                  <goal>single</goal>
+                </goals>
+                <configuration>
+                  <descriptor>src/main/assembly/dep.xml</descriptor>
+                  <finalName>myfaces-tobago-${project.version}</finalName>
+                  <outputDirectory>target/assembly/out</outputDirectory>
+                  <workDirectory>target/assembly/work</workDirectory>
+                  <tarLongFileMode>gnu</tarLongFileMode>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+ </project>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/assembly/dep.xml b/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/assembly/dep.xml
new file mode 100644
index 0000000..4b9b329
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/assembly/dep.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<assembly>
+  <id>example</id>
+  <formats>
+    <format>tar.gz</format>
+    <format>zip</format>
+  </formats>
+  <fileSets>
+    <fileSet>
+    	<directory>src/main/resources</directory>
+    	<outputDirectory></outputDirectory>
+      <includes>
+        <include>README*</include>
+        <include>LICENSE*</include>
+        <include>NOTICE*</include>
+      </includes>
+    </fileSet>
+    <fileSet>
+      <directory>target/webapp</directory>
+      <outputDirectory></outputDirectory>
+      <includes>
+        <include>*.war</include>
+      </includes>
+    </fileSet>
+  </fileSets>
+</assembly>
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/resources/LICENSE.txt b/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/resources/LICENSE.txt
new file mode 100644
index 0000000..306307e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/resources/LICENSE.txt
@@ -0,0 +1,255 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ For jQuery:
+
+ Copyright (c) 2010 John Resig, http://jquery.com/
+
+ Permission is hereby granted, free of charge, to any person obtaining
+ a copy of this software and associated documentation files (the
+ "Software"), to deal in the Software without restriction, including
+ without limitation the rights to use, copy, modify, merge, publish,
+ distribute, sublicense, and/or sell copies of the Software, and to
+ permit persons to whom the Software is furnished to do so, subject to
+ the following conditions:
+
+ The above copyright notice and this permission notice shall be
+ included in all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+ For SLF4J:
+
+ Copyright (c) 2004-2008 QOS.ch
+ All rights reserved.
+
+ Permission is hereby granted, free  of charge, to any person obtaining
+ a  copy  of this  software  and  associated  documentation files  (the
+ "Software"), to  deal in  the Software without  restriction, including
+ without limitation  the rights to  use, copy, modify,  merge, publish,
+ distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ permit persons to whom the Software  is furnished to do so, subject to
+ the following conditions:
+
+ The  above  copyright  notice  and  this permission  notice  shall  be
+ included in all copies or substantial portions of the Software.
+
+ THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+
+
+
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/resources/NOTICE.txt b/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/resources/NOTICE.txt
new file mode 100644
index 0000000..0f93d52
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-assembly/src/main/resources/NOTICE.txt
@@ -0,0 +1,16 @@
+Apache Tobago
+Copyright 2005-2017 The Apache Software Foundation
+
+This product includes software developed by
+The Apache Software Foundation (http://www.apache.org/).
+
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
+
+This product includes software developed by
+The jQuery Foundation (http://jquery.org/ and http://jqueryui.com/)
+
+This product includes software developed by
+QOS.ch (slf4j) (http://QOS.ch/)
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/pom.xml b/tobago-3.0.x/tobago-example/tobago-example-blank/pom.xml
new file mode 100644
index 0000000..140acde
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-example</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-example-blank</artifactId>
+  <packaging>war</packaging>
+  <name>Tobago Example Blank</name>
+  <description>A minimal Tobago application.</description>
+
+  <build>
+    <finalName>tobago-example-blank</finalName>
+  </build>
+
+  <dependencies>
+    <!-- needed for mvn jetty:run -->
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/java/org/apache/myfaces/tobago/example/blank/Hello.java b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/java/org/apache/myfaces/tobago/example/blank/Hello.java
new file mode 100644
index 0000000..375365d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/java/org/apache/myfaces/tobago/example/blank/Hello.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.blank;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.bean.ManagedBean;
+import javax.faces.bean.RequestScoped;
+
+@ManagedBean
+@RequestScoped
+public class Hello {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Hello.class);
+
+  private String name;
+
+  public String sayHello() {
+    if (LOG.isInfoEnabled()) {
+      LOG.info("Action was called, name is '{}'", name);
+    }
+    return null;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/resources/logback.xml b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/resources/logback.xml
new file mode 100644
index 0000000..14f544f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/resources/logback.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- Schema is NOT official from logback -->
+<configuration
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="https://raw.github.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{ISO8601} [%-16.16thread] %-5level %-50.50logger{50}:%-20.20method:%-4.4line [%mdc] %msg%n</pattern>
+    </encoder>
+  </appender>
+
+<!--
+  <logger name="org.apache.myfaces.tobago" level="debug"/>
+-->
+
+  <root level="info">
+    <appender-ref ref="console"/>
+  </root>
+</configuration>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/META-INF/context.xml b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..e624eee
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+    This file is for Apache Tomcat.
+    The property "antiResourceLocking" is needed for proper redeploy under Windows.
+-->
+
+<Context antiResourceLocking="true" >
+</Context>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/faces-config.xml b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..bbec4c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<faces-config
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
+    version="2.0">
+
+  <application>
+    <locale-config>
+      <default-locale>en</default-locale>
+      <supported-locale>de</supported-locale>
+      <supported-locale>de_DE</supported-locale>
+      <supported-locale>de_AT</supported-locale>
+      <supported-locale>de_CH</supported-locale>
+    </locale-config>
+  </application>
+
+</faces-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/tobago-config.xml b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/tobago-config.xml
new file mode 100644
index 0000000..1545ecb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/tobago-config.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+    version="3.0">
+
+  <theme-config>
+    <default-theme>standard</default-theme>
+  </theme-config>
+
+<!--
+  <create-session-secret>false</create-session-secret>
+  <check-session-secret>false</check-session-secret>
+-->
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/web.xml b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..ab1a385
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<web-app
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+    version="3.0">
+
+  <display-name>Blank Tobago Application</display-name>
+
+<!--
+  <context-param>
+    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
+    <param-value>client</param-value>
+  </context-param>
+-->
+
+  <!-- servlet -->
+  <servlet>
+    <servlet-name>FacesServlet</servlet-name>
+    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+    <load-on-startup>3</load-on-startup>
+    <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+    <multipart-config>
+      <max-request-size>20000000</max-request-size>
+      <max-file-size>1000000</max-file-size>
+    </multipart-config>
+  </servlet>
+
+  <!-- servlet-mapping -->
+
+  <servlet-mapping>
+    <servlet-name>FacesServlet</servlet-name>
+    <url-pattern>/faces/*</url-pattern>
+  </servlet-mapping>
+
+  <!-- The Usual Welcome File List -->
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+
+  <session-config>
+    <cookie-config>
+      <http-only>true</http-only>
+    </cookie-config>
+  </session-config>
+
+  <filter>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <filter-class>org.apache.myfaces.tobago.internal.webapp.LoggingMdcFilter</filter-class>
+  </filter>
+  <filter-mapping>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+</web-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/helloWorld.xhtml b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/helloWorld.xhtml
new file mode 100644
index 0000000..1d69ea8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/helloWorld.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component">
+
+  <tc:page>
+
+    <tc:in label="Name" value="#{hello.name}">
+      <f:facet name="after">
+        <tc:button label="Submit" defaultCommand="true" action="#{hello.sayHello}"/>
+      </f:facet>
+    </tc:in>
+
+    <tc:out value="Hello, #{hello.name}!" rendered="#{not empty hello.name}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/index.html b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/index.html
new file mode 100644
index 0000000..e80661c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-blank/src/main/webapp/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<html>
+<head>
+  <meta http-equiv="Cache-Control" content="no-cache">
+  <meta http-equiv="Refresh" content="0; URL=faces/helloWorld.xhtml">
+</head>
+<body>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/pom.xml b/tobago-3.0.x/tobago-example/tobago-example-data/pom.xml
new file mode 100644
index 0000000..7ff77ec
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-example</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-example-data</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Example Data</name>
+  <description>Data to use in the other examples.</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CantorInterval.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CantorInterval.java
new file mode 100644
index 0000000..0fbc114
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CantorInterval.java
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.TreeNode;
+import java.math.BigInteger;
+import java.util.Enumeration;
+
+/**
+ * Builds a tree with the iterations of the <a href="http://en.wikipedia.org/wiki/Cantor_set">Cantor set</a>.
+ * The tree is infinitive, so it will be created on the fly.
+ */
+public class CantorInterval extends DefaultMutableTreeNode {
+
+  private Fraction begin;
+  private Fraction end;
+  private boolean initialized;
+
+  public CantorInterval() {
+    begin = Fraction.ZERO;
+    end = Fraction.ONE;
+  }
+
+  private CantorInterval(final Fraction begin, final Fraction end) {
+    this.begin = begin;
+    this.end = end;
+  }
+
+  // init must be lazy, because the tree is infinite
+  private void init() {
+    if (!initialized) {
+      initialized = true; // add() will call getChildCount()!
+      final Fraction subtract = end.subtract(begin);
+      final Fraction multiply = subtract.multiply(Fraction.ONE_THIRD);
+      final Fraction oneThird = multiply.add(begin);
+      add(new CantorInterval(begin, oneThird));
+
+      final Fraction twoThird = end.subtract(begin).multiply(Fraction.TWO_THIRDS).add(begin);
+      add(new CantorInterval(twoThird, end));
+    }
+  }
+
+  @Override
+  public int getChildCount() {
+    init();
+    return super.getChildCount();
+  }
+
+  @Override
+  public TreeNode getChildAt(final int i) {
+    init();
+    return super.getChildAt(i);
+  }
+
+  @Override
+  public Enumeration children() {
+    init();
+    return super.children();
+  }
+
+  public String getLabel() {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append(begin);
+    builder.append(", ");
+    builder.append(end);
+    builder.append("]");
+    return builder.toString();
+  }
+
+  public String toString() {
+    return getLabel();
+  }
+
+  public static final class Fraction {
+
+    private final BigInteger numerator;
+    private final BigInteger denominator;
+
+    public static final Fraction ZERO = new Fraction(0);
+    public static final Fraction ONE = new Fraction(1);
+    public static final BigInteger THREE = BigInteger.valueOf(3);
+    public static final Fraction ONE_THIRD = new Fraction(BigInteger.ONE, THREE);
+    public static final Fraction TWO_THIRDS = new Fraction(BigInteger.valueOf(2), THREE);
+
+    private Fraction(final long i) {
+      numerator = BigInteger.valueOf(i);
+      denominator = BigInteger.ONE;
+    }
+
+    private Fraction(BigInteger numerator, BigInteger denominator) {
+      while (numerator.remainder(THREE).equals(BigInteger.ZERO)
+          && denominator.remainder(THREE).equals(BigInteger.ZERO)) {
+        numerator = numerator.divide(THREE);
+        denominator = denominator.divide(THREE);
+      }
+      this.numerator = numerator;
+      this.denominator = denominator;
+    }
+
+    public Fraction add(final Fraction value) {
+      return new Fraction(
+          numerator.multiply(value.denominator).add(denominator.multiply(value.numerator)),
+          denominator.multiply(value.denominator));
+    }
+
+    public Fraction subtract(final Fraction value) {
+      return new Fraction(
+          numerator.multiply(value.denominator).subtract(denominator.multiply(value.numerator)),
+          denominator.multiply(value.denominator));
+    }
+
+    public Fraction multiply(final Fraction value) {
+      return new Fraction(
+          numerator.multiply(value.numerator),
+          denominator.multiply(value.denominator));
+    }
+
+    @Override
+    public String toString() {
+      final StringBuilder builder = new StringBuilder();
+      if (denominator.equals(BigInteger.ONE)) {
+        builder.append(numerator);
+      } else {
+        builder.append(numerator);
+        builder.append("/");
+        builder.append(denominator);
+      }
+      return builder.toString();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CategoryTree.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CategoryTree.java
new file mode 100644
index 0000000..bb88e18
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CategoryTree.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import org.apache.myfaces.tobago.context.Markup;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class CategoryTree {
+
+  public static DefaultMutableTreeNode createSample() {
+    final DefaultMutableTreeNode tree = createNode("Root Node", "root");
+    tree.insert(createNode("Sports", "sports"), 0);
+    tree.insert(createNode("Movies", "movies"), 1);
+    final DefaultMutableTreeNode music = createNode("Music", "music");
+    tree.insert(music, 2);
+    music.insert(createNode("Classic", "classic"), 0);
+    music.insert(createNode("Pop", "pop"), 1);
+    music.insert(createNode("World", "world"), 2);
+    tree.insert(createNode("Games", "games"), 3);
+    final DefaultMutableTreeNode science = createNode("Science", "science");
+    science.insert(createNode("Geography", "geography"), 0);
+    science.insert(createNode("Mathematics", "math"), 0);
+    final DefaultMutableTreeNode astro = createNode("Astronomy", "astro");
+    astro.insert(createNode("Education", "edu"), 0);
+    astro.insert(createNode("Pictures", "pic"), 0);
+    science.insert(astro, 2);
+    tree.insert(science, 4);
+    return tree;
+  }
+
+  public static DefaultMutableTreeNode createNode(final String name, final String id) {
+    return new DefaultMutableTreeNode(new Node(name, id));
+  }
+
+  public static DefaultMutableTreeNode createSample2() {
+    final DefaultMutableTreeNode tree = new DefaultMutableTreeNode(new Node("1 Category"));
+    tree.add(new DefaultMutableTreeNode(new Node("1.1 Sports")));
+    tree.add(new DefaultMutableTreeNode(new Node("1.2 Movies")));
+    final DefaultMutableTreeNode temp = new DefaultMutableTreeNode(new Node("1.3 Science"));
+    tree.add(temp);
+    final DefaultMutableTreeNode music = new DefaultMutableTreeNode(new Node("1.4 Music"));
+    tree.add(music);
+    tree.add(new DefaultMutableTreeNode(new Node("1.5 Games")));
+    temp.add(new DefaultMutableTreeNode(new Node("1.3.1 Geography (strong markup)", Markup.STRONG)));
+    temp.add(new DefaultMutableTreeNode(new Node("1.3.2 Mathematics (strong markup)", Markup.STRONG)));
+    final DefaultMutableTreeNode temp2 = new DefaultMutableTreeNode(new Node("1.3.3 Pictures"));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.1 Education")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.2 Family")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.3 Comercial")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.4 Summer (disabled)", true)));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.5 Winter (disabled)", true)));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.6 Red")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.7 Black")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.8 White")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.9 Good")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.10 Evil")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.11 Flower")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.12 Animal")));
+    temp2.add(new DefaultMutableTreeNode(new Node("1.3.3.13 Personal")));
+    temp.add(temp2);
+    final DefaultMutableTreeNode bulk = new DefaultMutableTreeNode(new Node("1.6 Bulk"));
+    for (int i = 0; i < 5; i++) {
+      bulk.add(new DefaultMutableTreeNode(new Node("1.6." + (i + 1) + " Some Node")));
+    }
+    tree.add(bulk);
+
+    return tree;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CommandNode.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CommandNode.java
new file mode 100644
index 0000000..60f7158
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CommandNode.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class CommandNode extends DefaultMutableTreeNode {
+
+  private String name;
+  private String action;
+  private String url;
+
+  public CommandNode(String name) {
+    this.name = name;
+  }
+
+  public CommandNode(String name, String action, String url) {
+    this.name = name;
+    this.action = action;
+    this.url = url;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getAction() {
+    return action;
+  }
+
+  public String getUrl() {
+    return url;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CommandNodeFactory.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CommandNodeFactory.java
new file mode 100644
index 0000000..b3fdfb3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/CommandNodeFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+public class CommandNodeFactory {
+
+  public static CommandNode createSample() {
+    final CommandNode root = new CommandNode("Commands");
+
+    final CommandNode actions = new CommandNode("Actions");
+    actions.add(new CommandNode("Action 1", "ActionOne", null));
+    actions.add(new CommandNode("Action 2", "ActionTwo", null));
+    root.add(actions);
+
+    final CommandNode links = new CommandNode("Links");
+    links.add(new CommandNode("Apache", null, "https://www.apache.org/"));
+    links.add(new CommandNode("MyFaces", null, "https://myfaces.apache.org/"));
+    links.add(new CommandNode("Tobago", null, "https://myfaces.apache.org/tobago/"));
+    root.add(links);
+
+    return root;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Element.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Element.java
new file mode 100644
index 0000000..3aeef40
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Element.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+public class Element {
+
+  private String name;
+  private double ratio;
+
+  public Element(final String name, final double ratio) {
+    this.name = name;
+    this.ratio = ratio;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public double getRatio() {
+    return ratio;
+  }
+
+  public void setRatio(final double ratio) {
+    this.ratio = ratio;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/LocaleEntry.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/LocaleEntry.java
new file mode 100644
index 0000000..f0ab100
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/LocaleEntry.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Locale;
+
+public class LocaleEntry {
+
+  private Locale locale;
+  private Locale displayLocale;
+  private String country;
+  private String language;
+
+  public LocaleEntry(final Locale locale, final Locale displayLocale) {
+    this.locale = locale;
+    this.displayLocale = displayLocale;
+    country = locale.getDisplayCountry(displayLocale);
+    language = locale.getDisplayLanguage(displayLocale);
+  }
+
+  public boolean isDisabled() {
+    return StringUtils.isBlank(country);
+  }
+
+  public Locale getLocale() {
+    return locale;
+  }
+
+  public void setLocale(final Locale locale) {
+    this.locale = locale;
+  }
+
+  public Locale getDisplayLocale() {
+    return displayLocale;
+  }
+
+  public void setDisplayLocale(final Locale displayLocale) {
+    this.displayLocale = displayLocale;
+  }
+
+  public String getCountry() {
+    return country;
+  }
+
+  public void setCountry(final String country) {
+    this.country = country;
+  }
+
+  public String getLanguage() {
+    return language;
+  }
+
+  public void setLanguage(final String language) {
+    this.language = language;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/LocaleList.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/LocaleList.java
new file mode 100644
index 0000000..729cf13
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/LocaleList.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+public class LocaleList {
+
+  public static final List<LocaleEntry> DATA;
+
+  public static final List<String> COUNTRY_LANGUAGE;
+
+  public static final List<String> COUNTRY;
+
+  public static final List<String> HOLIDAY;
+
+  static {
+    final List<LocaleEntry> init = new ArrayList<LocaleEntry>();
+    for (final Locale displayLocale : Locale.getAvailableLocales()) {
+      for (final Locale locale : Locale.getAvailableLocales()) {
+        init.add(new LocaleEntry(locale, displayLocale));
+      }
+    }
+    DATA = Collections.unmodifiableList(init);
+  }
+
+  static {
+    final Set<String> init = new HashSet<String>();
+    for (final LocaleEntry localeEntry : DATA) {
+      if (StringUtils.isNotBlank(localeEntry.getCountry())
+          && StringUtils.isNotBlank(localeEntry.getLanguage())) {
+        final String name = localeEntry.getCountry() + " (" + localeEntry.getLanguage() + ")";
+        init.add(name);
+      }
+    }
+    final ArrayList<String> list = new ArrayList<String>(init);
+    Collections.sort(list);
+    COUNTRY_LANGUAGE = Collections.unmodifiableList(list);
+  }
+
+  static {
+    final Set<String> init = new HashSet<String>();
+    for (final LocaleEntry localeEntry : DATA) {
+      if (StringUtils.isNotBlank(localeEntry.getCountry())) {
+        init.add(localeEntry.getCountry());
+      }
+    }
+    final ArrayList<String> list = new ArrayList<String>(init);
+    Collections.sort(list);
+    COUNTRY = Collections.unmodifiableList(list);
+  }
+
+  static {
+    final List<String> list = Arrays.asList(
+        "Trinidad and Tobago",
+        "Portugal",
+        "Norway",
+        "New Zealand",
+        "Equador",
+        "Greece",
+        "Reunion",
+        "Mauritius",
+        "Dominica");
+    Collections.sort(list);
+    HOLIDAY = Collections.unmodifiableList(list);
+  }
+
+
+  private LocaleList() {
+    // do not call
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/MixedCommandTree.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/MixedCommandTree.java
new file mode 100644
index 0000000..b47a3d7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/MixedCommandTree.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+public class MixedCommandTree {
+
+  public static NamedNode createSample() {
+
+    final NamedNode tree = new NamedNode("Commands");
+
+    final NamedNode actions = new NamedNode("Actions");
+    tree.add(actions);
+    actions.add(new NamedNode("Action 1", "Action 1", null, null));
+    actions.add(new NamedNode("Action 2", "Action 2", null, null));
+    actions.add(new NamedNode("Action 3", "Action 3", null, null));
+
+    final NamedNode links = new NamedNode("Links");
+    tree.add(links);
+    links.add(new NamedNode("MyFaces", null, null, "http://myfaces.apache.org/"));
+    links.add(new NamedNode("Apache", null, null, "http://www.apache.org/"));
+
+    final NamedNode scripts = new NamedNode("Scripts");
+    tree.add(scripts);
+    scripts.add(new NamedNode("1", null, "alert(1);", null));
+    scripts.add(new NamedNode("2", null, "alert(2);", null));
+
+    return tree;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/NamedNode.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/NamedNode.java
new file mode 100644
index 0000000..3e427ec
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/NamedNode.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.event.ActionEvent;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class NamedNode extends DefaultMutableTreeNode {
+
+  private static final Logger LOG = LoggerFactory.getLogger(NamedNode.class);
+
+  private String name;
+  private String action;
+  private String script;
+  private String url;
+
+  public NamedNode(final String name) {
+    this.name = name;
+  }
+
+  public NamedNode(final String name, final String action, final String script, final String url) {
+    this.name = name;
+    this.action = action;
+    this.script = script;
+    this.url = url;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String action() {
+    LOG.info(action);
+    return null;
+  }
+
+  public void actionListener(final ActionEvent event) {
+    LOG.info("The actionListener() of node '" + name + "' was called.");
+  }
+
+  public String getScript() {
+    return script;
+  }
+
+  public String getUrl() {
+    return url;
+  }
+
+  public String toString() {
+    return "Node name='" + name + "'";
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Node.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Node.java
new file mode 100644
index 0000000..b582f86
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Node.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.event.TreeExpansionEvent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Node {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Node.class);
+
+  private String name;
+
+  private String id;
+
+  private String tip;
+
+  private Markup markup;
+
+  private boolean expanded = true;
+
+  private boolean disabled;
+
+  private boolean selected;
+
+  public Node(final String name) {
+    this.name = name;
+  }
+
+  public Node(final String name, final String id) {
+    this.name = name;
+    this.id = id;
+  }
+
+  public Node(final String name, final Markup markup) {
+    this.name = name;
+    this.markup = markup;
+  }
+
+  public Node(final String name, final boolean disabled) {
+    this.name = name;
+    this.disabled = disabled;
+  }
+
+  public String action() {
+    LOG.info("action: name='" + name + "'");
+    return null;
+  }
+
+  public void expansionListener(final TreeExpansionEvent event) {
+    LOG.info("event='" + event + "'");
+    expanded = event.isNewExpanded();
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public String getId() {
+    return id;
+  }
+
+  public void setId(final String id) {
+    this.id = id;
+  }
+
+  public boolean isExpanded() {
+    return expanded;
+  }
+
+  public void setExpanded(final boolean expanded) {
+    this.expanded = expanded;
+  }
+
+  public Markup getMarkup() {
+    return markup;
+  }
+
+  public void setMarkup(final Markup markup) {
+    this.markup = markup;
+  }
+
+  public String getTip() {
+    return tip;
+  }
+
+  public void setTip(final String tip) {
+    this.tip = tip;
+  }
+
+  public boolean isDisabled() {
+    return disabled;
+  }
+
+  public void setDisabled(final boolean disabled) {
+    this.disabled = disabled;
+  }
+
+  public boolean isSelected() {
+    return selected;
+  }
+
+  public void setSelected(final boolean selected) {
+    this.selected = selected;
+  }
+
+  public String toString() {
+    return "Node name=" + name + " id=" + id;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Planet.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Planet.java
new file mode 100644
index 0000000..bfbb5ee
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Planet.java
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Deprecated
+public class Planet {
+
+  public static final Planet MERCURY
+      = new Planet("NN", "NN", "NN", "NN", new ArrayList());
+  public static final Planet VENUS
+      = new Planet("NN", "NN", "NN", "NN", new ArrayList());
+  public static final Planet EARTH
+      = new Planet("NN", "NN", "NN", "NN", new ArrayList());
+  public static final Planet MARS
+      = new Planet("6794", "6.421e26", "227940000", "686.98", SolarObject.getSatellites("Mars"));
+
+  private String diameter;
+  private String mass;
+  private String sunDistance;
+  private String timeOfCirculation;
+  private List moons;
+
+  public Planet(final Planet planet) {
+    this.diameter = planet.diameter;
+    this.mass = planet.mass;
+    this.sunDistance = planet.sunDistance;
+    this.timeOfCirculation = planet.timeOfCirculation;
+    this.moons = planet.moons;
+  }
+
+  public Planet(final String diameter, final String mass, final String sunDistance,
+      final String timeOfCirculation, final List moons) {
+    this.diameter = diameter;
+    this.mass = mass;
+    this.sunDistance = sunDistance;
+    this.timeOfCirculation = timeOfCirculation;
+    this.moons = moons;
+  }
+
+  public String getDiameter() {
+    return diameter;
+  }
+
+  public void setDiameter(final String diameter) {
+    this.diameter = diameter;
+  }
+
+  public String getMass() {
+    return mass;
+  }
+
+  public void setMass(final String mass) {
+    this.mass = mass;
+  }
+
+  public String getSunDistance() {
+    return sunDistance;
+  }
+
+  public void setSunDistance(final String sunDistance) {
+    this.sunDistance = sunDistance;
+  }
+
+  public String getTimeOfCirculation() {
+    return timeOfCirculation;
+  }
+
+  public void setTimeOfCirculation(final String timeOfCirculation) {
+    this.timeOfCirculation = timeOfCirculation;
+  }
+
+  public List getMoons() {
+    return moons;
+  }
+
+  public void setMoons(final List moons) {
+    this.moons = moons;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Salutation.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Salutation.java
new file mode 100644
index 0000000..08573ca
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Salutation.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+public enum Salutation {
+
+  UNKNOWN("basic_itemUnknown"),
+
+  MR("basic_itemMr"),
+
+  MRS("basic_itemMrs");
+
+  private String key;
+
+  Salutation(final String key) {
+    this.key = key;
+  }
+
+  public String getKey() {
+    return key;
+  }
+
+  public static Salutation getSalutation(final String key) {
+    for (final Salutation salutation : values()) {
+      if (salutation.getKey().equals(key)) {
+        return salutation;
+      }
+    }
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SalutationConverter.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SalutationConverter.java
new file mode 100644
index 0000000..04e4b99
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SalutationConverter.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+
+public class SalutationConverter implements Converter {
+
+  @Override
+  public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
+      throws ConverterException {
+    return Salutation.getSalutation(value);
+  }
+
+  @Override
+  public String getAsString(final FacesContext context, final UIComponent component, final Object value)
+      throws ConverterException {
+    if (value instanceof Salutation) {
+      return ((Salutation) value).getKey();
+    }
+    return "";
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SmallTree.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SmallTree.java
new file mode 100644
index 0000000..fb6aab6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SmallTree.java
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class SmallTree {
+
+  public static DefaultMutableTreeNode createSample() {
+    final DefaultMutableTreeNode tree = new DefaultMutableTreeNode(new Node("Root Node", "root"));
+    final DefaultMutableTreeNode music = new DefaultMutableTreeNode(new Node("Music", "music"));
+    tree.add(music);
+    music.add(new DefaultMutableTreeNode(new Node("Pop", "pop")));
+    tree.add(new DefaultMutableTreeNode(new Node("Sports", "sports")));
+    return tree;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Solar.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Solar.java
new file mode 100644
index 0000000..a40af62
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/Solar.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@Deprecated
+public class Solar {
+
+  private List<Planet> planets;
+
+  public Solar() {
+    planets = new ArrayList<Planet>();
+    planets.add(new Planet(Planet.MARS));
+  }
+
+  public List<Planet> getPlanets() {
+    return planets;
+  }
+
+  public void setPlanets(final List<Planet> planets) {
+    this.planets = planets;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SolarObject.java b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SolarObject.java
new file mode 100644
index 0000000..07893f2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/java/org/apache/myfaces/tobago/example/data/SolarObject.java
@@ -0,0 +1,366 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.data;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class SolarObject {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SolarObject.class);
+
+  private String name;
+
+  private String number;
+
+  private String orbit;
+
+  private Integer distance;
+
+  private Double period;
+
+  private Double incl;
+
+  private Double eccen;
+
+  private String discoverer;
+
+  private Integer discoverYear;
+
+  private String population;
+
+  private List<Element> chemicalComposition;
+
+  public SolarObject(
+      final String name, final String number, final String orbit, final Integer distance, final Double period,
+      final Double incl, final Double eccen, final String discoverer, final Integer discoverYear) {
+    this.name = name;
+    this.number = number;
+    this.orbit = orbit;
+    this.distance = distance;
+    this.period = period;
+    this.incl = incl;
+    this.eccen = eccen;
+    this.discoverer = discoverer;
+    this.discoverYear = discoverYear;
+    this.population = "Earth".equals(name) ? "ca. 6.800.000.000" : "0";
+  }
+
+  public SolarObject(final SolarObject solarObject) {
+    this.name = solarObject.getName();
+    this.number = solarObject.getNumber();
+    this.orbit = solarObject.getOrbit();
+    this.distance = solarObject.getDistance();
+    this.period = solarObject.getPeriod();
+    this.incl = solarObject.getIncl();
+    this.eccen = solarObject.getEccen();
+    this.discoverer = solarObject.getDiscoverer();
+    this.discoverYear = solarObject.getDiscoverYear();
+    this.population = getPopulation();
+  }
+
+
+  public String getName() {
+    return name;
+  }
+
+  public void update(AjaxBehaviorEvent event) {
+    LOG.info("AjaxBehaviorEvent called. New value: '{}' event: {}", name, event);
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public String getMarkup() {
+    if (name.equals("Sun")) {
+      return "sun";
+    } else {
+      if (orbit.equals("Sun")) {
+        return "planet";
+      } else {
+        return "moon";
+      }
+    }
+  }
+
+  public String getNumber() {
+    return number;
+  }
+
+  public void setNumber(final String number) {
+    this.number = number;
+  }
+
+  public String getOrbit() {
+    return orbit;
+  }
+
+  public void setOrbit(final String orbit) {
+    this.orbit = orbit;
+  }
+
+  public Integer getDistance() {
+    return distance;
+  }
+
+  public void setDistance(final Integer distance) {
+    this.distance = distance;
+  }
+
+  public Double getPeriod() {
+    return period;
+  }
+
+  public void setPeriod(final Double period) {
+    this.period = period;
+  }
+
+  public Double getIncl() {
+    return incl;
+  }
+
+  public void setIncl(final Double incl) {
+    this.incl = incl;
+  }
+
+  public Double getEccen() {
+    return eccen;
+  }
+
+  public void setEccen(final Double eccen) {
+    this.eccen = eccen;
+  }
+
+  public String getDiscoverer() {
+    return discoverer;
+  }
+
+  public void setDiscoverer(final String discoverer) {
+    this.discoverer = discoverer;
+  }
+
+  public Integer getDiscoverYear() {
+    return discoverYear;
+  }
+
+  public void setDiscoverYear(final Integer discoverYear) {
+    this.discoverYear = discoverYear;
+  }
+
+  public String getPopulation() {
+    return population;
+  }
+
+  public void setPopulation(final String population) {
+    this.population = population;
+  }
+
+  public List<Element> getChemicalComposition() {
+    return chemicalComposition != null ? chemicalComposition : Collections.<Element>emptyList();
+  }
+
+  public void setChemicalComposition(final List<Element> chemicalComposition) {
+    this.chemicalComposition = chemicalComposition;
+  }
+
+  public String toString() {
+    return name;
+  }
+
+  public boolean isSelectionDisabled() {
+    return number.equals("II");
+  }
+
+  public static SolarObject[] getArray() {
+    return DATA;
+  }
+
+  public static List<SolarObject> getList() {
+    final SolarObject[] array = getArray();
+    final List<SolarObject> list = new ArrayList<SolarObject>(array.length);
+    Collections.addAll(list, array);
+    return list;
+  }
+
+  public static DefaultMutableTreeNode getTree() {
+    final SolarObject[] array = getArray();
+    final Map<String, DefaultMutableTreeNode> cache = new HashMap<String, DefaultMutableTreeNode>();
+    for (final SolarObject solar : array) {
+      final DefaultMutableTreeNode node = new DefaultMutableTreeNode(solar);
+      cache.put(solar.getName(), node);
+      final String orbitName = solar.getOrbit();
+      if (orbitName.equals("-")) {
+        continue;
+      }
+      // adds a solar object as node to its orbit as tree child.
+      cache.get(orbitName).add(node);
+    }
+    return cache.get("Sun");
+  }
+
+  public static List<SolarObject> getSatellites(final String center) {
+    final List<SolarObject> collect = new ArrayList<SolarObject>();
+    final SolarObject[] all = getArray();
+    for (final SolarObject anAll : all) {
+      if (anAll.getOrbit().equals(center)) {
+        collect.add(anAll);
+      }
+    }
+    return collect;
+  }
+
+  // TODO: optimize
+  public static SolarObject find(String name) {
+    for (SolarObject solarObject : DATA) {
+      if (solarObject.getName().equals(name)) {
+        return solarObject;
+      }
+    }
+    return null;
+  }
+
+
+  public static final SolarObject SUN = new SolarObject("Sun", "-", "-", 0, 0.0, 0.0, 0.0, "-", null);
+  public static final SolarObject EARTH = new SolarObject("Earth", "III", "Sun", 149600, 365.26, 0.00, 0.02, "-", null);
+  public static final SolarObject MOON = new SolarObject("Moon", "I", "Earth", 384, 27.32, 5.14, 0.05, "-", null);
+
+  public static final SolarObject[] DATA = {
+      SUN,
+      new SolarObject("Mercury", "I", "Sun", 57910, 87.97, 7.00, 0.21, "-", null),
+      new SolarObject("Venus", "II", "Sun", 108200, 224.70, 3.39, 0.01, "-", null),
+      EARTH,
+      new SolarObject("Mars", "IV", "Sun", 227940, 686.98, 1.85, 0.09, "-", null),
+      new SolarObject("Jupiter", "V", "Sun", 778330, 4332.71, 1.31, 0.05, "-", null),
+      new SolarObject("Saturn", "VI", "Sun", 1429400, 10759.50, 2.49, 0.06, "-", null),
+      new SolarObject("Uranus", "VII", "Sun", 2870990, 30685.0, 0.77, 0.05, "Herschel", 1781),
+      new SolarObject("Neptune", "VIII", "Sun", 4504300, 60190.0, 1.77, 0.01, "Adams", 1846),
+      new SolarObject("Pluto", "IX", "Sun", 5913520, 90800.0, 17.15, 0.25, "Tombaugh", 1930),
+      MOON,
+      new SolarObject("Phobos", "I", "Mars", 9, 0.32, 1.00, 0.02, "Hall", 1877),
+      new SolarObject("Deimos", "II", "Mars", 23, 1.26, 1.80, 0.00, "Hall", 1877),
+      new SolarObject("Metis", "XVI", "Jupiter", 128, 0.29, 0.00, 0.00, "Synnott", 1979),
+      new SolarObject("Adrastea", "XV", "Jupiter", 129, 0.30, 0.00, 0.00, "Jewitt", 1979),
+      new SolarObject("Amalthea", "V", "Jupiter", 181, 0.50, 0.40, 0.00, "Barnard", 1892),
+      new SolarObject("Thebe", "XIV", "Jupiter", 222, 0.67, 0.80, 0.02, "Synnott", 1979),
+      new SolarObject("Io", "I", "Jupiter", 422, 1.77, 0.04, 0.00, "Galileo", 1610),
+      new SolarObject("Europa", "II", "Jupiter", 671, 3.55, 0.47, 0.01, "Galileo", 1610),
+      new SolarObject("Ganymede", "III", "Jupiter", 1070, 7.15, 0.19, 0.00, "Galileo", 1610),
+      new SolarObject("Callisto", "IV", "Jupiter", 1883, 16.69, 0.28, 0.01, "Galileo", 1610),
+      new SolarObject("Themisto", "XVIII", "Jupiter", 7507, 130.02, null, null, "Sheppard", 2000),
+      new SolarObject("Leda", "XIII", "Jupiter", 11094, 238.72, 27.00, 0.15, "Kowal", 1974),
+      new SolarObject("Himalia", "VI", "Jupiter", 11480, 250.57, 28.00, 0.16, "Perrine", 1904),
+      new SolarObject("Lysithea", "X", "Jupiter", 11720, 259.22, 29.00, 0.11, "Nicholson", 1938),
+      new SolarObject("Elara", "VII", "Jupiter", 11737, 259.65, 28.00, 0.21, "Perrine", 1905),
+      new SolarObject("Ananke", "XII", "Jupiter", 21200, -629.770, 147.00, 0.17, "Nicholson", 1951),
+      new SolarObject("Carme", "XI", "Jupiter", 22600, -702.30, 163.00, 0.21, "Nicholson", 1938),
+      new SolarObject("Pasiphae", "VIII", "Jupiter", 23500, -708.0, 147.00, 0.38, "Melotte", 1908),
+      new SolarObject("Sinope", "IX", "Jupiter", 23700, -758.9, 153.00, 0.28, "Nicholson", 1914),
+      new SolarObject("Iocaste", "XXIV", "Jupiter", 20216, 631.5, null, null, "Sheppard", 2000),
+      new SolarObject("Harpalyke", "XXII", "Jupiter", 21132, 623.3, null, null, "Sheppard", 2000),
+      new SolarObject("Praxidike", "XXVII", "Jupiter", 20964, 625.3, null, null, "Sheppard", 2000),
+      new SolarObject("Taygete", "XX", "Jupiter", 23312, 732.2, null, null, "Sheppard", 2000),
+      new SolarObject("Chaldene", "XXI", "Jupiter", 23387, 723.8, null, null, "Sheppard", 2000),
+      new SolarObject("Kalyke", "XXIII", "Jupiter", 23745, 743.0, null, null, "Sheppard", 2000),
+      new SolarObject("Callirrhoe", "XVII", "Jupiter", 24100, 758.8, null, null, "Sheppard", 2000),
+      new SolarObject("Megaclite", "XIX", "Jupiter", 23911, 752.8, null, null, "Sheppard", 2000),
+      new SolarObject("Isonoe", "XXVI", "Jupiter", 23078, 725.5, null, null, "Sheppard", 2000),
+      new SolarObject("Erinome", "XXV", "Jupiter", 23168, 728.3, null, null, "Sheppard", 2000),
+      new SolarObject("Pan", "XVIII", "Saturn", 134, 0.58, 0.00, 0.00, "Showalter", 1990),
+      new SolarObject("Atlas", "XV", "Saturn", 138, 0.60, 0.00, 0.00, "Terrile", 1980),
+      new SolarObject("Prometheus", "XVI", "Saturn", 139, 0.61, 0.00, 0.00, "Collins", 1980),
+      new SolarObject("Pandora", "XVII", "Saturn", 142, 0.63, 0.00, 0.00, "Collins", 1980),
+      new SolarObject("Epimetheus", "XI", "Saturn", 151, 0.69, 0.34, 0.01, "Walker", 1980),
+      new SolarObject("Janus", "X", "Saturn", 151, 0.69, 0.14, 0.01, "Dollfus", 1966),
+      new SolarObject("Mimas", "I", "Saturn", 186, 0.94, 1.53, 0.02, "Herschel", 1789),
+      new SolarObject("Enceladus", "II", "Saturn", 238, 1.37, 0.02, 0.00, "Herschel", 1789),
+      new SolarObject("Tethys", "III", "Saturn", 295, 1.89, 1.09, 0.00, "Cassini", 1684),
+      new SolarObject("Telesto", "XIII", "Saturn", 295, 1.89, 0.00, 0.00, "Smith", 1980),
+      new SolarObject("Calypso", "XIV", "Saturn", 295, 1.89, 0.00, 0.00, "Pascu", 1980),
+      new SolarObject("Dione", "IV", "Saturn", 377, 2.74, 0.02, 0.00, "Cassini", 1684),
+      new SolarObject("Helene", "XII", "Saturn", 377, 2.74, 0.20, 0.01, "Laques", 1980),
+      new SolarObject("Rhea", "V", "Saturn", 527, 4.52, 0.35, 0.00, "Cassini", 1672),
+      new SolarObject("Titan", "VI", "Saturn", 1222, 15.95, 0.33, 0.03, "Huygens", 1655),
+      new SolarObject("Hyperion", "VII", "Saturn", 1481, 21.28, 0.43, 0.10, "Bond", 1848),
+      new SolarObject("Iapetus", "VIII", "Saturn", 3561, 79.33, 14.72, 0.03, "Cassini", 1671),
+      new SolarObject("Phoebe", "IX", "Saturn", 12952, -550.48, 175.30, 0.16, "Pickering", 1898),
+      new SolarObject("Cordelia", "VI", "Uranus", 50, 0.34, 0.14, 0.00, "Voyager 2", 1986),
+      new SolarObject("Ophelia", "VII", "Uranus", 54, 0.38, 0.09, 0.00, "Voyager 2", 1986),
+      new SolarObject("Bianca", "VIII", "Uranus", 59, 0.43, 0.16, 0.00, "Voyager 2", 1986),
+      new SolarObject("Cressida", "IX", "Uranus", 62, 0.46, 0.04, 0.00, "Voyager 2", 1986),
+      new SolarObject("Desdemona", "X", "Uranus", 63, 0.47, 0.16, 0.00, "Voyager 2", 1986),
+      new SolarObject("Juliet", "XI", "Uranus", 64, 0.49, 0.06, 0.00, "Voyager 2", 1986),
+      new SolarObject("Portia", "XII", "Uranus", 66, 0.51, 0.09, 0.00, "Voyager 2", 1986),
+      new SolarObject("Rosalind", "XIII", "Uranus", 70, 0.56, 0.28, 0.00, "Voyager 2", 1986),
+      new SolarObject("Belinda", "XIV", "Uranus", 75, 0.62, 0.03, 0.00, "Voyager 2", 1986),
+      new SolarObject("1986U10", "", "Uranus", 76, 0.64, null, null, "Karkoschka", 1999),
+      new SolarObject("Puck", "XV", "Uranus", 86, 0.76, 0.31, 0.00, "Voyager 2", 1985),
+      new SolarObject("Miranda", "V", "Uranus", 130, 1.41, 4.22, 0.00, "Kuiper", 1948),
+      new SolarObject("Ariel", "I", "Uranus", 191, 2.52, 0.00, 0.00, "Lassell", 1851),
+      new SolarObject("Umbriel", "II", "Uranus", 266, 4.14, 0.00, 0.00, "Lassell", 1851),
+      new SolarObject("Titania", "III", "Uranus", 436, 8.71, 0.00, 0.00, "Herschel", 1787),
+      new SolarObject("Oberon", "IV", "Uranus", 583, 13.46, 0.00, 0.00, "Herschel", 1787),
+      new SolarObject("Caliban", "XVI", "Uranus", 7169, -579.39, 140., 0.08, "Gladman", 1997),
+      new SolarObject("Stephano", "XX", "Uranus", 7948, -677.48, 143., 0.24, "Gladman", 1999),
+      new SolarObject("Sycorax", "XVII", "Uranus", 12213, -1283.48, 153., 0.51, "Nicholson", 1997),
+      new SolarObject("Prospero", "XVIII", "Uranus", 16568, -1962.95, 152., 0.44, "Holman", 1999),
+      new SolarObject("Setebos", "XIX", "Uranus", 17681, -2196.35, 158., 0.57, "Kavelaars", 1999),
+      new SolarObject("Naiad", "III", "Neptune", 48, 0.29, 0.00, 0.00, "Voyager 2", 1989),
+      new SolarObject("Thalassa", "IV", "Neptune", 50, 0.31, 4.50, 0.00, "Voyager 2", 1989),
+      new SolarObject("Despina", "V", "Neptune", 53, 0.33, 0.00, 0.00, "Voyager 2", 1989),
+      new SolarObject("Galatea", "VI", "Neptune", 62, 0.43, 0.00, 0.00, "Voyager 2", 1989),
+      new SolarObject("Larissa", "VII", "Neptune", 74, 0.55, 0.00, 0.00, "Reitsema", 1989),
+      new SolarObject("Proteus", "VIII", "Neptune", 118, 1.12, 0.00, 0.00, "Voyager 2", 1989),
+      new SolarObject("Triton", "I", "Neptune", 355, -5.88, 157.00, 0.00, "Lassell", 1846),
+      new SolarObject("Nereid", "II", "Neptune", 5513, 360.13, 29.00, 0.75, "Kuiper", 1949),
+      new SolarObject("Charon", "I", "Pluto", 20, 6.39, 98.80, 0.00, "Christy", 1978)
+  };
+
+  static {
+    List<Element> sun = Arrays.asList(
+        new Element("Hydrogen", 0.74),
+        new Element("Helium", 0.25)
+    );
+    SUN.setChemicalComposition(sun);
+    List<Element> earth = Arrays.asList(
+        new Element("Silica", 0.60),
+        new Element("Alimina", 0.15),
+        new Element("Lime", 0.05)
+    );
+    EARTH.setChemicalComposition(earth);
+    List<Element> moon = Arrays.asList(
+        new Element("Silica", 0.45),
+        new Element("Alimina", 0.24),
+        new Element("Lime", 0.16)
+    );
+    MOON.setChemicalComposition(moon);
+  }
+
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/EUR-14.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/EUR-14.png
new file mode 100644
index 0000000..f90188f
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/EUR-14.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/EUR.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/EUR.png
new file mode 100644
index 0000000..c1214bf
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/EUR.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/JPY-14.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/JPY-14.png
new file mode 100644
index 0000000..ca25754
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/JPY-14.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/JPY.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/JPY.png
new file mode 100644
index 0000000..97b237f
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/JPY.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/TTD-14.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/TTD-14.png
new file mode 100644
index 0000000..1bf9397
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/TTD-14.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/TTD.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/TTD.png
new file mode 100644
index 0000000..8bd266e
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/TTD.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/USD-14.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/USD-14.png
new file mode 100644
index 0000000..e0d5457
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/USD-14.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/USD.png b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/USD.png
new file mode 100644
index 0000000..654f777
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/USD.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/edit-solar.xhtml b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/edit-solar.xhtml
new file mode 100644
index 0000000..a04b09d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/edit-solar.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <tc:panel>
+    <tc:in value="#{solar.name}" label="Name" />
+    <tc:in value="#{solar.number}" label="Number" />
+    <tc:in value="#{solar.orbits}" label="Orbits" />
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/sun-behind-mountains.jpg b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/sun-behind-mountains.jpg
new file mode 100644
index 0000000..b1a18ae
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-data/src/main/resources/META-INF/resources/data/sun-behind-mountains.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/pom.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/pom.xml
new file mode 100644
index 0000000..13fb8ca
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/pom.xml
@@ -0,0 +1,785 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-example</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-example-demo</artifactId>
+  <packaging>war</packaging>
+  <name>Tobago Example Demo</name>
+  <description>Demonstration and documentation application.</description>
+
+  <properties>
+    <openwebbeans.version>1.2.8</openwebbeans.version>
+    <deltaspike.version>1.7.1</deltaspike.version>
+    <!--<arquillian.browser>firefox</arquillian.browser>-->
+    <!-- phantomjs works not with CSP (report-only) -->
+    <arquillian.browser>phantomjs</arquillian.browser>
+    <selenium.version>3.0.1</selenium.version>
+    <tomee.version>7.0.1</tomee.version>
+  </properties>
+  <build>
+    <finalName>tobago-example-demo</finalName>
+    <testResources>
+      <testResource>
+        <directory>src/test/resources</directory>
+        <filtering>true</filtering>
+      </testResource>
+    </testResources>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>xml-maven-plugin</artifactId>
+        <version>1.0.1</version>
+        <executions>
+          <execution>
+            <goals>
+              <goal>validate</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <validationSets>
+            <validationSet>
+              <dir>src/main/webapp</dir>
+              <includes>
+                <include>**/*.xhtml</include>
+              </includes>
+              <excludes>
+                  <exclude>**/x-error-in-syntax.xhtml</exclude>
+              </excludes>
+            </validationSet>
+          </validationSets>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <configuration>
+          <webResources>
+            <resource>
+              <targetPath>src</targetPath>
+              <directory>${basedir}/src/main/java</directory>
+            </resource>
+          </webResources>
+        </configuration>
+      </plugin>
+      <plugin>
+        <!-- TODO test glassfish -->
+        <groupId>org.glassfish</groupId>
+        <artifactId>maven-embedded-glassfish-plugin</artifactId>
+        <version>3.1.1</version>
+        <configuration>
+          <port>8080</port>
+          <contextRoot>/</contextRoot>
+          <autoDelete>true</autoDelete>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.eclipse.jetty</groupId>
+        <artifactId>jetty-maven-plugin</artifactId>
+        <configuration>
+          <loginServices>
+            <loginService implementation="org.eclipse.jetty.security.HashLoginService">
+              <name>demo-realm</name>
+              <config>src/test/resources/realm.properties</config>
+            </loginService>
+          </loginServices>
+          <stopKey>stopKey</stopKey>
+          <stopPort>9999</stopPort>
+          <systemProperties>
+            <systemProperty>
+              <name>derby.stream.error.file</name>
+              <value>target/derby.log</value>
+            </systemProperty>
+          </systemProperties>
+        </configuration>
+        <dependencies>
+        </dependencies>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <excludes><!-- TODO define group for ArquillianTests and use excludeGroups -->
+            <exclude>**/ArquillianTest.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-failsafe-plugin</artifactId>
+        <configuration>
+          <includes><!-- TODO define group for ArquillianTests or use convention *IT.java, *ITCase.java -->
+            <include>**/ArquillianTest.java</include>
+          </includes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>io.fabric8</groupId>
+        <artifactId>docker-maven-plugin</artifactId>
+        <version>0.15.9</version>
+        <configuration>
+          <images>
+            <image>
+              <name>selenium/standalone-firefox:${selenium.version}</name>
+              <run>
+                <ports>
+                  <port>4444:4444</port>
+                </ports>
+              </run>
+            </image>
+          </images>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencyManagement>
+    <dependencies>
+      <dependency>
+        <groupId>org.jboss.arquillian</groupId>
+        <artifactId>arquillian-bom</artifactId>
+        <version>1.1.12.Final</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+      <dependency>
+        <groupId>org.jboss.arquillian.selenium</groupId>
+        <artifactId>selenium-bom</artifactId>
+        <version>${selenium.version}</version>
+        <type>pom</type>
+        <scope>import</scope>
+      </dependency>
+      <dependency>
+        <groupId>org.jboss.arquillian.extension</groupId>
+        <artifactId>arquillian-drone-bom</artifactId>
+        <version>2.0.1.Final</version>
+        <scope>import</scope>
+        <type>pom</type>
+      </dependency>
+      <dependency>
+        <groupId>org.jboss.arquillian.graphene</groupId>
+        <artifactId>graphene-webdriver</artifactId>
+        <version>2.1.0.Final</version>
+        <type>pom</type>
+        <scope>test</scope>
+      </dependency>
+    </dependencies>
+  </dependencyManagement>
+
+  <dependencies>
+
+    <!-- Tobago -->
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-example-data</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>oro</groupId>
+      <artifactId>oro</artifactId>
+      <version>2.0.8</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.test</groupId>
+      <artifactId>myfaces-test20</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+
+    <!-- DeltaSpike -->
+    <dependency>
+      <groupId>org.apache.deltaspike.modules</groupId>
+      <artifactId>deltaspike-jsf-module-impl</artifactId>
+      <version>${deltaspike.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-annotation_1.0_spec</artifactId>
+      <!-- compile or provided depends on the used server -->
+      <scope>compile</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.hibernate</groupId>
+      <artifactId>hibernate-validator</artifactId>
+      <version>4.3.2.Final</version>
+    </dependency>
+
+    <dependency>
+      <groupId>org.jboss.arquillian.junit</groupId>
+      <artifactId>arquillian-junit-container</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.shrinkwrap.resolver</groupId>
+      <artifactId>shrinkwrap-resolver-impl-maven</artifactId>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.jboss.arquillian.graphene</groupId>
+      <artifactId>graphene-webdriver</artifactId>
+      <type>pom</type>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+
+    <profile>
+      <id>jsf-provided</id>
+      <!-- use this profile for containers that provide JSF and OWB e.g. WebSphere 8.5 -->
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>provided</value>
+        </property>
+      </activation>
+      <dependencies>
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+          <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+          <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+          <scope>provided</scope>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+          <scope>provided</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.0</id>
+      <activation>
+        <property>
+          <name>!jsf</name>
+        </property>
+      </activation>
+      <dependencies>
+
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+
+        <!-- OWB -->
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-web</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-resource</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.1</value>
+        </property>
+      </activation>
+      <dependencies>
+
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+
+        <!-- OWB -->
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-web</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-resource</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>myfaces-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>myfaces-2.2</value>
+        </property>
+      </activation>
+      <dependencies>
+
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+
+        <!-- OWB -->
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-web</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-resource</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.0</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.0</value>
+        </property>
+      </activation>
+      <dependencies>
+
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+
+        <!-- OWB -->
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-web</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-resource</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.1</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.1</value>
+        </property>
+      </activation>
+      <dependencies>
+
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+
+        <!-- OWB -->
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-web</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-resource</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>mojarra-2.2</id>
+      <activation>
+        <property>
+          <name>jsf</name>
+          <value>mojarra-2.2</value>
+        </property>
+      </activation>
+      <dependencies>
+
+        <!-- Specs -->
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-validation_1.0_spec</artifactId>
+          <version>1.1</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-atinject_1.0_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.geronimo.specs</groupId>
+          <artifactId>geronimo-interceptor_1.1_spec</artifactId>
+          <version>1.0</version>
+        </dependency>
+
+        <!-- OWB -->
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-jsf</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-web</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.openwebbeans</groupId>
+          <artifactId>openwebbeans-resource</artifactId>
+          <version>${openwebbeans.version}</version>
+        </dependency>
+
+      </dependencies>
+    </profile>
+
+    <profile>
+      <!--
+       mvn package cargo:start -Ptomcat7x
+       XXX not working yet
+      -->
+      <id>tomcat7x</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.cargo</groupId>
+            <artifactId>cargo-maven2-plugin</artifactId>
+            <version>1.4.6</version>
+            <configuration>
+              <container>
+                <containerId>tomcat7x</containerId>
+                <zipUrlInstaller>
+                  <url>http://archive.apache.org/dist/tomcat/tomcat-7/v7.0.50/bin/apache-tomcat-7.0.50.zip</url>
+                </zipUrlInstaller>
+                <output>${project.build.directory}/tomcat7/container.log</output>
+                <append>false</append>
+                <log>${project.build.directory}/tomcat7/cargo.log</log>
+              </container>
+              <configuration>
+                <home>${project.build.directory}/tomcat7/container</home>
+              </configuration>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <!--
+       mvn package cargo:start -Ptomcat8x
+       XXX not working yet
+      -->
+      <id>tomcat8x</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.cargo</groupId>
+            <artifactId>cargo-maven2-plugin</artifactId>
+            <version>1.4.6</version>
+            <configuration>
+              <container>
+                <containerId>tomcat8x</containerId>
+                <zipUrlInstaller>
+                  <url>http://archive.apache.org/dist/tomcat/tomcat-8/v8.0.1/bin/apache-tomcat-8.0.1.zip</url>
+                </zipUrlInstaller>
+                <output>${project.build.directory}/tomcat8/container.log</output>
+                <append>false</append>
+                <log>${project.build.directory}/tomcat8/cargo.log</log>
+              </container>
+              <configuration>
+                <home>${project.build.directory}/tomcat8/container</home>
+              </configuration>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+      <dependencies>
+        <dependency>
+          <groupId>org.jboss.arquillian.container</groupId>
+          <artifactId>arquillian-tomcat-embedded-8</artifactId>
+          <version>1.0.0.CR7</version>
+          <scope>test</scope>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>tomee</id>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>apache-tomee</artifactId>
+          <version>${tomee.version}</version>
+          <classifier>webprofile</classifier>
+          <type>zip</type>
+          <scope>test</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.slf4j</groupId>
+              <artifactId>slf4j-jdk14</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>arquillian-tomee-remote</artifactId>
+          <version>${tomee.version}</version>
+          <scope>test</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.slf4j</groupId>
+              <artifactId>slf4j-jdk14</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>qunit-integration-tests</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-failsafe-plugin</artifactId>
+            <configuration>
+              <includes>
+                <include>**/QUnitTests.java</include>
+              </includes>
+              <forkMode>never</forkMode>
+            </configuration>
+            <executions>
+              <execution>
+                <goals>
+                  <goal>integration-test</goal>
+                  <goal>verify</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+      <dependencies>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>apache-tomee</artifactId>
+          <version>${tomee.version}</version>
+          <classifier>webprofile</classifier>
+          <type>zip</type>
+          <scope>test</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.slf4j</groupId>
+              <artifactId>slf4j-jdk14</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+        <dependency>
+          <groupId>org.apache.tomee</groupId>
+          <artifactId>arquillian-tomee-remote</artifactId>
+          <version>${tomee.version}</version>
+          <scope>test</scope>
+          <exclusions>
+            <exclusion>
+              <groupId>org.slf4j</groupId>
+              <artifactId>slf4j-jdk14</artifactId>
+            </exclusion>
+          </exclusions>
+        </dependency>
+      </dependencies>
+    </profile>
+
+    <profile>
+      <id>checkstyle-for-view-definition-language</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-checkstyle-plugin</artifactId>
+            <configuration>
+              <configLocation>META-INF/checkstyle-tobago.xml</configLocation>
+              <includes>**/*.xhtml</includes>
+              <excludes>**/*.java</excludes>
+              <sourceDirectory>src/main/webapp</sourceDirectory>
+            </configuration>
+            <dependencies>
+              <dependency>
+                <groupId>org.apache.myfaces.tobago</groupId>
+                <artifactId>tobago-core</artifactId>
+                <version>${project.version}</version>
+              </dependency>
+            </dependencies>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+</project>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/appended-resouces/META-INF/LICENSE b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/appended-resouces/META-INF/LICENSE
new file mode 100644
index 0000000..b05b910
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/appended-resouces/META-INF/LICENSE
@@ -0,0 +1,51 @@
+------------------------------------------------------------------------------
+For Prism JS:
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For QUnit:
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/appended-resouces/META-INF/NOTICE b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/appended-resouces/META-INF/NOTICE
new file mode 100644
index 0000000..d4e5571
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/appended-resouces/META-INF/NOTICE
@@ -0,0 +1,9 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
+
+This product includes software developed by
+Lea Verou http://lea.verou.me et al. (http://prismjs.com/)
+
+This product includes software developed by
+jQuery Foundation and other contributors (https://qunitjs.com/)
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ButtonLinkController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ButtonLinkController.java
new file mode 100644
index 0000000..c6c1cb8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ButtonLinkController.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Named;
+import java.io.Serializable;
+
+@Named
+public class ButtonLinkController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ButtonLinkController.class);
+
+  public String linkToComponentsRoot() {
+    LOG.info("link to components root");
+    return "/content/20-component/component.xhtml";
+  }
+
+  public String actionPage() {
+    LOG.info("link to components root");
+    return "/content/40-test/4000-button+link/x-action.xhtml";
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CkeditorController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CkeditorController.java
new file mode 100644
index 0000000..ad02fc7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CkeditorController.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class CkeditorController extends SourceFileReader implements Serializable {
+
+  private boolean editorAvailable;
+  private String contentSecurityPolicyMode;
+  private String text;
+  private boolean collapsed;
+
+  public CkeditorController() {
+/* XXX RM
+    editorAvailable = ResourceManagerUtils.getScripts(
+            FacesContext.getCurrentInstance(),
+            "content/20-component/110-wysiwyg/01-ckeditor/ckeditor/ckeditor.js")
+            .size() != 0;
+*/
+
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(FacesContext.getCurrentInstance());
+    contentSecurityPolicyMode = tobagoConfig.getContentSecurityPolicy().getMode().getValue();
+
+    text = "<p><strong>Sun</strong></p>"
+            + "<p>The sun is a star in our galaxy.</p>";
+    collapsed = true;
+  }
+
+  public boolean isEditorAvailable() {
+    return editorAvailable;
+  }
+
+  public String getContentSecurityPolicyMode() {
+    return contentSecurityPolicyMode;
+  }
+
+  public String getText() {
+    return text;
+  }
+
+  public void setText(final String text) {
+    this.text = text;
+  }
+
+  public boolean isCollapsed() {
+    return collapsed;
+  }
+
+  public void setCollapsed(boolean collapsed) {
+    this.collapsed = collapsed;
+  }
+
+  public void switchCollapsed() {
+    collapsed = !collapsed;
+  }
+
+  public String getSource() {
+    return getSource("ckeditor.js");
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleBoxController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleBoxController.java
new file mode 100644
index 0000000..8f784b8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleBoxController.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class CollapsibleBoxController implements Serializable {
+
+  private boolean collapsed = false;
+
+  public boolean isCollapsed() {
+    return collapsed;
+  }
+
+  public void setCollapsed(boolean collapsed) {
+    this.collapsed = collapsed;
+  }
+
+  public void show() {
+    collapsed = false;
+  }
+
+  public void hide() {
+    collapsed = true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleController.java
new file mode 100644
index 0000000..e34fd5b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleController.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class CollapsibleController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CollapsibleController.class);
+
+  private boolean collapsed = true;
+
+  public String submit() {
+    LOG.info("submit(): collapsed={}", collapsed);
+    return FacesContext.getCurrentInstance().getViewRoot().getViewId();
+  }
+
+  public String action() {
+    LOG.info("action(): collapsed={}", collapsed);
+    return null;
+  }
+
+  public String cancel() {
+    LOG.info("cancel(): collapsed={}", collapsed);
+    return null;
+  }
+
+  public boolean isCollapsed() {
+    return collapsed;
+  }
+
+  public void setCollapsed(boolean collapsed) {
+    this.collapsed = collapsed;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsiblePanelController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsiblePanelController.java
new file mode 100644
index 0000000..e11996a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsiblePanelController.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class CollapsiblePanelController implements Serializable {
+
+  private boolean panelCollapsed = false;
+
+  public boolean isPanelCollapsed() {
+    return panelCollapsed;
+  }
+
+  public void setPanelCollapsed(boolean panelCollapsed) {
+    this.panelCollapsed = panelCollapsed;
+  }
+
+  public void showPanel() {
+    panelCollapsed = false;
+  }
+
+  public void hidePanel() {
+    panelCollapsed = true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsiblePopupController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsiblePopupController.java
new file mode 100644
index 0000000..f7dc990
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsiblePopupController.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class CollapsiblePopupController implements Serializable {
+
+  private boolean collapsed = true;
+
+  public boolean isCollapsed() {
+    return collapsed;
+  }
+
+  public void setCollapsed(boolean collapsed) {
+    this.collapsed = collapsed;
+  }
+
+  public void open() {
+    collapsed = false;
+  }
+
+  public void close() {
+    collapsed = true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleSectionController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleSectionController.java
new file mode 100644
index 0000000..85e9a44
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CollapsibleSectionController.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class CollapsibleSectionController implements Serializable {
+
+  private boolean collapsed = false;
+
+  public boolean isCollapsed() {
+    return collapsed;
+  }
+
+  public void setCollapsed(boolean collapsed) {
+    this.collapsed = collapsed;
+  }
+
+  public void show() {
+    collapsed = false;
+  }
+
+  public void hide() {
+    collapsed = true;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ConversionController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ConversionController.java
new file mode 100644
index 0000000..cb6fa31
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ConversionController.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class ConversionController implements Serializable {
+
+  private double amount = 7200000.9876;
+
+  public double getAmount() {
+    return amount;
+  }
+
+  public void setAmount(double amount) {
+    this.amount = amount;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CurrentValueController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CurrentValueController.java
new file mode 100644
index 0000000..2a6ca3a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/CurrentValueController.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Named;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Currency;
+import java.util.Date;
+import java.util.GregorianCalendar;
+
+@Named
+public class CurrentValueController {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CurrentValueController.class);
+
+  private String string;
+  private Date date;
+  private Currency currency;
+
+  public CurrentValueController() {
+
+    string = "simple string";
+
+    try {
+      this.date = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("1969-07-24 16:50:35");
+    } catch (ParseException e) {
+      LOG.error("", e);
+    }
+
+    currency = Currency.getInstance("TTD");
+  }
+
+  public String toUpperCase(final String text) {
+    return text != null ? text.toUpperCase() : null;
+  }
+
+  public Date plus50(final Date base) {
+    if (date == null) {
+      return null;
+    }
+    final GregorianCalendar calendar = new GregorianCalendar();
+    calendar.setTime(date);
+    calendar.add(Calendar.YEAR, 50);
+    return calendar.getTime();
+  }
+
+  public Currency toCurrency(String string) {
+    return Currency.getInstance(string);
+  }
+
+  public String getString() {
+    return string;
+  }
+
+  public Date getDate() {
+    return date;
+  }
+
+  public Currency getCurrency() {
+    return currency;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DateController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DateController.java
new file mode 100644
index 0000000..fc0c6ba
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DateController.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@RequestScoped
+@Named
+public class DateController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DateController.class);
+
+  private Date once;
+  private Date onchange;
+  private Date submitDate;
+
+  public DateController() {
+    once = new Date();
+    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
+    try {
+      submitDate = sdf.parse("2016-05-22");
+    } catch (ParseException e) {
+      LOG.error("", e);
+    }
+  }
+
+  public Date getOnce() {
+    return once;
+  }
+
+  public void setOnce(Date once) {
+    this.once = once;
+  }
+
+  public Date getOnchange() {
+    return onchange;
+  }
+
+  public void setOnchange(Date onchange) {
+    this.onchange = onchange;
+  }
+
+  public Date getNow() {
+    return new Date();
+  }
+
+  public Date getSubmitDate() {
+    return submitDate;
+  }
+
+  public void setSubmitDate(Date submitDate) {
+    this.submitDate = submitDate;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DefaultCommandController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DefaultCommandController.java
new file mode 100644
index 0000000..a66fbe5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DefaultCommandController.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.event.ActionEvent;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class DefaultCommandController implements Serializable {
+
+  private String value1;
+  private String value2;
+  private String value3;
+  private String lastActiveButtonId;
+
+  public String getValue1() {
+    return value1;
+  }
+
+  public void setValue1(String value1) {
+    this.value1 = value1;
+  }
+
+  public String getValue2() {
+    return value2;
+  }
+
+  public void setValue2(String value2) {
+    this.value2 = value2;
+  }
+
+  public String getValue3() {
+    return value3;
+  }
+
+  public void setValue3(String value3) {
+    this.value3 = value3;
+  }
+
+  public void click(final ActionEvent actionEvent) {
+    lastActiveButtonId = actionEvent.getComponent().getId();
+  }
+
+  public String getLastActiveButtonId() {
+    return lastActiveButtonId;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DemoBundle.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DemoBundle.java
new file mode 100644
index 0000000..782516d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DemoBundle.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.context.TobagoBundle;
+
+import javax.faces.context.FacesContext;
+
+/**
+ * Resources of the demo application.
+ */
+public class DemoBundle extends TobagoBundle {
+
+  public static final String VAR = "demoBundle";
+  public static final String BUNDLE_NAME = "org.apache.myfaces.tobago.example.demo.Demo";
+
+  public DemoBundle() {
+    super(BUNDLE_NAME);
+  }
+
+  public static String getString(final FacesContext facesContext, final String key) {
+    return facesContext.getApplication().getResourceBundle(facesContext, VAR).getString(key);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DemoController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DemoController.java
new file mode 100644
index 0000000..1d5e313
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/DemoController.java
@@ -0,0 +1,294 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.deltaspike.core.api.scope.WindowScoped;
+import org.apache.myfaces.tobago.component.UISheet;
+import org.apache.myfaces.tobago.example.data.Salutation;
+import org.apache.myfaces.tobago.model.SelectItem;
+import org.apache.myfaces.tobago.model.Selectable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+import javax.faces.validator.ValidatorException;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Currency;
+import java.util.Date;
+
+@WindowScoped
+@Named(value = "demoController")
+public class DemoController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DemoController.class);
+
+  private static final Selectable[] TREE_SELECT_MODE_KEYS = {
+      Selectable.none,
+      Selectable.single,
+      Selectable.singleLeafOnly,
+      Selectable.multi,
+      Selectable.multiLeafOnly,
+      Selectable.multiCascade
+  };
+
+  private static final Selectable[] TREELISTBOX_SELECT_MODE_KEYS = {
+      Selectable.single,
+      Selectable.singleLeafOnly,
+      Selectable.siblingLeafOnly
+  };
+
+  private String radioValue;
+  private Currency[] currencyItems;
+
+  private Salutation singleValue;
+
+  private Salutation[] multiValue;
+
+  /*
+    @Required
+  */
+  private String basicInput;
+
+  private String suggestInput;
+
+  private String placeholder;
+
+  private String basicArea = "";
+
+  private Date basicDate = new Date();
+
+  private Date basicTime = new Date();
+
+  private Selectable treeSelectMode;
+
+  private Selectable treeListboxSelectMode;
+
+  private String lastAction;
+
+  private SheetConfig sheetConfig;
+
+  public DemoController() {
+    radioValue = "JPY";
+    currencyItems = new Currency[]{
+        Currency.getInstance("JPY"),
+        Currency.getInstance("TTD"),
+        Currency.getInstance("USD"),
+        Currency.getInstance("EUR")
+    };
+    singleValue = Salutation.UNKNOWN;
+    treeSelectMode = TREE_SELECT_MODE_KEYS[3];
+    treeListboxSelectMode = TREELISTBOX_SELECT_MODE_KEYS[0];
+    multiValue = new Salutation[0];
+    sheetConfig = new SheetConfig();
+  }
+
+  private static SelectItem[] getSalutationSelectItems() {
+    final Salutation[] salutations = Salutation.values();
+    final SelectItem[] items = new SelectItem[salutations.length];
+    for (int i = 0; i < items.length; i++) {
+      String label = DemoBundle.getString(FacesContext.getCurrentInstance(), salutations[i].getKey());
+      if (LOG.isTraceEnabled()) {
+        LOG.trace("label = " + label + "");
+      }
+      items[i] = new SelectItem(salutations[i], label);
+    }
+    return items;
+  }
+
+  private static SelectItem[] getSelectItems(final Selectable[] keys) {
+    final SelectItem[] items = new SelectItem[keys.length];
+    for (int i = 0; i < items.length; i++) {
+      String label = DemoBundle.getString(FacesContext.getCurrentInstance(), keys[i].name());
+      if (LOG.isTraceEnabled()) {
+        LOG.trace("label = " + label + "");
+      }
+      items[i] = new SelectItem(keys[i], label);
+    }
+    return items;
+  }
+
+  public void click(final ActionEvent actionEvent) {
+    LOG.info("click the action listener");
+    lastAction = actionEvent.getComponent().getId();
+  }
+
+  public void resetColumnWidths(final ActionEvent event) {
+    final UISheet sheet = (UISheet) event.getComponent().findComponent("sheet");
+    if (sheet != null) {
+      sheet.getState().setColumnWidths(new ArrayList<Integer>());
+    } else {
+      LOG.warn("Didn't find sheet component!");
+    }
+  }
+
+  public String ping() {
+    LOG.debug("ping invoked");
+    return null;
+  }
+
+  public void customValidator(final FacesContext context, final UIComponent component, final Object value)
+      throws ValidatorException {
+    if (value == null) {
+      return;
+    }
+    if (!"tobago".equalsIgnoreCase(value.toString())) {
+      throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please type in 'Tobago'",
+          "Please type in 'Tobago'"));
+    }
+  }
+
+  public boolean getShowPopup() {
+    return "popupButton".equals(lastAction) || "popupButton2".equals(lastAction);
+  }
+
+  public Currency[] getCurrencyItems() {
+    return currencyItems;
+  }
+
+  public SelectItem[] getItems() {
+    return getSalutationSelectItems();
+  }
+
+  public SelectItem[] getItems2() {
+    return getSelectItems(TREE_SELECT_MODE_KEYS);
+
+  }
+
+
+  public SelectItem[] getTreeSelectModeItems() {
+    return getSelectItems(TREE_SELECT_MODE_KEYS);
+
+  }
+
+  public SelectItem[] getTreeListboxSelectModeItems() {
+    return getSelectItems(TREELISTBOX_SELECT_MODE_KEYS);
+
+  }
+
+  public String getRadioValue() {
+    return radioValue;
+  }
+
+  public void setRadioValue(final String radioValue) {
+    this.radioValue = radioValue;
+  }
+
+  public Salutation getSingleValue() {
+    return singleValue;
+  }
+
+  public void setSingleValue(final Salutation singleValue) {
+    this.singleValue = singleValue;
+  }
+
+  public Salutation[] getMultiValue() {
+    return multiValue;
+  }
+
+  public void setMultiValue(final Salutation[] multiValue) {
+    this.multiValue = multiValue;
+  }
+
+  public Date getBasicDate() {
+    return basicDate;
+  }
+
+  public void setBasicDate(final Date basicDate) {
+    this.basicDate = basicDate;
+  }
+
+  public Date getBasicTime() {
+    return basicTime;
+  }
+
+  public void setBasicTime(final Date basicTime) {
+    this.basicTime = basicTime;
+  }
+
+  public Selectable getTreeSelectMode() {
+    return treeSelectMode;
+  }
+
+  public void setTreeSelectMode(final Selectable treeSelectMode) {
+    this.treeSelectMode = treeSelectMode;
+  }
+
+  public Selectable getTreeListboxSelectMode() {
+    return treeListboxSelectMode;
+  }
+
+  public void setTreeListboxSelectMode(final Selectable treeListboxSelectMode) {
+    this.treeListboxSelectMode = treeListboxSelectMode;
+  }
+
+  public String getBasicInput() {
+    return basicInput;
+  }
+
+  public void setBasicInput(final String basicInput) {
+    this.basicInput = basicInput;
+  }
+
+  public String getSuggestInput() {
+    return suggestInput;
+  }
+
+  public void setSuggestInput(final String suggestInput) {
+    this.suggestInput = suggestInput;
+  }
+
+  public String getPlaceholder() {
+    return placeholder;
+  }
+
+  public void setPlaceholder(final String placeholder) {
+    this.placeholder = placeholder;
+  }
+
+  public String getBasicArea() {
+    return basicArea;
+  }
+
+  public void setBasicArea(final String basicArea) {
+    this.basicArea = basicArea;
+  }
+
+  public String getLastAction() {
+    return lastAction;
+  }
+
+  public SheetConfig getSheetConfig() {
+    return sheetConfig;
+  }
+
+  public void setSheetConfig(final SheetConfig sheetConfig) {
+    this.sheetConfig = sheetConfig;
+  }
+
+  public String noop() {
+    LOG.info("noop");
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/EventController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/EventController.java
new file mode 100644
index 0000000..9aac280
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/EventController.java
@@ -0,0 +1,260 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.component.UIBar;
+import org.apache.myfaces.tobago.component.UIButton;
+import org.apache.myfaces.tobago.component.UIIn;
+import org.apache.myfaces.tobago.component.UIRow;
+import org.apache.myfaces.tobago.component.UITextarea;
+import org.apache.myfaces.tobago.example.data.SolarObject;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.component.UIData;
+import javax.faces.event.ActionEvent;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.faces.event.FacesEvent;
+import javax.faces.event.ValueChangeEvent;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+@SessionScoped
+@Named
+public class EventController implements Serializable {
+
+  private List<EventsOnComponent> eventsOnComponents = new ArrayList<EventsOnComponent>();
+  private EventsOnComponent selectedComponent;
+  private int action = 0;
+  private int actionListener = 0;
+  private int ajaxListener = 0;
+  private int valueChangeListener = 0;
+  private List<SolarObject> planets = new ArrayList<SolarObject>();
+  private String selectedPlanet;
+
+  public EventController() {
+    eventsOnComponents.add(new EventsOnComponent("bar", new UIBar().getEventNames()));
+    eventsOnComponents.add(new EventsOnComponent("button", new UIButton().getEventNames()));
+    eventsOnComponents.add(new EventsOnComponent("in", new UIIn().getEventNames()));
+    eventsOnComponents.add(new EventsOnComponent("row", new UIRow().getEventNames()));
+    eventsOnComponents.add(new EventsOnComponent("textarea", new UITextarea().getEventNames()));
+
+    planets.add(new SolarObject("Mercury", "I", "Sun", 57910, 87.97, 7.00, 0.21, "-", null));
+    planets.add(new SolarObject("Venus", "II", "Sun", 108200, 224.70, 3.39, 0.01, "-", null));
+    planets.add(new SolarObject("Earth", "III", "Sun", 149600, 365.26, 0.00, 0.02, "-", null));
+    planets.add(new SolarObject("Mars", "IV", "Sun", 227940, 686.98, 1.85, 0.09, "-", null));
+    planets.add(new SolarObject("Jupiter", "V", "Sun", 778330, 4332.71, 1.31, 0.05, "-", null));
+    planets.add(new SolarObject("Saturn", "VI", "Sun", 1429400, 10759.50, 2.49, 0.06, "-", null));
+    planets.add(new SolarObject("Uranus", "VII", "Sun", 2870990, 30685.0, 0.77, 0.05, "Herschel", 1781));
+    planets.add(new SolarObject("Neptune", "VIII", "Sun", 4504300, 60190.0, 1.77, 0.01, "Adams", 1846));
+  }
+
+  public void reset() {
+    action = 0;
+    actionListener = 0;
+    ajaxListener = 0;
+    valueChangeListener = 0;
+    selectedPlanet = null;
+  }
+
+  public List<EventsOnComponent> getEventsOnComponents() {
+    return eventsOnComponents;
+  }
+
+  public EventsOnComponent getSelectedComponent() {
+    return selectedComponent;
+  }
+
+  public void setSelectedComponent(EventsOnComponent selectedComponent) {
+    this.selectedComponent = selectedComponent;
+  }
+
+  public void selectComponent(final ActionEvent actionEvent) {
+    final UIData data = ComponentUtils.findAncestor(actionEvent.getComponent(), UIData.class);
+    selectedComponent = data != null ? ((EventsOnComponent) data.getRowData()) : null;
+  }
+
+  public void action() {
+    action++;
+  }
+
+  public void actionListener(final ActionEvent event) {
+    actionListener++;
+  }
+
+  public void ajaxListener(final AjaxBehaviorEvent event) {
+    ajaxListener++;
+  }
+
+  public void valueChangeListener(final ValueChangeEvent event) {
+    valueChangeListener++;
+  }
+
+  public int getActionCount() {
+    return action;
+  }
+
+  public int getActionListenerCount() {
+    return actionListener;
+  }
+
+  public int getAjaxListenerCount() {
+    return ajaxListener;
+  }
+
+  public int getValueChangeListenerCount() {
+    return valueChangeListener;
+  }
+
+  public long getCurrentTimestamp() {
+    return new Date().getTime();
+  }
+
+  public List<SolarObject> getPlanets() {
+    return planets;
+  }
+
+  public String getSelectedPlanet() {
+    return selectedPlanet;
+  }
+
+  public void setSelectedPlanet(String selectedPlanet) {
+    this.selectedPlanet = selectedPlanet;
+  }
+
+  public void selectPlanet(final FacesEvent actionEvent) {
+    final UIData data = ComponentUtils.findAncestor(actionEvent.getComponent(), UIData.class);
+    selectedPlanet = data != null ? ((SolarObject) data.getRowData()).getName() : null;
+  }
+
+  public class EventsOnComponent {
+    private String tagName;
+    private Set<String> eventNames = new TreeSet<String>();
+
+    public EventsOnComponent(String tagName, Collection<String> eventNames) {
+      this.tagName = tagName;
+      if (eventNames != null) {
+        this.eventNames.addAll(eventNames);
+      }
+    }
+
+    public String getTagName() {
+      return tagName;
+    }
+
+    public Set<String> getEventNames() {
+      return eventNames;
+    }
+
+    public String getChangeEvent() {
+      return getCommonEventString(CommonEvent.change);
+    }
+
+    public String getClickEvents() {
+      return getCommonEventString(CommonEvent.click, CommonEvent.dblclick);
+    }
+
+    public String getFocusEvents() {
+      return getCommonEventString(CommonEvent.focus, CommonEvent.blur);
+    }
+
+    public String getKeyEvents() {
+      return getCommonEventString(CommonEvent.keydown, CommonEvent.keypress, CommonEvent.keyup);
+    }
+
+    public String getMouseEvents() {
+      return getCommonEventString(CommonEvent.mousedown, CommonEvent.mousemove, CommonEvent.mouseout,
+          CommonEvent.mouseover, CommonEvent.mouseup);
+    }
+
+    public String getSelectEvent() {
+      return getCommonEventString(CommonEvent.select);
+    }
+
+    private String getCommonEventString(CommonEvent... commonEvents) {
+      boolean allTrue = true;
+      boolean allFalse = true;
+
+      for (CommonEvent commonEvent : commonEvents) {
+        if (eventNames.contains(commonEvent.name())) {
+          allFalse = false;
+        } else {
+          allTrue = false;
+        }
+      }
+
+      if (allTrue) {
+        return "x";
+      } else if (allFalse) {
+        return "-";
+      } else {
+        return concatStrings(eventNames);
+      }
+    }
+
+    public String getSpecialEvents() {
+      Set<String> specialEventNames = new TreeSet<String>();
+
+      for (String eventName : eventNames) {
+        boolean isSpecialEvent = true;
+        for (CommonEvent commonEvent : CommonEvent.values()) {
+          if (eventName.equals(commonEvent.name())) {
+            isSpecialEvent = false;
+          }
+        }
+
+        if (isSpecialEvent) {
+          specialEventNames.add(eventName);
+        }
+      }
+
+      return specialEventNames.size() > 0 ? concatStrings(specialEventNames) : "";
+    }
+
+    private String concatStrings(Set<String> strings) {
+      StringBuilder stringBuilder = new StringBuilder();
+
+      int i = 0;
+      for (String string : strings) {
+        i++;
+        stringBuilder.append(string);
+        if (i < strings.size()) {
+          stringBuilder.append(", ");
+        }
+      }
+      return stringBuilder.toString();
+    }
+  }
+
+  private enum CommonEvent {
+    change,
+    click, dblclick,
+    focus, blur,
+    keydown, keypress, keyup,
+    mousedown, mousemove, mouseout, mouseover, mouseup,
+    select
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExceptionController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExceptionController.java
new file mode 100644
index 0000000..8c49eb8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExceptionController.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+
+@RequestScoped
+@Named
+public class ExceptionController implements Serializable {
+
+  public String getStackTrace() {
+    Exception exception = (Exception) FacesContext.getCurrentInstance().getExternalContext()
+            .getRequestMap().get("javax.servlet.error.exception");
+    StringWriter stringWriter = new StringWriter();
+    PrintWriter printWriter = new PrintWriter(stringWriter);
+    exception.printStackTrace(printWriter);
+    return stringWriter.toString();
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExecuteController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExecuteController.java
new file mode 100644
index 0000000..cabecfd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ExecuteController.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@Named
+@SessionScoped
+public class ExecuteController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ExecuteController.class);
+
+  private String value1;
+  private String value2;
+  private String value3;
+  private String value4;
+
+  public String clear() {
+    LOG.info("action");
+    value1=null;
+    value2=null;
+    value3=null;
+    value4=null;
+    log();
+    return "/content/40-test/50000-java/20-ajax-execute/ajax-execute.xhtml";
+  }
+
+  public String reload() {
+    LOG.info("reload");
+    log();
+    return "/content/40-test/50000-java/20-ajax-execute/ajax-execute.xhtml";
+  }
+
+  public String action() {
+    LOG.info("action");
+    log();
+    return null;
+  }
+
+  private void log() {
+    LOG.info("value1='{}'", value1);
+    LOG.info("value2='{}'", value2);
+    LOG.info("value3='{}'", value3);
+    LOG.info("value4='{}'", value4);
+  }
+
+  public String getValue1() {
+    return value1;
+  }
+
+  public void setValue1(String value1) {
+    this.value1 = value1;
+  }
+
+  public String getValue2() {
+    return value2;
+  }
+
+  public void setValue2(String value2) {
+    this.value2 = value2;
+  }
+
+  public String getValue3() {
+    return value3;
+  }
+
+  public void setValue3(String value3) {
+    this.value3 = value3;
+  }
+
+  public String getValue4() {
+    return value4;
+  }
+
+  public void setValue4(String value4) {
+    this.value4 = value4;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ForEachController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ForEachController.java
new file mode 100644
index 0000000..7b54f80
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ForEachController.java
@@ -0,0 +1,114 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class ForEachController implements Serializable {
+
+  private List<River> rivers;
+  private String name;
+  private String length;
+  private String discharge;
+
+  public ForEachController() {
+    reset();
+  }
+
+  public List<River> getRivers() {
+    return rivers;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getLength() {
+    return length;
+  }
+
+  public void setLength(String length) {
+    this.length = length;
+  }
+
+  public String getDischarge() {
+    return discharge;
+  }
+
+  public void setDischarge(String discharge) {
+    this.discharge = discharge;
+  }
+
+  public String addNewRiver() {
+    rivers.add(new River(name, Integer.valueOf(length), Integer.valueOf(discharge)));
+    resetInputFields();
+    return null;
+  }
+
+  public String reset() {
+    rivers = new ArrayList<River>(Arrays.asList(
+            new River("Nile", 6853, 2830),
+            new River("Amazon", 6437, 209000),
+            new River("Yangtze", 6300, 30166)));
+    resetInputFields();
+    return null;
+  }
+
+  private void resetInputFields() {
+    name = null;
+    length = null;
+    discharge = null;
+  }
+
+  public class River {
+    private String name;
+    private int length;
+    private int discharge;
+
+    public River(String name, int length, int discharge) {
+      this.name = name;
+      this.length = length;
+      this.discharge = discharge;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public int getLength() {
+      return length;
+    }
+
+    public int getDischarge() {
+      return discharge;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormAjaxController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormAjaxController.java
new file mode 100644
index 0000000..0cf81c6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormAjaxController.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class FormAjaxController implements Serializable {
+
+  private String outerValue;
+  private String innerValue1;
+  private String innerValue2;
+
+  public String getOuterValue() {
+    return outerValue;
+  }
+
+  public void setOuterValue(String outerValue) {
+    this.outerValue = outerValue;
+  }
+
+  public String getInnerValue1() {
+    return innerValue1;
+  }
+
+  public void setInnerValue1(String innerValue1) {
+    this.innerValue1 = innerValue1;
+  }
+
+  public String getInnerValue2() {
+    return innerValue2;
+  }
+
+  public void setInnerValue2(String innerValue2) {
+    this.innerValue2 = innerValue2;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormController.java
new file mode 100644
index 0000000..fdfe5f9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormController.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class FormController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(FormController.class);
+
+  private String value1;
+  private String value2;
+
+  public String getValue1() {
+    return value1;
+  }
+
+  public void setValue1(String value1) {
+    this.value1 = value1;
+  }
+
+  public String getValue2() {
+    return value2;
+  }
+
+  public void setValue2(String value2) {
+    this.value2 = value2;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormRequiredController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormRequiredController.java
new file mode 100644
index 0000000..9d1154c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/FormRequiredController.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class FormRequiredController implements Serializable {
+
+  private String outerValue;
+  private String innerValue1;
+  private String innerValue2;
+
+  public String getOuterValue() {
+    return outerValue;
+  }
+
+  public void setOuterValue(String outerValue) {
+    this.outerValue = outerValue;
+  }
+
+  public String getInnerValue1() {
+    return innerValue1;
+  }
+
+  public void setInnerValue1(String innerValue1) {
+    this.innerValue1 = innerValue1;
+  }
+
+  public String getInnerValue2() {
+    return innerValue2;
+  }
+
+  public void setInnerValue2(String innerValue2) {
+    this.innerValue2 = innerValue2;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/GroupController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/GroupController.java
new file mode 100644
index 0000000..bbed56b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/GroupController.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.Currency;
+
+@SessionScoped
+@Named
+public class GroupController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(GroupController.class);
+
+  private String chatlog;
+  private String newMessage;
+  private String sendTo;
+  private double value;
+  private double valueInEuro;
+  private Currency currency;
+  private static final Currency[] CURRENCIES;
+
+  static {
+    CURRENCIES = new Currency[]{
+        Currency.getInstance("JPY"),
+        Currency.getInstance("TTD"),
+        Currency.getInstance("USD"),
+        Currency.getInstance("EUR")};
+  }
+
+  public GroupController() {
+    chatlog = "Peter: Hi, how are you?";
+    newMessage = "I'm fine.";
+    sendTo = "";
+    value = 1000.0;
+    currency = Currency.getInstance("EUR");
+  }
+
+  public String getChatlog() {
+    return chatlog;
+  }
+
+  public String getNewMessage() {
+    return newMessage;
+  }
+
+  public void setNewMessage(String newMessage) {
+    this.newMessage = newMessage;
+  }
+
+  public void sendChat() {
+    chatlog += "\nUser Two: " + newMessage;
+    newMessage = "";
+  }
+
+  public String getSendTo() {
+    return sendTo;
+  }
+
+  public void setSendTo(String sendTo) {
+    this.sendTo = sendTo;
+  }
+
+  public void sendToListener(AjaxBehaviorEvent event) {
+
+    LOG.info("AjaxBehaviorEvent called.");
+
+    if (event != null && event.getComponent() instanceof AbstractUICommand) {
+      AbstractUICommand command = (AbstractUICommand) event.getComponent();
+      sendTo = command.getLabel();
+      LOG.info("AjaxBehaviorEvent called. Current label: '{}'", sendTo);
+    }
+  }
+
+  public void compute(AjaxBehaviorEvent event) {
+    LOG.info("AjaxBehaviorEvent called.");
+    compute();
+  }
+
+  private void compute() {
+    if (currency.getCurrencyCode().equals("JPY")) {
+      valueInEuro = value * 0.00884806667;
+    } else if (currency.getCurrencyCode().equals("TTD")) {
+      valueInEuro = value * 0.133748824;
+    } else if (currency.getCurrencyCode().equals("USD")) {
+      valueInEuro = value * 0.896097495;
+    } else if (currency.getCurrencyCode().equals("EUR")) {
+      valueInEuro = value;
+    } else {
+      valueInEuro = 0;
+    }
+    LOG.info("euro value: '{}', value: '{}', currency: '{}'", valueInEuro, value, currency.getCurrencyCode());
+  }
+
+  public double getValue() {
+    return value;
+  }
+
+  public void setValue(double value) {
+    this.value = value;
+  }
+
+  public double getValueInEuro() {
+    return valueInEuro;
+  }
+
+  public Currency getCurrency() {
+    return currency;
+  }
+
+  public void setCurrency(Currency currency) {
+    this.currency = currency;
+  }
+
+  public Currency[] getCurrencies() {
+    return CURRENCIES;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/InController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/InController.java
new file mode 100644
index 0000000..063e19b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/InController.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.inject.Named;
+
+@RequestScoped
+@Named
+public class InController {
+
+  private static final Logger LOG = LoggerFactory.getLogger(InController.class);
+
+  private String changeValue;
+
+  public void update(AjaxBehaviorEvent event) {
+    LOG.info("AjaxBehaviorEvent called. Current value: '{}'", changeValue);
+  }
+
+  public String getChangeValue() {
+    return changeValue;
+  }
+
+  public void setChangeValue(String changeValue) {
+    this.changeValue = changeValue;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/InputSuggestController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/InputSuggestController.java
new file mode 100644
index 0000000..2b77273
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/InputSuggestController.java
@@ -0,0 +1,194 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.commons.lang.math.RandomUtils;
+import org.apache.myfaces.tobago.model.AutoSuggestExtensionItem;
+import org.apache.myfaces.tobago.model.AutoSuggestItem;
+import org.apache.myfaces.tobago.model.AutoSuggestItems;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.component.UIInput;
+import javax.faces.model.SelectItem;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class InputSuggestController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(InputSuggestController.class);
+
+  private String simpleValue;
+  private String zipValue;
+  private String cityValue;
+
+  private List<SelectItem> regionItems;
+
+  private String region;
+
+  private String[][] suggestData = {
+      {"26127 Oldenburg", "26127", "Oldenburg", "Niedersachsen"},
+      {"26203 Wardenburg", "26203", "Wardenburg", "Niedersachsen"},
+      {"26160 Bad Zwischenahn", "26160", "Bad Zwischenahn", "Niedersachsen"},
+      {"26655 Westerstede", "26655", "Westerstede", "Niedersachsen"},
+      {"26919 Brake (Unterweser)", "26919", "Brake", "Niedersachsen"},
+      {"57462 Olpe", "57462", "Olpe", "Nordrhein-Westfalen"},
+      {"23758 Oldenburg (Holstein)", "23758", "Oldenburg", "Schleswig Holstein"},
+      {"99628 Olbersleben", "99628", "Olbersleben", "Tueringen"},
+      {"25860 Olderup", "25860", "Olderup", "Schleswig Holstein"},
+      {"66851 Olenkorb", "66851", "Olenkorb", "Rheinland-Pfalz"}
+  };
+
+
+  public String getSimpleValue() {
+    return simpleValue;
+  }
+
+  public void setSimpleValue(final String simpleValue) {
+    this.simpleValue = simpleValue;
+  }
+
+  public String getZipValue() {
+    return zipValue;
+  }
+
+  public void setZipValue(final String zipValue) {
+    this.zipValue = zipValue;
+  }
+
+  public String getCityValue() {
+    return cityValue;
+  }
+
+  public void setCityValue(final String cityValue) {
+    this.cityValue = cityValue;
+  }
+
+  public List<SelectItem> getRegionItems() {
+    if (regionItems == null) {
+      regionItems = new ArrayList<SelectItem>(17);
+      regionItems.add(new SelectItem("Please select"));
+      regionItems.add(new SelectItem("Baden-Württemberg"));
+      regionItems.add(new SelectItem("Bayern"));
+      regionItems.add(new SelectItem("Berlin"));
+      regionItems.add(new SelectItem("Brandenburg"));
+      regionItems.add(new SelectItem("Bremen"));
+      regionItems.add(new SelectItem("Hamburg"));
+      regionItems.add(new SelectItem("Hessen"));
+      regionItems.add(new SelectItem("Mecklenburg-Vorpommern"));
+      regionItems.add(new SelectItem("Niedersachsen"));
+      regionItems.add(new SelectItem("Nordrhein-Westfalen"));
+      regionItems.add(new SelectItem("Rheinland-Pfalz"));
+      regionItems.add(new SelectItem("Saarland"));
+      regionItems.add(new SelectItem("Sachsen"));
+      regionItems.add(new SelectItem("Sachsen-Anhalt"));
+      regionItems.add(new SelectItem("Schleswig Holstein"));
+      regionItems.add(new SelectItem("Tueringen"));
+    }
+    return regionItems;
+  }
+
+  public String getRegion() {
+    return region;
+  }
+
+  public void setRegion(final String region) {
+    this.region = region;
+  }
+
+  public List<String> getSimpleSuggestItems(final UIInput component) {
+    String prefix = (String) component.getSubmittedValue();
+    LOG.info("Creating items for prefix '" + prefix + "'");
+    if (prefix == null) {
+      prefix = "";
+    }
+    final List<String> list = new ArrayList<String>();
+    final int n = RandomUtils.nextInt(10);
+    for (int i = 0; i < n; i++) {
+      list.add(prefix + i);
+    }
+    return list;
+  }
+
+  public AutoSuggestItems getZipSuggestItems(final UIInput component) {
+    final String prefix = (String) component.getSubmittedValue();
+    final AutoSuggestItems item = new AutoSuggestItems();
+    item.setItems(getSuggestItems(prefix, true));
+    item.setNextFocusId("page:txarea");
+    return item;
+  }
+
+
+
+  public AutoSuggestItems getCitySuggestItems(final UIInput component) {
+    final String prefix = (String) component.getSubmittedValue();
+    final AutoSuggestItems item = new AutoSuggestItems();
+    item.setItems(getSuggestItems(prefix, false));
+    item.setNextFocusId("page:txarea");
+    return item;
+  }
+
+  private List<AutoSuggestItem> getSuggestItems(final String prefix, final boolean zip) {
+    final List<AutoSuggestItem> items = new ArrayList<AutoSuggestItem>();
+    for (final String[] dataRow : suggestData) {
+      if (zip) {
+        if (dataRow[1].startsWith(prefix)) {
+          final AutoSuggestItem item = new AutoSuggestItem();
+          item.setLabel(dataRow[0]);
+          item.setValue(dataRow[1]);
+          final List<AutoSuggestExtensionItem> extensionItems = new ArrayList<AutoSuggestExtensionItem>(2);
+          extensionItems.add(createExtensionItem("page:isCity", dataRow[2]));
+          if (dataRow[3] != null) {
+            extensionItems.add(createExtensionItem("page:isState", dataRow[3]));
+          }
+          item.setExtensionItems(extensionItems);
+          items.add(item);
+        }
+      } else {
+        if (dataRow[2].toLowerCase().startsWith(prefix.toLowerCase())) {
+          final AutoSuggestItem item = new AutoSuggestItem();
+          item.setLabel(dataRow[0]);
+          item.setValue(dataRow[2]);
+          final List<AutoSuggestExtensionItem> extensionItems = new ArrayList<AutoSuggestExtensionItem>(2);
+          extensionItems.add(createExtensionItem("page:isZip", dataRow[1]));
+          if (dataRow[3] != null) {
+            extensionItems.add(createExtensionItem("page:isState", dataRow[3]));
+          }
+          item.setExtensionItems(extensionItems);
+          items.add(item);
+        }
+      }
+    }
+
+    return items;
+  }
+
+  private AutoSuggestExtensionItem createExtensionItem(final String id, final String value) {
+    final AutoSuggestExtensionItem extItem = new AutoSuggestExtensionItem();
+    extItem.setId(id);
+    extItem.setValue(value);
+    return extItem;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Jsr303Bean.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Jsr303Bean.java
new file mode 100644
index 0000000..fd7f632
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Jsr303Bean.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+
+@RequestScoped
+@Named(value = "jsr303")
+public class Jsr303Bean {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Jsr303Bean.class);
+
+  @NotNull
+  private String required;
+
+  @Size(min = 5, max = 10, message = "Must be between 5 and 10")
+  private String length;
+
+  public String action() {
+    LOG.info("Action of JSR-303 called.");
+    return FacesContext.getCurrentInstance().getViewRoot().getViewId();
+  }
+
+  public String getRequired() {
+    return required;
+  }
+
+  public void setRequired(final String required) {
+    this.required = required;
+  }
+
+  public String getLength() {
+    return length;
+  }
+
+  public void setLength(final String length) {
+    this.length = length;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Login.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Login.java
new file mode 100644
index 0000000..7986dad
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/Login.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+@Named
+@RequestScoped
+public class Login {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Login.class);
+
+  private String username;
+  private String password;
+
+  public void login() throws ServletException, IOException {
+    final ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
+    final HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
+    final HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
+
+    LOG.info("Try to login user: '{}'", username);
+    request.login(username, password);
+    LOG.info("Successful login user: '{}'", username);
+
+    response.sendRedirect(response.encodeRedirectURL(
+            request.getContextPath() + "/faces/content/30-concept/80-security/20-roles/roles.xhtml"));
+  }
+
+  public void logout() throws ServletException, IOException {
+    final ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
+    final HttpServletRequest request = (HttpServletRequest) externalContext.getRequest();
+    final HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
+
+    request.logout();
+
+    response.sendRedirect(response.encodeRedirectURL(
+            request.getContextPath() + "/faces/content/30-concept/80-security/20-roles/roles.xhtml"));
+  }
+
+  public String resetSession() throws IOException {
+    LOG.info("Resetting the session.");
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final HttpSession session = (HttpSession) facesContext.getExternalContext().getSession(false);
+    if (session != null) {
+      session.invalidate();
+    }
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    externalContext.redirect(externalContext.getRequestContextPath() + "/");
+    facesContext.responseComplete();
+    return null;
+  }
+
+  public String getUsername() {
+    return username;
+  }
+
+  public void setUsername(String username) {
+    this.username = username;
+  }
+
+  public String getPassword() {
+    return password;
+  }
+
+  public void setPassword(String password) {
+    this.password = password;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ManifestEntry.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ManifestEntry.java
new file mode 100644
index 0000000..20faf2f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ManifestEntry.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+
+public class ManifestEntry extends DefaultMutableTreeNode {
+
+  private final String name;
+  private final String value;
+
+  public ManifestEntry(final String name, final String value) {
+    this.name = name;
+    this.value = value;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getValue() {
+    return value;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ManifestReader.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ManifestReader.java
new file mode 100644
index 0000000..dcf9ce5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ManifestReader.java
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.SheetState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+
+@ApplicationScoped
+@Named
+public class ManifestReader {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ManifestReader.class);
+
+  private final ManifestEntry manifestTree;
+
+  private final SheetState state;
+
+  public ManifestReader() {
+
+    state = new SheetState();
+    state.setExpandedState(new ExpandedState(1));
+    manifestTree = new ManifestEntry("Tobago Example Demo", null);
+
+    URL url = null;
+    try {
+      final Enumeration<URL> ul = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF");
+
+      while (ul.hasMoreElements()) {
+        url = ul.nextElement();
+
+        String name = url.toString();
+        name = name.replaceAll(".+/([^/]+\\.jar)\\!/META-INF/MANIFEST.MF", "$1");
+        final ManifestEntry jar = new ManifestEntry(name, null);
+        manifestTree.add(jar);
+
+        final Manifest manifest = new Manifest(url.openStream());
+        final Attributes attributes = manifest.getMainAttributes();
+        for (final Object key : attributes.keySet()) {
+          jar.add(new ManifestEntry(key.toString(), attributes.get(key).toString()));
+        }
+      }
+    } catch (final IOException e) {
+      LOG.error("Problem while processing URL: " + url, e);
+    }
+  }
+
+  public ManifestEntry getManifestTree() {
+    return manifestTree;
+  }
+
+  public SheetState getState() {
+    return state;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/MessagesController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/MessagesController.java
new file mode 100644
index 0000000..e61c514
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/MessagesController.java
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class MessagesController implements Serializable {
+
+  public FacesMessage.Severity getSeverityFatal() {
+    return FacesMessage.SEVERITY_FATAL;
+  }
+
+  public FacesMessage.Severity getSeverityError() {
+    return FacesMessage.SEVERITY_ERROR;
+  }
+
+  public FacesMessage.Severity getSeverityWarn() {
+    return FacesMessage.SEVERITY_WARN;
+  }
+
+  public FacesMessage.Severity getSeverityInfo() {
+    return FacesMessage.SEVERITY_INFO;
+  }
+
+  public void createFatalMessage() {
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_FATAL, "Fatal Message", "Details of fatal message."));
+  }
+
+  public void createErrorMessage() {
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error Message", "Details of error message."));
+  }
+
+  public void createWarnMessage() {
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_WARN, "Warn Message", "Details of warn message."));
+  }
+
+  public void createInfoMessage() {
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_INFO, "Info Message", "Details of info message."));
+  }
+
+  public void createSevenMessages() {
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_INFO, "First Message - Info", null));
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_FATAL, "Second Message - Fatal", null));
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_WARN, "Third Message - Warn", null));
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_FATAL, "Fourth Message - Fatal", null));
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_ERROR, "Fifth Message - Error", null));
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_INFO, "Sixth Message - Info", null));
+    FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_WARN, "Seventh Message - Warn", null));
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationNode.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationNode.java
new file mode 100644
index 0000000..3dcf7d2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationNode.java
@@ -0,0 +1,117 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.model.TreePath;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class NavigationNode extends DefaultMutableTreeNode implements Comparable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(NavigationNode.class);
+
+  private final String name;
+  private final String branch;
+  private final String title;
+  private final String outcome;
+
+  private NavigationTree tree;
+
+  /** Cache the TreePath for optimization. */
+  private TreePath treePath;
+
+  public NavigationNode(final String path, final NavigationTree tree) {
+
+    this.tree = tree;
+    outcome = path;
+    final Pattern pattern = Pattern.compile("(.*)/([^/]*)\\.(xhtml)");
+//      final Pattern pattern = Pattern.compile("([\\d\\d/]*\\d\\d[^/]*)/([^/]*)\\.(xhtml)");
+    final Matcher matcher = pattern.matcher(path);
+    matcher.find();
+    branch = matcher.group(1);
+    name = matcher.group(2);
+    final String extension = matcher.group(3);
+    final String key = name.replaceAll("\\+|\\-", "_");
+    String t;
+    try {
+      t = DemoBundle.getString(FacesContext.getCurrentInstance(), key);
+    } catch (Exception e) {
+      LOG.error("Not found key '{}' in bundle", key);
+      t = name;
+    }
+    title = t;
+  }
+
+  @Override
+  public int compareTo(final Object o) {
+    final NavigationNode other = (NavigationNode) o;
+    return branch.compareTo(other.getBranch());
+  }
+
+  public String action() {
+    tree.gotoNode(this);
+    return outcome;
+  }
+
+  public void evaluateTreePath() {
+    treePath = new TreePath(this);
+  }
+
+  @Override
+  public NavigationNode getNextNode() {
+    return (NavigationNode) super.getNextNode();
+  }
+
+  @Override
+  public NavigationNode getPreviousNode() {
+    return (NavigationNode) super.getPreviousNode();
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getBranch() {
+    return branch;
+  }
+
+  public String getTitle() {
+    return title;
+  }
+
+  public String getOutcome() {
+    return outcome;
+  }
+
+  public TreePath getTreePath() {
+    return treePath;
+  }
+
+  @Override
+  public String toString() {
+    return outcome;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationState.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationState.java
new file mode 100644
index 0000000..9f0f3f9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationState.java
@@ -0,0 +1,143 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.deltaspike.core.api.scope.WindowScoped;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.SelectedState;
+import org.apache.myfaces.tobago.model.TreeState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.event.Observes;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@WindowScoped
+@Named
+public class NavigationState implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(NavigationState.class);
+
+  @Inject
+  private NavigationTree tree;
+
+  private NavigationNode currentNode;
+
+  private TreeState state = new TreeState(new ExpandedState(1), new SelectedState());
+
+  private boolean viewSource = true;
+
+  @PostConstruct
+  public void init() {
+    currentNode = tree.findByViewId(FacesContext.getCurrentInstance().getViewRoot().getViewId());
+    initState();
+  }
+
+  private void initState() {
+    if (currentNode != null) {
+      state.getSelectedState().clearAndSelect(currentNode.getTreePath());
+      state.getExpandedState().expand(currentNode.getTreePath(), true);
+    }
+  }
+
+  public NavigationNode getCurrentNode() {
+    return currentNode;
+  }
+
+  public String gotoFirst() {
+    return gotoNode(tree.getTree().getNextNode()); // the "first" is the first after the root node
+  }
+
+  public String gotoPrevious() {
+    if (currentNode == null) {
+      return gotoFirst();
+    } else {
+      final NavigationNode previousNode = currentNode.getPreviousNode();
+      if (previousNode != null) {
+        return gotoNode(previousNode);
+      } else {
+        LOG.warn("Strange navigation behavior");
+        return null;
+      }
+    }
+  }
+
+  public String gotoNext() {
+    if (currentNode == null) {
+      return gotoFirst();
+    } else {
+      final NavigationNode nextNode = currentNode.getNextNode();
+      if (nextNode != null) {
+        return gotoNode(nextNode);
+      } else {
+        LOG.warn("Strange navigation behavior");
+        return null;
+      }
+    }
+  }
+
+  public String gotoNode(@Observes final NavigationNode node) {
+    if (node == null) {
+      return gotoFirst();
+    } else {
+      currentNode = node;
+      initState();
+      LOG.info("Navigate to '" + currentNode.getOutcome() + "'");
+      return currentNode.getOutcome();
+    }
+  }
+
+  public boolean isFirst() {
+    if (currentNode == null) {
+      return false;
+    }
+    final NavigationNode previousNode = currentNode.getPreviousNode();
+    return previousNode == null || previousNode.isRoot();
+  }
+
+  public boolean isLast() {
+    if (currentNode == null) {
+      return false;
+    }
+    final NavigationNode nextNode = currentNode.getNextNode();
+    return nextNode == null;
+  }
+
+  public TreeState getState() {
+    return state;
+  }
+
+  public String toggleViewSource() {
+    viewSource = !viewSource;
+    return null;
+  }
+
+  public boolean isViewSource() {
+    return viewSource;
+  }
+
+  public void setViewSource(boolean viewSource) {
+    this.viewSource = viewSource;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationTree.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationTree.java
new file mode 100644
index 0000000..a6cfe80
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/NavigationTree.java
@@ -0,0 +1,177 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.annotation.PostConstruct;
+import javax.enterprise.context.ApplicationScoped;
+import javax.enterprise.event.Event;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.servlet.ServletContext;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+@ApplicationScoped
+@Named
+public class NavigationTree implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(NavigationTree.class);
+
+  private NavigationNode root;
+
+  @Inject
+  private Event<NavigationNode> events;
+
+  /**
+   * todo: Seems not working with Java EE 6, needs Java EE 7?
+   */
+//  @Inject
+//  private ServletContext servletContext;
+  public NavigationTree() {
+    LOG.info("<init> " + this);
+  }
+
+  @PostConstruct
+  protected void postConstruct() {
+    // todo: refactor with Java EE 7
+    final ServletContext servletContext;
+    servletContext = ((ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext());
+    final List<String> list = locateResourcesInWar(servletContext, "/content", new ArrayList<String>());
+
+    list.add("/content/root-dummy.xhtml"); // helps to build the tree, this is not an existing file
+    final List<NavigationNode> nodes = new ArrayList<NavigationNode>();
+    for (final String path : list) {
+
+      if (path.contains("/x-") || !path.contains(".xhtml")) {
+        // ignoring excluded files
+        continue;
+      }
+      try {
+        nodes.add(new NavigationNode(path, this));
+      } catch (final IllegalStateException e) {
+        LOG.error("Found file with wrong pattern: '{}'", path);
+      }
+    }
+
+    Collections.sort(nodes);
+
+    // after sorting the first node is the root node.
+    root = nodes.get(0);
+
+    final Map<String, NavigationNode> map = new HashMap<String, NavigationNode>();
+//    map.put(tree.getBranch(), tree);
+
+    for (final NavigationNode node : nodes) {
+      LOG.info("node='{}' with title '{}'", node.getName(), node.getTitle());
+      map.put(node.getBranch(), node);
+      final String parent = node.getBranch().substring(0, node.getBranch().lastIndexOf('/'));
+      if (!parent.equals("")) { // is root
+        map.get(parent).add(node);
+      }
+      node.evaluateTreePath();
+    }
+  }
+
+  protected List<String> locateResourcesInWar(
+      final ServletContext servletContext, final String directory, final List<String> result) {
+
+    final Set<String> resourcePaths = servletContext.getResourcePaths(directory);
+
+    if (resourcePaths != null) {
+      for (final String path : resourcePaths) {
+
+        if (path.endsWith("/.svn/")) {
+          // ignoring svn files
+          continue;
+        }
+
+        if (path.endsWith("/")) {
+          locateResourcesInWar(servletContext, path, result);
+          continue;
+        }
+
+        result.add(path);
+
+      }
+    }
+    return result;
+  }
+
+  public NavigationNode findByViewId(String viewId) {
+    final Enumeration enumeration = root.depthFirstEnumeration();
+    while (enumeration.hasMoreElements()) {
+      final NavigationNode node = ((NavigationNode) enumeration.nextElement());
+      if (node.getOutcome() != null && viewId.contains(node.getOutcome())) {
+        return node;
+      }
+    }
+    return null;
+  }
+
+  public NavigationNode getTree() {
+    return root;
+  }
+
+  public void gotoNode(final NavigationNode node) {
+    if (node != null) {
+      events.fire(node);
+    } else {
+      events.fire(root);
+    }
+  }
+
+  public String getSource() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    final String viewId = facesContext.getViewRoot().getViewId();
+    InputStream resourceAsStream = null;
+    try {
+      resourceAsStream = externalContext.getResourceAsStream(viewId);
+      return IOUtils.toString(resourceAsStream, "UTF-8");
+    } catch (final IOException e) {
+      LOG.error("", e);
+      return "error";
+    } finally {
+      IOUtils.closeQuietly(resourceAsStream);
+    }
+  }
+
+  public boolean isMessagesPage() {
+    return FacesContext.getCurrentInstance().getViewRoot().getViewId().endsWith("messages.xhtml");
+  }
+
+  public boolean isOutputPage() {
+    return FacesContext.getCurrentInstance().getViewRoot().getViewId().endsWith("output.xhtml");
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ObjectController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ObjectController.java
new file mode 100644
index 0000000..82f6a91
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ObjectController.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class ObjectController extends SourceFileReader implements Serializable {
+
+  public String getJavaScriptSource() {
+    return getSource("object.js");
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/OnOffConverter.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/OnOffConverter.java
new file mode 100644
index 0000000..e2a7f31
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/OnOffConverter.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+
+public class OnOffConverter implements Converter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(OnOffConverter.class);
+
+  @Override
+  public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
+      throws ConverterException {
+    final String result = Boolean.parseBoolean(value) ? "on" : "off";
+    LOG.info("Got value = '" + value + "'. Result = '" + result + "'");
+    return result;
+  }
+
+  @Override
+  public String getAsString(final FacesContext context, final UIComponent component, final Object value)
+      throws ConverterException {
+    final String result = "on".equals(value) ? Boolean.TRUE.toString() : Boolean.FALSE.toString();
+    LOG.info("Got value = '" + value + "'. Result: '" + result + "'");
+    return result;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/OutController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/OutController.java
new file mode 100644
index 0000000..1f30824
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/OutController.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.inject.Named;
+import java.io.Serializable;
+
+@Named
+public class OutController implements Serializable {
+
+  public String getHtml() {
+    return "Text in <span style='color:#FF0000'>red</span>, "
+        + "<span style='color:#00FF00'>green</span> and <span style='color:#0000FF'>blue</span>.";
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PanelController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PanelController.java
new file mode 100644
index 0000000..70e1415
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PanelController.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.Date;
+
+@RequestScoped
+@Named
+public class PanelController implements Serializable {
+
+  private String text;
+
+  public Date getCurrentDate() {
+    return new Date();
+  }
+
+  public String getText() {
+    return text;
+  }
+
+  public void setText(String text) {
+    this.text = text;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PartialReloadController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PartialReloadController.java
new file mode 100644
index 0000000..2d3d849
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PartialReloadController.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.util.AjaxUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.enterprise.context.RequestScoped;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.util.Date;
+
+@RequestScoped
+@Named
+public class PartialReloadController {
+
+  private static final Logger LOG = LoggerFactory.getLogger(PartialReloadController.class);
+
+  private String navigateActionValue;
+
+  @Inject
+  private NavigationState navigationState;
+
+  public Date getCurrentDate() {
+    return new Date();
+  }
+
+  public String reload() {
+    return logAndNavigate(null);
+  }
+
+  public String error() {
+    throw new RuntimeException("Test Exception");
+  }
+  
+  public String waitAndReload3() {
+    return waitAndReload(3000);
+  }
+
+  public String waitAndReload7() {
+    return waitAndReload(7000);
+  }
+
+  private String waitAndReload(final long delay) {
+    synchronized (this) {
+      try {
+        wait(delay);
+      } catch (final InterruptedException e) {
+        //
+      }
+    }
+    return logAndNavigate(null);
+  }
+
+  public void navigateAction(AjaxBehaviorEvent event) {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+
+    if (navigationState == null) {
+      final ELContext elContext = facesContext.getELContext();
+      final ValueExpression expression = facesContext.getApplication().getExpressionFactory()
+          .createValueExpression(elContext, "#{navigationState}", NavigationState.class);
+      navigationState = (NavigationState) expression.getValue(elContext);
+    }
+
+    LOG.info("navigateActionValue = \"" + navigateActionValue + "\"");
+    if (navigateActionValue == null) {
+      logAndNavigate(null);
+    } else if ("left".equals(navigateActionValue)) {
+      AjaxUtils.addRenderIds("page:mainForm:left");
+      navigateActionValue = null;
+      logAndNavigate(null);
+    } else if ("right".equals(navigateActionValue)) {
+      AjaxUtils.addRenderIds("page:mainForm:right");
+      navigateActionValue = null;
+      logAndNavigate(null);
+    } else if ("both".equals(navigateActionValue)) {
+      AjaxUtils.addRenderIds("page:mainForm:left", "page:mainForm:right");
+      navigateActionValue = null;
+      logAndNavigate(null);
+    } else if ("parent".equals(navigateActionValue)) {
+      navigateActionValue = null;
+      AjaxUtils.addRenderIds("page:mainForm:parent");
+      logAndNavigate(null);
+    } else if ("prev".equals(navigateActionValue)) {
+      navigateActionValue = null;
+      AjaxUtils.navigate(facesContext, logAndNavigate(navigationState.gotoPrevious()));
+    } else if ("next".equals(navigateActionValue)) {
+      navigateActionValue = null;
+      AjaxUtils.navigate(facesContext, logAndNavigate(navigationState.gotoNext()));
+    }
+    logAndNavigate(null);
+  }
+
+  private String logAndNavigate(final String navValue) {
+    LOG.info("Return navigate value: " + navValue + "");
+    return navValue;
+  }
+
+
+  public String getNavigateActionValue() {
+    return navigateActionValue;
+  }
+
+  public void setNavigateActionValue(final String navigateActionValue) {
+    this.navigateActionValue = navigateActionValue;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PlanetExample.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PlanetExample.java
new file mode 100644
index 0000000..fa34fd5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PlanetExample.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.model.SelectItem;
+
+public abstract class PlanetExample {
+
+  private SelectItem[] planets;
+  private SelectItem[] earthMoons;
+  private SelectItem[] marsMoons;
+  private SelectItem[] jupiterMoons;
+  private int planet;
+
+  public PlanetExample() {
+    planets = new SelectItem[]{
+            new SelectItem(0, "Earth"),
+            new SelectItem(1, "Mars"),
+            new SelectItem(2, "Jupiter")};
+    earthMoons = new SelectItem[]{
+            new SelectItem(0, "Moon")
+    };
+    marsMoons = new SelectItem[]{
+            new SelectItem(0, "Phobos"),
+            new SelectItem(1, "Deimos")
+    };
+    jupiterMoons = new SelectItem[]{
+            new SelectItem(0, "Europa"),
+            new SelectItem(1, "Ganymed"),
+            new SelectItem(2, "Io"),
+            new SelectItem(3, "Kallisto")
+    };
+  }
+
+  public SelectItem[] getPlanets() {
+    return planets;
+  }
+
+  public int getPlanet() {
+    return planet;
+  }
+
+  public void setPlanet(int planet) {
+    this.planet = planet;
+  }
+
+  public SelectItem[] getMoons() {
+    switch (planet) {
+      case 0:
+        return earthMoons;
+      case 1:
+        return marsMoons;
+      case 2:
+        return jupiterMoons;
+      default:
+        return new SelectItem[0];
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PopupController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PopupController.java
new file mode 100644
index 0000000..5ad1b92
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PopupController.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class PopupController implements Serializable {
+
+  private boolean popup1Collapsed = true;
+  private String popup1Text;
+  private String popup2Text;
+
+  public boolean isPopup1Collapsed() {
+    return popup1Collapsed;
+  }
+
+  public void setPopup1Collapsed(boolean popup1Collapsed) {
+    this.popup1Collapsed = popup1Collapsed;
+  }
+
+  public void openPopup1() {
+    popup1Collapsed = false;
+  }
+
+  public void closePopup1() {
+    popup1Collapsed = true;
+  }
+
+  public String getPopup1Text() {
+    return popup1Text;
+  }
+
+  public void setPopup1Text(String popup1Text) {
+    this.popup1Text = popup1Text;
+  }
+
+  public String getPopup2Text() {
+    return popup2Text;
+  }
+
+  public void setPopup2Text(String popup2Text) {
+    this.popup2Text = popup2Text;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PrettyUrlForMenuNavigationHandler.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PrettyUrlForMenuNavigationHandler.java
new file mode 100644
index 0000000..7520f52
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/PrettyUrlForMenuNavigationHandler.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.commons.lang.StringUtils;
+
+import javax.faces.application.NavigationHandler;
+import javax.faces.application.ViewHandler;
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.List;
+
+public class PrettyUrlForMenuNavigationHandler extends NavigationHandler {
+
+  private NavigationHandler navigationHandler;
+
+  public PrettyUrlForMenuNavigationHandler(final NavigationHandler navigationHandler) {
+    this.navigationHandler = navigationHandler;
+  }
+
+  @Override
+  public void handleNavigation(final FacesContext facesContext, final String fromAction, String outcome) {
+
+    if (StringUtils.startsWith(outcome, "/content/")) {
+      final ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
+      final UIViewRoot viewRoot = viewHandler.createView(facesContext, outcome);
+      facesContext.setViewRoot(viewRoot);
+      final ExternalContext externalContext = facesContext.getExternalContext();
+      try {
+        externalContext.redirect(
+            externalContext.encodeRedirectURL(externalContext.getRequestContextPath() + "/faces" + outcome,
+            Collections.<String, List<String>>emptyMap()));
+      } catch (final IOException e) {
+        // not nice?
+        facesContext.renderResponse();
+      }
+    } else {
+      navigationHandler.handleNavigation(facesContext, fromAction, outcome);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ProgressController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ProgressController.java
new file mode 100644
index 0000000..ea097f7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ProgressController.java
@@ -0,0 +1,77 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.event.FacesEvent;
+import javax.inject.Named;
+import javax.swing.DefaultBoundedRangeModel;
+import java.io.Serializable;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+@SessionScoped
+@Named
+public class ProgressController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ProgressController.class);
+
+  private DefaultBoundedRangeModel progress = new DefaultBoundedRangeModel(3, 0, 0, 5);
+
+  public DefaultBoundedRangeModel getProgress() {
+    return progress;
+  }
+
+  public void addProgress() {
+    int value = progress.getValue();
+
+    if (value >= progress.getMaximum()) {
+      progress.setValue(0);
+    } else {
+      progress.setValue(value + 1);
+    }
+  }
+
+  public void resetProgress(final FacesEvent event) {
+    progress.setValue(0);
+  }
+
+  public Date getCurrentDate() {
+    return new Date();
+  }
+
+  public double getCurrentHours() {
+    SimpleDateFormat sdf = new SimpleDateFormat("HH");
+    return Double.valueOf(sdf.format(getCurrentDate()));
+  }
+
+  public double getCurrentMinutes() {
+    SimpleDateFormat sdf = new SimpleDateFormat("mm");
+    return Double.valueOf(sdf.format(getCurrentDate()));
+  }
+
+  public double getCurrentSeconds() {
+    SimpleDateFormat sdf = new SimpleDateFormat("ss");
+    return Double.valueOf(sdf.format(getCurrentDate()));
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ResizeController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ResizeController.java
new file mode 100644
index 0000000..bb06424
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ResizeController.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.inject.Model;
+
+@Model
+public class ResizeController {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ResizeController.class);
+
+  public String resize() {
+    LOG.info("Method resize() was called!");
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/RoleController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/RoleController.java
new file mode 100644
index 0000000..b2e3852
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/RoleController.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.annotation.security.RolesAllowed;
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class RoleController implements Serializable {
+
+  private String text;
+  private static final String OUTCOME_ADMIN = "admin";
+
+  public String getText() {
+    return text;
+  }
+
+  public void setText(String text) {
+    this.text = text;
+  }
+
+  @RolesAllowed({"demo-admin", "demo-guest"})
+  public boolean guestBox() {
+    return true;
+  }
+
+  @RolesAllowed({"demo-admin"})
+  public boolean adminBox() {
+    return true;
+  }
+
+  @RolesAllowed({"demo-admin"})
+  public String admin() {
+    return OUTCOME_ADMIN;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectBooleanCheckboxController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectBooleanCheckboxController.java
new file mode 100644
index 0000000..3e5a81c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectBooleanCheckboxController.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class SelectBooleanCheckboxController implements Serializable {
+
+  private boolean a;
+  private boolean b;
+  private boolean c;
+  private boolean d;
+  private boolean e;
+  private boolean f;
+
+  public boolean isA() {
+    return a;
+  }
+
+  public void setA(boolean a) {
+    this.a = a;
+  }
+
+  public boolean isB() {
+    return b;
+  }
+
+  public void setB(boolean b) {
+    this.b = b;
+  }
+
+  public boolean isC() {
+    return c;
+  }
+
+  public void setC(boolean c) {
+    this.c = c;
+  }
+
+  public boolean isD() {
+    return d;
+  }
+
+  public void setD(boolean d) {
+    this.d = d;
+  }
+
+  public boolean isE() {
+    return e;
+  }
+
+  public void setE(boolean e) {
+    this.e = e;
+  }
+
+  public boolean isF() {
+    return f;
+  }
+
+  public void setF(boolean f) {
+    this.f = f;
+  }
+
+  public String getSelectedItems() {
+    return (a ? "A " : "") + (b ? "B " : "") + (c ? "C " : "");
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectController.java
new file mode 100644
index 0000000..dae8114
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectController.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.model.SelectItem;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class SelectController implements Serializable {
+
+  private SelectItem[] entries;
+
+  public SelectController() {
+    entries = new SelectItem[]{
+            new SelectItem("1", "Entry One"),
+            new SelectItem("2", "Entry Two"),
+            new SelectItem("3", "Entry Three"),
+            new SelectItem("4", "Entry Four"),
+            new SelectItem("5", "Entry Five"),
+            new SelectItem("6", "Entry Six"),
+            new SelectItem("7", "Entry Seven"),
+            new SelectItem("8", "Entry Eight"),
+            new SelectItem("9", "Entry Nine")
+    };
+  }
+
+  public SelectItem[] getEntries() {
+    return entries;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectItemModel.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectItemModel.java
new file mode 100644
index 0000000..2fe3211
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectItemModel.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.model.SelectItem;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.Currency;
+
+@Named
+@SessionScoped
+public class SelectItemModel implements Serializable {
+
+  private int number = 3;
+
+  private Currency currency = Currency.getInstance("JPY");
+  private Currency currency2;
+
+  private final SelectItem[] availableCurrencies;
+
+  private final Currency[] availableCurrenciesAsObject;
+
+  public SelectItemModel() {
+    availableCurrenciesAsObject = new Currency[]{
+        Currency.getInstance("JPY"),
+        Currency.getInstance("TTD"),
+        Currency.getInstance("USD"),
+        Currency.getInstance("EUR")
+    };
+    availableCurrencies = new SelectItem[availableCurrenciesAsObject.length];
+    for (int i = 0; i < availableCurrenciesAsObject.length; i++) {
+      availableCurrencies[i] = new SelectItem(availableCurrenciesAsObject[i]);
+    }
+  }
+
+  public SelectItem[] getAvailableCurrencies() {
+    return availableCurrencies;
+  }
+
+  public Currency[] getAvailableCurrenciesAsObject() {
+    return availableCurrenciesAsObject;
+  }
+
+  public int getNumber() {
+    return number;
+  }
+
+  public void setNumber(final int number) {
+    this.number = number;
+  }
+
+  public void setCurrency(final Currency currency) {
+    this.currency = currency;
+  }
+
+  public Currency getCurrency() {
+    return currency;
+  }
+
+  public Currency getCurrency2() {
+    return currency2;
+  }
+
+  public void setCurrency2(Currency currency2) {
+    this.currency2 = currency2;
+  }
+
+  public int getTwo() {
+    return 2;
+  }
+
+  public int getFour() {
+    return 4;
+  }
+
+  public Currency getUsd() {
+    return Currency.getInstance("USD");
+  }
+
+  public Currency getEur() {
+    return Currency.getInstance("EUR");
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyCheckboxController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyCheckboxController.java
new file mode 100644
index 0000000..1596dc1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyCheckboxController.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@RequestScoped
+@Named
+public class SelectManyCheckboxController implements Serializable {
+
+  private List<String> animals = new ArrayList<String>();
+  private List<String> numbers = new ArrayList<String>();
+
+  public List getAnimals() {
+    return animals;
+  }
+
+  public void setAnimals(List<String> animals) {
+    this.animals = animals;
+  }
+
+  public String getAnimal() {
+    String retValue = "";
+    for (String s : animals) {
+      retValue = retValue.concat(s + " ");
+    }
+    return retValue;
+  }
+
+  public List<String> getNumbers() {
+    return numbers;
+  }
+
+  public void setNumbers(List<String> numbers) {
+    this.numbers = numbers;
+  }
+
+  public int getResult() {
+    int result = 0;
+    for (String number : numbers) {
+      result += Integer.valueOf(number);
+    }
+    return result;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyListboxController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyListboxController.java
new file mode 100644
index 0000000..5d43970
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyListboxController.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.model.SelectItem;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@RequestScoped
+@Named
+public class SelectManyListboxController implements Serializable {
+
+  private List<String> celestials = new ArrayList<String>();
+  private SelectItem[] deserts;
+  private List<String> selectedDeserts = new ArrayList<String>();
+
+  public SelectManyListboxController() {
+    deserts = new SelectItem[]{
+            new SelectItem("Antarctic Desert"),
+            new SelectItem("Arctic"),
+            new SelectItem("Sahara"),
+            new SelectItem("Arabian Desert"),
+            new SelectItem("Gobi Desert")
+    };
+  }
+
+  public List<String> getCelestials() {
+    return celestials;
+  }
+
+  public void setCelestials(List<String> celestials) {
+    this.celestials = celestials;
+  }
+
+  public String getCelestial() {
+    String retValue = "";
+    for (String s : celestials) {
+      retValue = retValue.concat(s);
+    }
+    return retValue;
+  }
+
+  public SelectItem[] getDeserts() {
+    return deserts;
+  }
+
+  public List<String> getSelectedDeserts() {
+    return selectedDeserts;
+  }
+
+  public void setSelectedDeserts(List<String> selectedDeserts) {
+    this.selectedDeserts = selectedDeserts;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyShuttleController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyShuttleController.java
new file mode 100644
index 0000000..dd8fbca
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectManyShuttleController.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.example.data.SolarObject;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class SelectManyShuttleController implements Serializable {
+
+  private List<SolarObject> planets = new ArrayList<SolarObject>();
+  private SolarObject[] selectedPlanets = new SolarObject[0];
+  private List<String> stars = Arrays.asList("Proxima Centauri", "Alpha Centauri", "Wolf 359", "Sirius");
+  private String[] selectedStars = new String[0];
+
+  public SelectManyShuttleController() {
+    planets = SolarObject.getSatellites("Sun");
+  }
+
+  public List<SolarObject> getPlanets() {
+    return planets;
+  }
+
+  public SolarObject[] getSelectedPlanets() {
+    return selectedPlanets;
+  }
+
+  public void setSelectedPlanets(SolarObject[] selectedPlanets) {
+    this.selectedPlanets = selectedPlanets;
+  }
+
+  public String getSelectedPlanetsAsString() {
+    return Arrays.toString(selectedPlanets);
+  }
+
+  public List<String> getStars() {
+    return stars;
+  }
+
+  public String[] getSelectedStars() {
+    return selectedStars;
+  }
+
+  public void setSelectedStars(String[] selectedStars) {
+    this.selectedStars = selectedStars;
+  }
+
+  public String getSelectedStarsAsString() {
+    return Arrays.toString(selectedStars);
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneChoiceController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneChoiceController.java
new file mode 100644
index 0000000..d578857
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneChoiceController.java
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class SelectOneChoiceController extends PlanetExample implements Serializable {
+
+  private String person;
+
+  public String getPerson() {
+    return person;
+  }
+
+  public void setPerson(String person) {
+    this.person = person;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneListboxController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneListboxController.java
new file mode 100644
index 0000000..38a820a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneListboxController.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.model.SelectItem;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class SelectOneListboxController implements Serializable {
+
+  private String river;
+  private SelectItem[] mountains;
+  private String mountain;
+
+  public SelectOneListboxController() {
+    mountains = new SelectItem[]{
+            new SelectItem("8848 m", "Everest"),
+            new SelectItem("8611 m", "K2"),
+            new SelectItem("8586 m", "Kangchenjunga"),
+            new SelectItem("8516 m", "Lhotse"),
+            new SelectItem("8481 m", "Makalu")
+    };
+  }
+
+  public String getRiver() {
+    return river;
+  }
+
+  public void setRiver(String river) {
+    this.river = river;
+  }
+
+  public SelectItem[] getMountains() {
+    return mountains;
+  }
+
+  public String getMountain() {
+    return mountain;
+  }
+
+  public void setMountain(String mountain) {
+    this.mountain = mountain;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneRadioController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneRadioController.java
new file mode 100644
index 0000000..152e5cb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SelectOneRadioController.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class SelectOneRadioController extends PlanetExample implements Serializable {
+
+  private int numberOne;
+  private int numberTwo;
+  private int result;
+
+  public int getNumberOne() {
+    return numberOne;
+  }
+
+  public void setNumberOne(int numberOne) {
+    this.numberOne = numberOne;
+  }
+
+  public int getNumberTwo() {
+    return numberTwo;
+  }
+
+  public void setNumberTwo(int numberTwo) {
+    this.numberTwo = numberTwo;
+  }
+
+  public void add() {
+    result = numberOne + numberTwo;
+  }
+
+  public void subtract() {
+    result = numberOne - numberTwo;
+  }
+
+  public int getResult() {
+    return result;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ServerInfo.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ServerInfo.java
new file mode 100644
index 0000000..5930da9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ServerInfo.java
@@ -0,0 +1,126 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import javax.servlet.ServletContext;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+/**
+ * The server info class makes some information about the system and application available in the demo.
+ * This is enabled by default, but can be disabled by configuration in a properties file with the key
+ * <code>{@value #ENABLED_KEY}</code>.
+ * The default file name is <code>{@value #CONFIG_FILE_DEFAULT}</code>.
+ * The file name can be changed with a system property with name <code>{@value #CONFIG_FILE}</code>.
+ */
+@ApplicationScoped
+@Named("info")
+public class ServerInfo {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ServerInfo.class);
+
+  private static final String CONFIG_FILE = "org.apache.myfaces.tobago.example.demo.config.file";
+  private static final String CONFIG_FILE_DEFAULT = "/etc/tobago-example-demo.properties";
+  private static final String ENABLED_KEY = "server.info.enabled";
+
+  private String version;
+
+  /**
+   * Enabled the Server Info. May be disabled for security reasons. Default is true.
+   */
+  private boolean enabled = true;
+
+  public ServerInfo() {
+    String file = System.getProperty(CONFIG_FILE);
+    try {
+      if (file == null) {
+        file = CONFIG_FILE_DEFAULT;
+      }
+      LOG.info("Loading config from file '" + file + "'");
+      final Properties config = new Properties();
+      config.load(new FileInputStream(file));
+      enabled = Boolean.parseBoolean(config.getProperty(ENABLED_KEY));
+    } catch (final IOException e) {
+      LOG.warn("Can't load config: " + e.getMessage());
+    }
+    // the tobago version should be set in any case
+    LOG.info("server.info.enabled=" + enabled);
+    version = Package.getPackage("org.apache.myfaces.tobago.component").getImplementationVersion();
+  }
+
+  public String getServerInfo() {
+    if (enabled) {
+      return ((ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext()).getServerInfo();
+    } else {
+      return null;
+    }
+  }
+
+  public Properties getSystemProperties() {
+    return enabled ? System.getProperties() : null;
+  }
+
+  public List<Map.Entry<Object, Object>> getSystemPropertiesAsList() {
+    return enabled ? new ArrayList<Map.Entry<Object, Object>>(getSystemProperties().entrySet()) : null;
+  }
+
+  public String getVersion() {
+    return version;
+  }
+
+  public String getJsfTitle() {
+    return enabled ? FacesContext.class.getPackage().getImplementationTitle() : null;
+  }
+
+  public String getJsfVersion() {
+    return enabled ? FacesContext.class.getPackage().getImplementationVersion() : null;
+  }
+
+  public boolean isEnabled() {
+    return enabled;
+  }
+
+  public String getStableVersion() {
+    if (version.endsWith("-SNAPSHOT")) {
+      StringTokenizer tokenizer = new StringTokenizer(version, ".-");
+      int major = Integer.parseInt(tokenizer.nextToken());
+      int minor = Integer.parseInt(tokenizer.nextToken());
+      int fix = Integer.parseInt(tokenizer.nextToken());
+      if (fix == 0) {
+        return major + "." + (minor - 1) + ".0";
+      } else {
+        return major + "." + minor + "." + (fix - 1);
+      }
+    } else {
+      return version;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SeverityController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SeverityController.java
new file mode 100644
index 0000000..113f574
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SeverityController.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+
+@Named
+public class SeverityController {
+
+  public void addFatal(final FacesContext facesContext, final UIComponent component, final Object value) {
+    final FacesMessage message = new FacesMessage(
+        FacesMessage.SEVERITY_FATAL, "Custom fatal", "This is a custom fatal error");
+    facesContext.addMessage(component.getClientId(facesContext), message);
+  }
+
+  public void addError(final FacesContext facesContext, final UIComponent component, final Object value) {
+    final FacesMessage message = new FacesMessage(
+        FacesMessage.SEVERITY_ERROR, "Custom error", "This is a custom error");
+    facesContext.addMessage(component.getClientId(facesContext), message);
+  }
+
+  public void addWarn(final FacesContext facesContext, final UIComponent component, final Object value) {
+    final FacesMessage message = new FacesMessage(
+        FacesMessage.SEVERITY_WARN, "Custom warning", "This is a custom warning");
+    facesContext.addMessage(component.getClientId(facesContext), message);
+  }
+
+  public void addInfo(final FacesContext facesContext, final UIComponent component, final Object value) {
+    final FacesMessage message = new FacesMessage(
+        FacesMessage.SEVERITY_INFO, "Custom info", "This is a custom information");
+    facesContext.addMessage(component.getClientId(facesContext), message);
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetConfig.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetConfig.java
new file mode 100644
index 0000000..fa65a76
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetConfig.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.layout.ShowPosition;
+import org.apache.myfaces.tobago.model.Selectable;
+
+import javax.faces.model.SelectItem;
+import java.util.HashSet;
+import java.util.Set;
+
+public class SheetConfig {
+
+  private boolean sheetShowHeader;
+  private boolean showPagingAlways;
+  private int sheetFirst;
+  private int sheetRows;
+  private int sheetDirectLinkCount;
+  private ShowPosition sheetRowPagingPosition;
+  private ShowPosition sheetDirectPagingPosition;
+  private ShowPosition sheetPagePagingPosition;
+  private SelectItem[] sheetDirectLinkCountItems;
+  private SelectItem[] sheetPagingPositionItems;
+  private SelectItem[] sheetSelectableItems;
+  private Selectable selectable;
+  private boolean showDirectLinksArrows;
+  private boolean showPageRangeArrows;
+  private boolean sheetConfigPopup;
+
+  public SheetConfig() {
+    sheetFirst = 0;
+    sheetRows = 10;
+    sheetDirectLinkCount = 5;
+    sheetDirectLinkCountItems = createSheetItems(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
+    sheetShowHeader = true;
+    showPagingAlways = false;
+    sheetRowPagingPosition = ShowPosition.left;
+    sheetDirectPagingPosition = ShowPosition.center;
+    sheetPagePagingPosition = ShowPosition.right;
+    sheetPagingPositionItems = createSheetItems(ShowPosition.values());
+    final Set<Selectable> selectableSupportedBySheet = new HashSet<Selectable>();
+    for (Selectable selectable : Selectable.values()) {
+      if (selectable.isSupportedBySheet()) {
+        selectableSupportedBySheet.add(selectable);
+      }
+    }
+    sheetSelectableItems = createSheetItems(selectableSupportedBySheet.toArray());
+    selectable = Selectable.singleOrNone;
+    showDirectLinksArrows = false;
+    showPageRangeArrows = true;
+  }
+
+  public String configSheet() {
+    sheetConfigPopup = true;
+    return null;
+  }
+
+  private SelectItem[] createSheetItems(final Object[] values) {
+    final SelectItem[] items = new SelectItem[values.length];
+
+    for (int i = 0; i < values.length; i++) {
+      items[i] = new SelectItem(values[i], values[i].toString());
+    }
+    return items;
+  }
+
+
+  public boolean isSheetShowHeader() {
+    return sheetShowHeader;
+  }
+
+  public void setSheetShowHeader(final boolean sheetShowHeader) {
+    this.sheetShowHeader = sheetShowHeader;
+  }
+
+  public boolean isShowPagingAlways() {
+    return showPagingAlways;
+  }
+
+  public void setShowPagingAlways(final boolean showPagingAlways) {
+    this.showPagingAlways = showPagingAlways;
+  }
+
+  public int getSheetFirst() {
+    return sheetFirst;
+  }
+
+  public int getSheetRows() {
+    return sheetRows;
+  }
+
+  public void setSheetRows(final int sheetRows) {
+    this.sheetRows = sheetRows;
+  }
+
+  public int getSheetFirstValue() {
+    final int value = getSheetFirst();
+    return (value - 1) < 0 ? 0 : value - 1;
+  }
+
+  public void setSheetFirst(final int sheetFirst) {
+    this.sheetFirst = sheetFirst;
+  }
+
+  public boolean isSheetConfigPopup() {
+    return sheetConfigPopup;
+  }
+
+  public void setSheetConfigPopup(final boolean sheetConfigPopup) {
+    this.sheetConfigPopup = sheetConfigPopup;
+  }
+
+  public int getSheetDirectLinkCount() {
+    return sheetDirectLinkCount;
+  }
+
+  public void setSheetDirectLinkCount(final int sheetDirectLinkCount) {
+    this.sheetDirectLinkCount = sheetDirectLinkCount;
+  }
+
+  public SelectItem[] getSheetDirectLinkCountItems() {
+    return sheetDirectLinkCountItems;
+  }
+
+  public ShowPosition getSheetRowPagingPosition() {
+    return sheetRowPagingPosition;
+  }
+
+  public void setSheetRowPagingPosition(final ShowPosition sheetRowPagingPosition) {
+    this.sheetRowPagingPosition = sheetRowPagingPosition;
+  }
+
+  public ShowPosition getSheetDirectPagingPosition() {
+    return sheetDirectPagingPosition;
+  }
+
+  public void setSheetDirectPagingPosition(final ShowPosition sheetDirectPagingPosition) {
+    this.sheetDirectPagingPosition = sheetDirectPagingPosition;
+  }
+
+  public ShowPosition getSheetPagePagingPosition() {
+    return sheetPagePagingPosition;
+  }
+
+  public void setSheetPagePagingPosition(final ShowPosition sheetPagePagingPosition) {
+    this.sheetPagePagingPosition = sheetPagePagingPosition;
+  }
+
+  public SelectItem[] getSheetPagingPositionItems() {
+    return sheetPagingPositionItems;
+  }
+
+  public SelectItem[] getSheetSelectableItems() {
+    return sheetSelectableItems;
+  }
+
+  public void setSheetSelectableItems(final SelectItem[] sheetSelectableItems) {
+    this.sheetSelectableItems = sheetSelectableItems;
+  }
+
+  public Selectable getSelectable() {
+    return selectable;
+  }
+
+  public void setSelectable(final Selectable selectable) {
+    this.selectable = selectable;
+  }
+
+  public boolean isShowDirectLinksArrows() {
+    return showDirectLinksArrows;
+  }
+
+  public void setShowDirectLinksArrows(boolean showDirectLinksArrows) {
+    this.showDirectLinksArrows = showDirectLinksArrows;
+  }
+
+  public boolean isShowPageRangeArrows() {
+    return showPageRangeArrows;
+  }
+
+  public void setShowPageRangeArrows(boolean showPageRangeArrows) {
+    this.showPageRangeArrows = showPageRangeArrows;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetController.java
new file mode 100644
index 0000000..b5b39cf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetController.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.example.data.SolarObject;
+import org.apache.myfaces.tobago.model.SheetState;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIData;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.DateTimeConverter;
+import javax.faces.event.FacesEvent;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class SheetController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SheetController.class);
+
+  private List<SolarObject> solarList;
+  private List<SolarObject> hugeSolarList;
+  private SheetState sheetState;
+  private SolarObject selectedSolarObject;
+  private boolean automaticLayout;
+  private List<Markup> markup;
+  private int columnEventSample;
+
+  public SheetController() {
+    solarList = SolarObject.getList();
+
+    hugeSolarList = new ArrayList<SolarObject>();
+    for (int i = 1; i <= 12; i++) {
+      for (SolarObject solarObject : solarList) {
+        SolarObject solarObjectClone = new SolarObject(solarObject);
+        solarObjectClone.setName(solarObject.getName() + " (" + i + ". entry)");
+        hugeSolarList.add(solarObjectClone);
+      }
+    }
+  }
+
+  public List<SolarObject> getSolarList() {
+    return solarList;
+  }
+
+  public List<SolarObject> getHugeSolarList() {
+    return hugeSolarList;
+  }
+
+  public SheetState getSheetState() {
+    return sheetState;
+  }
+
+  public void setSheetState(SheetState sheetState) {
+    this.sheetState = sheetState;
+  }
+
+  public void selectSolarObject(final FacesEvent actionEvent) {
+    LOG.info("actionEvent=" + actionEvent);
+    final UIData data = ComponentUtils.findAncestor(actionEvent.getComponent(), UIData.class);
+    if (data != null) {
+      selectedSolarObject = (SolarObject) data.getRowData();
+      LOG.info("Selected: " + selectedSolarObject.getName());
+    } else {
+      selectedSolarObject = null;
+      LOG.info("Deselect.");
+    }
+  }
+
+  public SolarObject getSelectedSolarObject() {
+    return selectedSolarObject;
+  }
+
+  public int getNumberOfSelections() {
+    return sheetState.getSelectedRows().size();
+  }
+
+  public int getSelectedRowNumber() {
+    if (sheetState.getSelectedRows().size() <= 0) {
+      return -1;
+    } else {
+      return sheetState.getSelectedRows().get(0);
+    }
+  }
+
+  public boolean isAutomaticLayout() {
+    return automaticLayout;
+  }
+
+  public void setAutomaticLayout(boolean automaticLayout) {
+    this.automaticLayout = automaticLayout;
+  }
+
+  public List<Markup> getMarkup() {
+    return markup;
+  }
+
+  public void setMarkup(List<Markup> markup) {
+    this.markup = markup;
+  }
+
+  public void setColumnEventSample(int columnEventSample) {
+    this.columnEventSample = columnEventSample;
+  }
+
+  public int getColumnEventSample() {
+    return columnEventSample;
+  }
+
+  public javax.faces.convert.Converter getYearConverter() {
+
+    final DateTimeConverter dateTimeConverter = new DateTimeConverter() {
+
+      @Override
+      public Object getAsObject(FacesContext facesContext, UIComponent uiComponent, String value) {
+        final Date date = (Date) super.getAsObject(facesContext, uiComponent, value);
+        final Calendar calendar = GregorianCalendar.getInstance(facesContext.getViewRoot().getLocale());
+        calendar.setTime(date);
+        return calendar.get(Calendar.YEAR);
+      }
+
+      @Override
+      public String getAsString(FacesContext facesContext, UIComponent uiComponent, Object value) {
+        final Calendar calendar = GregorianCalendar.getInstance(facesContext.getViewRoot().getLocale());
+        calendar.set(Calendar.YEAR, (Integer) value);
+        final Date date = calendar.getTime();
+        return super.getAsString(facesContext, uiComponent, date);
+      }
+    };
+
+    dateTimeConverter.setPattern("yyyy");
+    return dateTimeConverter;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetFilterController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetFilterController.java
new file mode 100644
index 0000000..205798a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetFilterController.java
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.myfaces.tobago.example.data.SolarObject;
+import org.apache.myfaces.tobago.model.SelectItem;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+
+@RequestScoped
+@Named
+public class SheetFilterController extends SheetController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SheetFilterController.class);
+
+  private List<SolarObject> filteredSolarList = new ArrayList<SolarObject>();
+
+  private SelectItem[] distanceItems;
+  private SelectItem[] minYearItems;
+  private SelectItem[] maxYearItems;
+
+  private DistanceRangeConverter distanceRangeConverter;
+
+  private String name;
+  private String orbit;
+  private DistanceRange distance;
+  private String discoverer;
+  private Integer minYear;
+  private Integer maxYear;
+
+  private String nameSuggestionQuery;
+
+  public SheetFilterController() {
+    distanceItems = new SelectItem[]{
+        new SelectItem(new DistanceRange(-1, Integer.MAX_VALUE), "any"),
+        new SelectItem(new DistanceRange(-1, 10), "≤ 10"),
+        new SelectItem(new DistanceRange(10, 100), "10 < x ≤ 100"),
+        new SelectItem(new DistanceRange(100, 1000), "100 < x ≤ 1000"),
+        new SelectItem(new DistanceRange(1000, 10000), "1000 < x ≤ 10000"),
+        new SelectItem(new DistanceRange(10000, 100000), "10000 < x ≤ 100000"),
+        new SelectItem(new DistanceRange(100000, 1000000), "100000 < x ≤ 1000000"),
+        new SelectItem(new DistanceRange(1000000, Integer.MAX_VALUE), "1000000 < x")
+    };
+
+    Set<Integer> years = new TreeSet<Integer>();
+    for (SolarObject solarObject : getSolarList()) {
+      if (solarObject.getDiscoverYear() != null) {
+        years.add(solarObject.getDiscoverYear());
+      }
+    }
+    minYearItems = new SelectItem[years.size() + 1];
+    maxYearItems = new SelectItem[years.size() + 1];
+    minYearItems[0] = new SelectItem(0, "min");
+    maxYearItems[0] = new SelectItem(Integer.MAX_VALUE, "max");
+    int i = 1;
+    for (Integer year : years) {
+      SelectItem selectItem = new SelectItem(year, String.valueOf(year));
+
+      minYearItems[i] = selectItem;
+      maxYearItems[i] = selectItem;
+
+      i++;
+    }
+
+    distanceRangeConverter = new DistanceRangeConverter();
+
+    filter();
+  }
+
+  public String filter() {
+    filteredSolarList.clear();
+    if (name == null) {
+      name = "";
+    }
+    if (orbit == null) {
+      orbit = "";
+    }
+    if (distance == null) {
+      distance = (DistanceRange) distanceItems[0].getValue();
+    }
+    if (discoverer == null) {
+      discoverer = "";
+    }
+    if (minYear == null) {
+      minYear = 0;
+    }
+    if (maxYear == null) {
+      maxYear = Integer.MAX_VALUE;
+    }
+    for (final SolarObject solarObject : getSolarList()) {
+      int discoverYear = 0;
+      if (solarObject.getDiscoverYear() != null) {
+        discoverYear = solarObject.getDiscoverYear();
+      }
+      if (StringUtils.containsIgnoreCase(solarObject.getName(), name)
+          && StringUtils.containsIgnoreCase(solarObject.getOrbit(), orbit)
+          && distance.getMin() < solarObject.getDistance() && solarObject.getDistance() <= distance.getMax()
+          && StringUtils.containsIgnoreCase(solarObject.getDiscoverer(), discoverer)
+          && minYear <= discoverYear && discoverYear <= maxYear) {
+        filteredSolarList.add(solarObject);
+      }
+    }
+    return null;
+  }
+
+  public void filter(AjaxBehaviorEvent event) {
+    filter();
+  }
+
+  public List<SolarObject> getFilteredSolarList() {
+    return filteredSolarList;
+  }
+
+  public SelectItem[] getDistanceItems() {
+    return distanceItems;
+  }
+
+  public SelectItem[] getMinYearItems() {
+    return minYearItems;
+  }
+
+  public SelectItem[] getMaxYearItems() {
+    return maxYearItems;
+  }
+
+  public DistanceRangeConverter getDistanceRangeConverter() {
+    return distanceRangeConverter;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getOrbit() {
+    return orbit;
+  }
+
+  public void setOrbit(String orbit) {
+    this.orbit = orbit;
+  }
+
+  public DistanceRange getDistance() {
+    return distance;
+  }
+
+  public void setDistance(DistanceRange distance) {
+    this.distance = distance;
+  }
+
+  public String getDiscoverer() {
+    return discoverer;
+  }
+
+  public void setDiscoverer(String discoverer) {
+    this.discoverer = discoverer;
+  }
+
+  public Integer getMinYear() {
+    return minYear;
+  }
+
+  public void setMinYear(Integer minYear) {
+    this.minYear = minYear;
+  }
+
+  public Integer getMaxYear() {
+    return maxYear;
+  }
+
+  public void setMaxYear(Integer maxYear) {
+    this.maxYear = maxYear;
+  }
+
+  public String getNameSuggestionQuery() {
+    return nameSuggestionQuery;
+  }
+
+  public void setNameSuggestionQuery(String nameSuggestionQuery) {
+    this.nameSuggestionQuery = nameSuggestionQuery;
+  }
+
+  public List<String> getSuggestionSolarList() {
+    final String substring = nameSuggestionQuery != null ? nameSuggestionQuery : "";
+    LOG.info("Creating items for substring: '" + substring + "'");
+    final List<String> result = new ArrayList<String>();
+    for (final SolarObject solarObject : getSolarList()) {
+      String name = solarObject.getName();
+      if (StringUtils.containsIgnoreCase(name, substring)) {
+        result.add(name);
+      }
+    }
+    return result;
+  }
+
+  private class DistanceRange {
+
+    private int min;
+    private int max;
+    private final String label;
+
+    public DistanceRange(int min, int max) {
+      this.min = min;
+      this.max = max;
+      label = String.valueOf(min) + " < x ≤ " + String.valueOf(max);
+    }
+
+    public DistanceRange(int min, int max, String label) {
+      this.min = min;
+      this.max = max;
+      this.label = label;
+    }
+
+    public int getMin() {
+      return min;
+    }
+
+    public int getMax() {
+      return max;
+    }
+
+    public String getLabel() {
+      return label;
+    }
+
+    @Override
+    public boolean equals(final Object object) {
+      if (this == object) {
+        return true;
+      }
+      if (object == null || getClass() != object.getClass()) {
+        return false;
+      }
+      final DistanceRange that = (DistanceRange) object;
+      return max == that.max && min == that.min;
+    }
+
+    @Override
+    public int hashCode() {
+      return 31 * min + max;
+    }
+  }
+
+  public class DistanceRangeConverter implements Converter {
+    @Override
+    public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
+        throws ConverterException {
+      try {
+        for (SelectItem distanceItem : distanceItems) {
+          if (distanceItem.getLabel().equals(value)) {
+            return distanceItem.getValue();
+          }
+        }
+        return distanceItems[0].getValue();
+      } catch (RuntimeException e) {
+        LOG.warn("unknown value='" + value + "'", e);
+        return distanceItems[0].getValue();
+      }
+    }
+
+    @Override
+    public String getAsString(
+        final FacesContext context, final UIComponent component, final Object value) throws ConverterException {
+      if (value instanceof DistanceRange) {
+        for (SelectItem distanceItem : distanceItems) {
+          if (distanceItem.getValue().equals(value)) {
+            return distanceItem.getLabel();
+          }
+        }
+      }
+      return distanceItems[0].getLabel();
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetSortingController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetSortingController.java
new file mode 100644
index 0000000..92132cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetSortingController.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.component.UISheet;
+import org.apache.myfaces.tobago.event.SortActionEvent;
+import org.apache.myfaces.tobago.example.data.SolarObject;
+import org.apache.myfaces.tobago.model.SheetState;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ActionEvent;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class SheetSortingController extends SheetController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SheetSortingController.class);
+
+  public void sheetSorter(final ActionEvent event) {
+    if (event instanceof SortActionEvent) {
+      final SortActionEvent sortEvent = (SortActionEvent) event;
+      final UISheet sheet = (UISheet) sortEvent.getComponent();
+      final SheetState sheetState = sheet.getSheetState(FacesContext.getCurrentInstance());
+      final List<SolarObject> list = (List<SolarObject>) sheet.getValue();
+      sheetSorter(sheetState, list);
+    }
+  }
+
+  private void sheetSorter(final SheetState sheetState, final List<SolarObject> list) {
+    final String columnId = sheetState.getSortedColumnId();
+
+    LOG.info("Sorting column '{}'", columnId);
+
+    Comparator<SolarObject> comparator = null;
+
+    if ("customColumnName".equals(columnId)) {
+      comparator = new Comparator<SolarObject>() {
+        @Override
+        public int compare(final SolarObject o1, final SolarObject o2) {
+          return o1.getName().compareToIgnoreCase(o2.getName());
+        }
+      };
+    } else if ("customColumnPeriod".equals(columnId)) {
+      comparator = new Comparator<SolarObject>() {
+        @Override
+        public int compare(final SolarObject o1, final SolarObject o2) {
+          Double period1 = Math.abs(o1.getPeriod());
+          Double period2 = Math.abs(o2.getPeriod());
+          return period1.compareTo(period2);
+        }
+      };
+    } else if ("customColumnYear".equals(columnId)) {
+      comparator = new Comparator<SolarObject>() {
+        @Override
+        public int compare(final SolarObject o1, final SolarObject o2) {
+          Integer discoverYear1 = o1.getDiscoverYear() != null ? o1.getDiscoverYear() : 0;
+          Integer discoverYear2 = o2.getDiscoverYear() != null ? o2.getDiscoverYear() : 0;
+          return discoverYear1.compareTo(discoverYear2);
+        }
+      };
+    }
+
+    Collections.sort(list, comparator);
+    if (!sheetState.isAscending()) {
+      Collections.reverse(list);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetTreeController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetTreeController.java
new file mode 100644
index 0000000..1f79ecf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SheetTreeController.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.example.data.SolarObject;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class SheetTreeController implements Serializable {
+
+  private DefaultMutableTreeNode solarTree;
+
+  public SheetTreeController() {
+    solarTree = SolarObject.getTree();
+  }
+
+  public DefaultMutableTreeNode getSolarTree() {
+    return solarTree;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SolarConverter.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SolarConverter.java
new file mode 100644
index 0000000..dab5794
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SolarConverter.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.example.data.SolarObject;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.convert.Converter;
+import javax.faces.convert.ConverterException;
+import javax.faces.convert.FacesConverter;
+
+@FacesConverter(forClass = SolarObject.class)
+public class SolarConverter implements Converter {
+
+  @Override
+  public Object getAsObject(final FacesContext context, final UIComponent component, final String value)
+      throws ConverterException {
+    return SolarObject.find(value);
+  }
+
+  @Override
+  public String getAsString(final FacesContext context, final UIComponent component, final Object value)
+      throws ConverterException {
+    return ((SolarObject) value).getName();
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SourceFileReader.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SourceFileReader.java
new file mode 100644
index 0000000..20114dc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SourceFileReader.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.io.InputStream;
+
+public abstract class SourceFileReader {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SourceFileReader.class);
+
+  public String getSource(String filename) {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    final String viewId = facesContext.getViewRoot().getViewId();
+    final String file = viewId.substring(0, viewId.lastIndexOf("/")) + "/" + filename;
+    InputStream resourceAsStream = null;
+    try {
+      resourceAsStream = externalContext.getResourceAsStream(file);
+      return IOUtils.toString(resourceAsStream, "UTF-8");
+    } catch (final IOException e) {
+      LOG.error("", e);
+      return "error";
+    } finally {
+      IOUtils.closeQuietly(resourceAsStream);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SuggestController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SuggestController.java
new file mode 100644
index 0000000..7bc1c5f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SuggestController.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.myfaces.tobago.example.data.LocaleList;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.component.UIInput;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class SuggestController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SuggestController.class);
+  private String query;
+
+  public String getQuery() {
+    return query;
+  }
+
+  public void setQuery(String query) {
+    this.query = query;
+  }
+
+  public List<String> getLanguages() {
+    final String substring = query != null ? query : "";
+    LOG.info("Creating items for substring: '" + substring + "'");
+    final List<String> result = new ArrayList<String>(LocaleList.COUNTRY_LANGUAGE.size());
+    for (final String name : LocaleList.COUNTRY_LANGUAGE) {
+      if (StringUtils.containsIgnoreCase(name, substring)) {
+        result.add(name);
+      }
+    }
+    return result;
+  }
+
+  public List<String> getAllLanguages() {
+    return LocaleList.COUNTRY_LANGUAGE;
+  }
+
+  /*
+   * use <tc:selectItems/> instead
+   */
+  @Deprecated
+  public List<String> getInputSuggestItems(final UIInput component) {
+    String substring = (String) component.getSubmittedValue();
+    if (substring == null) {
+      substring = "";
+    }
+    LOG.info("Creating items for substring: '" + substring + "'");
+    final List<String> result = new ArrayList<String>();
+    for (final String name : LocaleList.COUNTRY_LANGUAGE) {
+      if (StringUtils.containsIgnoreCase(name, substring)) {
+        result.add(name);
+      }
+      if (result.size() > 100) { // this value should not be smaller than the value of the suggest control
+        break;
+      }
+    }
+    return result;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SynchronizeNavigationPhaseListener.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SynchronizeNavigationPhaseListener.java
new file mode 100644
index 0000000..d827826
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/SynchronizeNavigationPhaseListener.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.util.VariableResolverUtils;
+
+import javax.faces.component.UIViewRoot;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+//todo @JsfPhaseListener
+public class SynchronizeNavigationPhaseListener implements PhaseListener {
+
+  @Override
+  public void beforePhase(final PhaseEvent event) {
+    if (PhaseId.RENDER_RESPONSE.equals(event.getPhaseId())) {
+      synchronizeState();
+    }
+  }
+
+  @Override
+  public void afterPhase(final PhaseEvent event) {
+    if (PhaseId.RESTORE_VIEW.equals(event.getPhaseId())) {
+      synchronizeState();
+    }
+  }
+
+  @Override
+  public PhaseId getPhaseId() {
+    return PhaseId.ANY_PHASE;
+  }
+
+  private void synchronizeState() {
+    // synchronizing current site with
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final UIViewRoot viewRoot = facesContext.getViewRoot();
+    // in case of direct links the ViewRoot is empty after "restore view".
+    if (viewRoot != null && viewRoot.getChildCount() == 0) {
+      final String viewId = viewRoot.getViewId();
+      final NavigationTree navigation
+          = (NavigationTree) VariableResolverUtils.resolveVariable(facesContext, "navigationTree");
+      navigation.gotoNode(navigation.findByViewId(viewId));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TabController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TabController.java
new file mode 100644
index 0000000..55695d3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TabController.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.event.TabChangeListener;
+import org.apache.myfaces.tobago.example.demo.actionlistener.SimpleTabChangeListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class TabController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TabController.class);
+
+  private String open = "/image/feather-open.png";
+  private String close = "/image/feather.png";
+  private int index;
+  private SimpleTabChangeListener tabChangeListener;
+
+  public int getIndex() {
+    return index;
+  }
+
+  public void setIndex(int index) {
+    this.index = index;
+  }
+
+  public String getTabOneImage() {
+    if (index != 0) {
+      return close;
+    } else {
+      return open;
+    }
+  }
+
+  public String getTabTwoImage() {
+    if (index != 1) {
+      return close;
+    } else {
+      return open;
+    }
+  }
+
+  public String getTabThreeImage() {
+    if (index != 2) {
+      return close;
+    } else {
+      return open;
+    }
+  }
+
+  public TabChangeListener getTabChangeListener() {
+    return tabChangeListener;
+  }
+
+  public void setTabChangeListener(final SimpleTabChangeListener tabChangeListener) {
+    this.tabChangeListener = tabChangeListener;
+  }
+
+  public int getCount() {
+    return tabChangeListener.getCount();
+  }
+
+  public int getNewTabIndex() {
+    return tabChangeListener.getNewTabIndex();
+  }
+
+  public int getOldTabIndex() {
+    return tabChangeListener.getOldTabIndex();
+  }
+
+  public String getClientId() {
+    return tabChangeListener.getClientId();
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestController.java
new file mode 100644
index 0000000..65d30b1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestController.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.context.ExternalContext;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.net.MalformedURLException;
+
+@RequestScoped
+@Named
+public class TestController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TestController.class);
+
+  public String getTestBase() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final ExternalContext externalContext = facesContext.getExternalContext();
+    final String viewId = facesContext.getViewRoot().getViewId();
+    final String base = viewId.substring(0, viewId.length() - 6);
+    try {
+      if (externalContext.getResource(base + ".test.js") != null) {
+        return base;
+      }
+    } catch (MalformedURLException e) {
+      LOG.error("viewId='" + viewId + "'", e);
+    }
+
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestExceptionHandler.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestExceptionHandler.java
new file mode 100644
index 0000000..9453c06
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestExceptionHandler.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.faces.FacesException;
+import javax.faces.application.FacesMessage;
+import javax.faces.application.NavigationHandler;
+import javax.faces.application.ViewExpiredException;
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerWrapper;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ExceptionQueuedEvent;
+import javax.faces.event.ExceptionQueuedEventContext;
+import java.util.Iterator;
+
+public class TestExceptionHandler extends ExceptionHandlerWrapper {
+
+  private ExceptionHandler wrapped;
+
+  public TestExceptionHandler(final ExceptionHandler wrapped) {
+    this.wrapped = wrapped;
+  }
+
+  @Override
+  public ExceptionHandler getWrapped() {
+    return wrapped;
+  }
+
+  @Override
+  public void handle() throws FacesException {
+
+    final Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents().iterator();
+    while (iterator.hasNext()) {
+      final ExceptionQueuedEvent event = iterator.next();
+      final ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
+      final Throwable cause = context.getException();
+
+      if (cause instanceof ViewExpiredException) {
+        final FacesContext facesContext = FacesContext.getCurrentInstance();
+        final NavigationHandler nav = facesContext.getApplication().getNavigationHandler();
+        try {
+          facesContext.addMessage(null, new FacesMessage("The view has been expired!"));
+
+          /*
+           * TODO analyse the '/faces'-prefix
+           * actually the viewID should be enough, but if you do so, the FacesMessage won't be shown.
+           */
+          nav.handleNavigation(facesContext, null, "/faces" + ((ViewExpiredException) cause).getViewId());
+          facesContext.renderResponse();
+        } finally {
+          iterator.remove();
+        }
+      }
+    }
+    getWrapped().handle();
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestExceptionHandlerFactory.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestExceptionHandlerFactory.java
new file mode 100644
index 0000000..a6cb346
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TestExceptionHandlerFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerFactory;
+
+public class TestExceptionHandlerFactory extends ExceptionHandlerFactory {
+
+  private ExceptionHandlerFactory parent;
+
+  public TestExceptionHandlerFactory(final ExceptionHandlerFactory parent) {
+    this.parent = parent;
+  }
+
+  @Override
+  public ExceptionHandler getExceptionHandler() {
+    ExceptionHandler result = parent.getExceptionHandler();
+    result = new TestExceptionHandler(result);
+    return result;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TextareaController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TextareaController.java
new file mode 100644
index 0000000..f878ec5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TextareaController.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class TextareaController implements Serializable {
+
+  private String longText;
+
+  public TextareaController() {
+    longText = "The goal of Apache Tobago™ is to provide the community with a well designed set of user interface "
+        + "components based on JSF and run on MyFaces.\n\n"
+        + "Tobago is more than just a tag library. The following statements characterize Tobago and make it "
+        + "different from other frameworks:\n"
+        + "- The focus of Tobago is to create business applications without the need for HTML design. "
+        + "The development of Tobago pages follows more the development of conventional user interfaces "
+        + "than the creation of web pages.\n"
+        + "- The UI components are abstracted from HTML and any layout information that does not belong to the "
+        + "general page structure. The final output format is determined by the client/user-agent.\n"
+        + "- A theming mechanism makes it easy to change the look and feel and to provide special implementations for "
+        + "certain browsers. A  fallback solution ensures that as much code is reused for new themes as possible.\n"
+        + "- A layout manager is used to arrange the components automatically. This means, no manual laying out with "
+        + "HTML tables or other constructs is needed.\n"
+        + "\n"
+        + "The development of Tobago started in 2002.";
+  }
+
+  public String getLongText() {
+    return longText;
+  }
+
+  public void setLongText(String longText) {
+    this.longText = longText;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ThemeController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ThemeController.java
new file mode 100644
index 0000000..348d968
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ThemeController.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.TobagoContext;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class ThemeController implements Serializable {
+
+  private Theme theme;
+  private SelectItem[] themeItems;
+
+  public ThemeController() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(facesContext);
+    final List<Theme> themes = new ArrayList<Theme>(tobagoConfig.getSupportedThemes());
+    themes.add(0, tobagoConfig.getDefaultTheme());
+    themeItems = new SelectItem[themes.size()];
+    for (int i = 0; i < themeItems.length; i++) {
+      final Theme themeItem = themes.get(i);
+      themeItems[i] = new SelectItem(themeItem, themeItem.getDisplayName());
+    }
+  }
+
+  public Theme getTheme() {
+    return theme;
+  }
+
+  public void setTheme(Theme theme) {
+    this.theme = theme;
+  }
+
+  public SelectItem[] getThemeItems() {
+    return themeItems;
+  }
+
+  public void setThemeItems(SelectItem[] themeItems) {
+    this.themeItems = themeItems;
+  }
+
+  public String submit() {
+    final TobagoContext tobagoContext = TobagoContext.getInstance(FacesContext.getCurrentInstance());
+    tobagoContext.setTheme(theme);
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TinyMceController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TinyMceController.java
new file mode 100644
index 0000000..3a86b92
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TinyMceController.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class TinyMceController extends SourceFileReader implements Serializable {
+
+  private String text;
+
+  public TinyMceController() {
+    text = "<h1>Sonne</h1>"
+        + "<p>Die Sonne ist ein Stern in der Galaxie Milchstraße.</p>";
+  }
+
+  public String getText() {
+    return text;
+  }
+
+  public void setText(String text) {
+    this.text = text;
+  }
+
+  public String getSource() {
+    return getSource("tinymce.js");
+  }
+
+  public boolean isEditorAvailable() {
+    return !"error".equals(getSource("tinymce/js/tinymce/tinymce.min.js"));
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeCommandTypesController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeCommandTypesController.java
new file mode 100644
index 0000000..432b1f7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeCommandTypesController.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.example.data.CommandNode;
+import org.apache.myfaces.tobago.example.data.CommandNodeFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class TreeCommandTypesController implements Serializable {
+
+  private CommandNode sample;
+  private int actionOneCount = 0;
+  private int actionTwoCount = 0;
+
+  public TreeCommandTypesController() {
+    sample = CommandNodeFactory.createSample();
+  }
+
+  public CommandNode getSample() {
+    return sample;
+  }
+
+  public int getActionOneCount() {
+    return actionOneCount;
+  }
+
+  public void increaseActionCount(String name) {
+    if ("ActionOne".equals(name)) {
+      actionOneCount++;
+    } else if ("ActionTwo".equals(name)) {
+      actionTwoCount++;
+    }
+  }
+
+  public int getActionTwoCount() {
+    return actionTwoCount;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeController.java
new file mode 100644
index 0000000..c72de9a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeController.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.example.data.CategoryTree;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class TreeController implements Serializable {
+
+  private DefaultMutableTreeNode sample;
+  private boolean treeShowRoot = false;
+  private boolean treeShowRootJunction = false;
+  private boolean treeIndentRendered = true;
+  private boolean treeIndentShowJunction = true;
+
+  public TreeController() {
+    sample = CategoryTree.createSample();
+  }
+
+  public DefaultMutableTreeNode getSample() {
+    return sample;
+  }
+
+  public boolean isTreeShowRoot() {
+    return treeShowRoot;
+  }
+
+  public void setTreeShowRoot(boolean treeShowRoot) {
+    this.treeShowRoot = treeShowRoot;
+  }
+
+  public boolean isTreeShowRootJunction() {
+    return treeShowRootJunction;
+  }
+
+  public void setTreeShowRootJunction(boolean treeShowRootJunction) {
+    this.treeShowRootJunction = treeShowRootJunction;
+  }
+
+  public boolean isTreeIndentRendered() {
+    return treeIndentRendered;
+  }
+
+  public void setTreeIndentRendered(boolean treeIndentRendered) {
+    this.treeIndentRendered = treeIndentRendered;
+  }
+
+  public boolean isTreeIndentShowJunction() {
+    return treeIndentShowJunction;
+  }
+
+  public void setTreeIndentShowJunction(boolean treeIndentShowJunction) {
+    this.treeIndentShowJunction = treeIndentShowJunction;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeEditorController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeEditorController.java
new file mode 100644
index 0000000..9fcf8a8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeEditorController.java
@@ -0,0 +1,217 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.example.data.CategoryTree;
+import org.apache.myfaces.tobago.example.data.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.io.Serializable;
+import java.util.Enumeration;
+
+@SessionScoped
+@Named
+public class TreeEditorController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TreeEditorController.class);
+
+  private DefaultMutableTreeNode categoryTree;
+  private String name;
+  private DefaultMutableTreeNode copyNode;
+  private DefaultMutableTreeNode cutNode;
+
+
+  public TreeEditorController() {
+    this.categoryTree = CategoryTree.createSample();
+  }
+
+  public DefaultMutableTreeNode getCategoryTree() {
+    return categoryTree;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String create() {
+    final DefaultMutableTreeNode node = findFirstSelected();
+    if (node != null) {
+      node.insert(CategoryTree.createNode(name, "id" + System.identityHashCode(name)), 0);
+      LOG.debug("Creating one node in {}", node.getUserObject());
+    } else {
+      LOG.warn("No node selected.");
+    }
+    return null;
+  }
+
+  public String delete() {
+    final DefaultMutableTreeNode node = findFirstSelected();
+    if (node != null) {
+      if (node.getParent() != null) {
+        node.removeFromParent();
+      } else {
+        FacesContext.getCurrentInstance().addMessage(null,
+                new FacesMessage(FacesMessage.SEVERITY_INFO, "Root node cannot be removed", null));
+      }
+    } else {
+      LOG.warn("No node selected.");
+    }
+    return null;
+  }
+
+  public String rename() {
+    final DefaultMutableTreeNode node = findFirstSelected();
+    if (node != null && node.getUserObject() instanceof Node) {
+      final Node userObject = (Node) node.getUserObject();
+      LOG.debug("Renaming node from {} to {}", userObject.getName(), name);
+      userObject.setName(name);
+    } else {
+      LOG.warn("No node selected.");
+    }
+    return null;
+  }
+
+  public String cut() {
+    copyNode = null;
+    cutNode = findFirstSelected();
+    return null;
+  }
+
+  public String copy() {
+    cutNode = null;
+    copyNode = cloneNode(findFirstSelected());
+    return null;
+  }
+
+  private DefaultMutableTreeNode cloneNode(DefaultMutableTreeNode node) {
+    String nodeName = ((Node) node.getUserObject()).getName();
+    DefaultMutableTreeNode resultNode = new DefaultMutableTreeNode(new Node(nodeName));
+
+    Enumeration children = node.children();
+    while (children.hasMoreElements()) {
+      final DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
+      resultNode.insert(cloneNode(child), resultNode.getChildCount());
+    }
+
+    return resultNode;
+  }
+
+  public String paste() {
+    final DefaultMutableTreeNode node = findFirstSelected();
+    if (cutNode != null) {
+      if (isBaseNodeContainSelectedNode(cutNode, node)) {
+        FacesContext.getCurrentInstance().addMessage(null,
+                new FacesMessage(FacesMessage.SEVERITY_INFO, "Cannot past a cut node into itself.", null));
+      } else {
+        node.insert(cutNode, 0);
+        cutNode = null;
+      }
+    } else if (copyNode != null) {
+      node.insert(copyNode, 0);
+      copyNode = null;
+      deselectAllNodes(categoryTree);
+    }
+    return null;
+  }
+
+  private boolean isBaseNodeContainSelectedNode(DefaultMutableTreeNode base, DefaultMutableTreeNode selected) {
+    if (base.equals(selected)) {
+      return true;
+    }
+    Enumeration children = base.children();
+    while (children.hasMoreElements()) {
+      final DefaultMutableTreeNode baseChild = (DefaultMutableTreeNode) children.nextElement();
+
+      if (isBaseNodeContainSelectedNode(baseChild, selected)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  private void deselectAllNodes(DefaultMutableTreeNode node) {
+    ((Node) node.getUserObject()).setSelected(false);
+
+    Enumeration children = node.children();
+    while (children.hasMoreElements()) {
+      final DefaultMutableTreeNode child = (DefaultMutableTreeNode) children.nextElement();
+      deselectAllNodes(child);
+    }
+  }
+
+  public String moveUp() {
+    final DefaultMutableTreeNode node = findFirstSelected();
+    if (node != null) {
+      DefaultMutableTreeNode previousSibling = node.getPreviousSibling();
+      if (previousSibling != null) {
+        DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
+        parent.insert(node, parent.getIndex(previousSibling));
+      } else {
+        FacesContext.getCurrentInstance().addMessage(null,
+                new FacesMessage(FacesMessage.SEVERITY_INFO, "The node cannot moved up further.", null));
+      }
+    }
+    return null;
+  }
+
+  public String moveDown() {
+    final DefaultMutableTreeNode node = findFirstSelected();
+    if (node != null) {
+      DefaultMutableTreeNode nextSibling = node.getNextSibling();
+      if (nextSibling != null) {
+        DefaultMutableTreeNode parent = (DefaultMutableTreeNode) node.getParent();
+        parent.insert(node, parent.getIndex(nextSibling));
+      } else {
+        FacesContext.getCurrentInstance().addMessage(null,
+                new FacesMessage(FacesMessage.SEVERITY_INFO, "The node cannot moved down further.", null));
+      }
+    }
+    return null;
+  }
+
+  public String reset() {
+    categoryTree = CategoryTree.createSample();
+    cutNode = null;
+    copyNode = null;
+    return null;
+  }
+
+  private DefaultMutableTreeNode findFirstSelected() {
+    final Enumeration enumeration = categoryTree.depthFirstEnumeration();
+    while (enumeration.hasMoreElements()) {
+      final DefaultMutableTreeNode node = (DefaultMutableTreeNode) enumeration.nextElement();
+      if (((Node) node.getUserObject()).isSelected()) {
+        return node;
+      }
+    }
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeSelectController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeSelectController.java
new file mode 100644
index 0000000..40dd440
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/TreeSelectController.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.example.data.CategoryTree;
+import org.apache.myfaces.tobago.example.data.Node;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.io.Serializable;
+
+@SessionScoped
+@Named
+public class TreeSelectController implements Serializable {
+
+  private DefaultMutableTreeNode sample;
+  private String selectable = "multi";
+
+  public TreeSelectController() {
+    sample = CategoryTree.createSample();
+  }
+
+  public DefaultMutableTreeNode getSample() {
+    return sample;
+  }
+
+  public String getSelectable() {
+    return selectable;
+  }
+
+  public void setSelectable(String selectable) {
+    this.selectable = selectable;
+    resetSelection(sample);
+  }
+
+  public void resetSelection(DefaultMutableTreeNode node) {
+    Node userObject = (Node) node.getUserObject();
+    userObject.setSelected(false);
+    for (int i = 0; i < node.getChildCount(); i++) {
+      DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
+      resetSelection(child);
+    }
+  }
+
+  public String getSelectedNodes() {
+    StringBuilder stringBuilder = new StringBuilder();
+    buildSelectedNodesString(stringBuilder, sample);
+    if (stringBuilder.length() > 2) {
+      return stringBuilder.substring(2); // Remove ', '.
+    } else {
+      return "";
+    }
+  }
+
+  private void buildSelectedNodesString(StringBuilder stringBuilder, DefaultMutableTreeNode node) {
+    Node userObject = (Node) node.getUserObject();
+    if (userObject.isSelected()) {
+      stringBuilder.append(", " + userObject.getName());
+    }
+    for (int i = 0; i < node.getChildCount(); i++) {
+      DefaultMutableTreeNode child = (DefaultMutableTreeNode) node.getChildAt(i);
+      buildSelectedNodesString(stringBuilder, child);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UniversalLoggingInfo.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UniversalLoggingInfo.java
new file mode 100644
index 0000000..6a03120
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UniversalLoggingInfo.java
@@ -0,0 +1,253 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+import java.io.PrintStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+/**
+ * Provides the possibility to get information about various logging APIs available in the current setup.
+ */
+@Named
+@ApplicationScoped
+public class UniversalLoggingInfo {
+
+  private static final PrintStream LOG = System.err;
+
+  public static final String JUL = "JUL";
+  public static final String SLF4J = "SLF4J";
+  public static final String LOG4J = "LOG4J";
+  public static final String LOG4J2 = "LOG4J2";
+  public static final String JCL = "JCL";
+
+  /**
+   * should always be available, because it's part of Java since 1.4
+   */
+  private LoggingInfo jul;
+
+  /**
+   * should always be true, because it's used by Tobago
+   */
+  private LoggingInfo slf4j;
+
+  private LoggingInfo log4j;
+
+  private LoggingInfo log4j2;
+
+  private LoggingInfo commonsLogging;
+
+  private String testCategory = UniversalLoggingInfo.class.getName();
+
+  public UniversalLoggingInfo() {
+    jul = new LoggingInfo(JUL, "java.util.logging.Logger", "getLogger", testCategory, true,
+        "finest",
+        "finer",
+        "fine",
+        "config",
+        "info",
+        "warning",
+        "severe");
+    slf4j = new LoggingInfo(SLF4J, "org.slf4j.LoggerFactory", "getLogger", testCategory, true,
+        "trace",
+        "debug",
+        "info",
+        "warn",
+        "error");
+    log4j = new LoggingInfo(LOG4J, "org.apache.log4j.Logger", "getLogger", testCategory, false,
+        "trace",
+        "debug",
+        "info",
+        "warn",
+        "error",
+        "fatal");
+    log4j2 = new LoggingInfo(LOG4J2, "org.apache.logging.log4j.LogManager", "getLogger", testCategory, false,
+        "trace",
+        "debug",
+        "info",
+        "warn",
+        "error",
+        "fatal");
+    commonsLogging = new LoggingInfo(JCL, "org.apache.commons.logging.LogFactory", "getLog", testCategory, false,
+        "trace",
+        "debug",
+        "info",
+        "warn",
+        "error",
+        "fatal");
+    update();
+  }
+
+  public String update() {
+    jul.reset(testCategory);
+    slf4j.reset(testCategory);
+    log4j.reset(testCategory);
+    log4j2.reset(testCategory);
+    commonsLogging.reset(testCategory);
+    return null;
+  }
+
+  public LoggingInfo getJul() {
+    return jul;
+  }
+
+  public LoggingInfo getSlf4j() {
+    return slf4j;
+  }
+
+  public LoggingInfo getLog4j() {
+    return log4j;
+  }
+
+  public LoggingInfo getLog4j2() {
+    return log4j2;
+  }
+
+  public LoggingInfo getCommonsLogging() {
+    return commonsLogging;
+  }
+
+  public String getTestCategory() {
+    return testCategory;
+  }
+
+  public void setTestCategory(String testCategory) {
+    if (testCategory != null) {
+      this.testCategory = testCategory;
+    } else {
+      this.testCategory = "";
+    }
+  }
+
+  public static class LoggingInfo {
+
+    private String id;
+    private Object logger;
+    private String[] calls;
+    private String activeLevels = "n/a";
+    private String factoryClassName;
+    private String factoryMethod;
+    private boolean usesString; // is false it uses "Object" for logging
+
+    public LoggingInfo(String id, String factoryClassName, String factoryMethod,
+                       String category, boolean usesString, String... calls) {
+      this.id = id;
+      this.calls = calls;
+      this.factoryClassName = factoryClassName;
+      this.factoryMethod = factoryMethod;
+      this.usesString = usesString;
+      reset(category);
+    }
+
+    public void logDemo() {
+      for (String call : calls) {
+        try {
+          invoke(id, logger, call);
+        } catch (Exception e) {
+          LOG.println("Ignoring: " + e);
+        }
+      }
+    }
+
+    private void invoke(String id, Object logger, String name) throws Exception {
+      final Class clazz = usesString ? String.class : Object.class;
+      final Method method = logger.getClass().getMethod(name, clazz);
+      method.invoke(logger, "Hello " + id + ", this is the level: " + name);
+    }
+
+    public boolean isAvailable() {
+      return logger != null;
+    }
+
+    public String getActiveLevels() {
+      return activeLevels;
+    }
+
+    protected void reset(String category) {
+
+      logger = null;
+
+      try {
+        final Method method = Class.forName(factoryClassName).getMethod(factoryMethod, String.class);
+        logger = method.invoke(null, category);
+      } catch (Exception e) {
+        LOG.println("Ignoring: " + e);
+      }
+
+      if (logger != null) {
+        activeLevels = "";
+        for (String call : calls) {
+          try {
+            if (checkLevel(category, call)) {
+              activeLevels += call + ":+ ";
+            } else {
+              activeLevels += call + ":- ";
+            }
+          } catch (Exception e) {
+            LOG.println(e.getMessage());
+            e.printStackTrace();
+            activeLevels += call + ":? ";
+          }
+        }
+      } else {
+        activeLevels = "n/a";
+      }
+    }
+
+    private boolean checkLevel(String category, String level)
+        throws NoSuchMethodException, ClassNotFoundException, InvocationTargetException, IllegalAccessException {
+
+      final Method method = Class.forName(factoryClassName).getMethod(factoryMethod, String.class);
+      final Object c = method.invoke(null, category);
+
+      if (JUL.equals(id)) {
+        return checkLevelGeneric(level, c, "java.util.logging.Level", "isLoggable", "parse");
+      }
+
+      if (LOG4J.equals(id)) {
+        return checkLevelGeneric(level, c, "org.apache.log4j.Priority", "isEnabledFor", "toPriority");
+      }
+
+      if (LOG4J2.equals(id)) {
+        return checkLevelGeneric(level, c, "org.apache.logging.log4j.Level", "isEnabled", "getLevel");
+      }
+
+      if (SLF4J.equals(id) || JCL.equals(id)) {
+        String methodName = "is" + level.substring(0, 1).toUpperCase() + level.substring(1) + "Enabled";
+        final Object hasLevel = c.getClass().getMethod(methodName).invoke(c);
+        return (Boolean) hasLevel;
+      }
+
+      throw new IllegalStateException();
+    }
+
+    private boolean checkLevelGeneric(String level, Object c, String clazz, String enabledMethod, String levelMethod)
+        throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+      final Class<?> levelClass = Class.forName(clazz);
+      final Method isLoggable = c.getClass().getMethod(enabledMethod, levelClass);
+      final Method parse = levelClass.getMethod(levelMethod, String.class);
+      final Object levelObject = parse.invoke(null, level.toUpperCase());
+      final Object hasLevel = isLoggable.invoke(c, levelObject);
+      return (Boolean) hasLevel;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadController.java
new file mode 100644
index 0000000..89e327b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadController.java
@@ -0,0 +1,119 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.internal.util.PartUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AjaxBehaviorEvent;
+import javax.inject.Named;
+import javax.servlet.http.Part;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@SessionScoped
+@Named
+public class UploadController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(UploadController.class);
+
+  private Part fileBasic;
+  private Part fileContentType;
+  private Part[] fileMulti;
+  private Part fileAjax;
+  private List<UploadItem> uploadItems = new ArrayList<UploadItem>();
+
+  public String uploadBasic() {
+    upload(fileBasic);
+    return null;
+  }
+
+  public String uploadContentType() {
+    upload(fileContentType);
+    return null;
+  }
+
+  public String uploadMulti() {
+    for (Part part : fileMulti) {
+      upload(part);
+    }
+    return null;
+  }
+
+  public void uploadAjax(AjaxBehaviorEvent event) {
+    upload(fileAjax);
+  }
+
+  private void upload(Part part) {
+    LOG.info("checking file item");
+    if (part == null || part.getSize() == 0) {
+      return;
+    }
+    LOG.info("type=" + part.getContentType());
+    LOG.info("size=" + part.getSize());
+    LOG.info("cd = " + part.getHeader("Content-Disposition"));
+    final String submittedFileName = PartUtils.getSubmittedFileName(part);
+    LOG.info("name=" + submittedFileName);
+    uploadItems.add(new UploadItem(submittedFileName, part.getSize(), part.getContentType()));
+    FacesContext.getCurrentInstance().addMessage(
+            null, new FacesMessage(FacesMessage.SEVERITY_INFO, "File was uploaded: " + submittedFileName, null));
+  }
+
+  public Part getFileBasic() {
+    return fileBasic;
+  }
+
+  public void setFileBasic(Part fileBasic) {
+    this.fileBasic = fileBasic;
+  }
+
+  public Part getFileContentType() {
+    return fileContentType;
+  }
+
+  public void setFileContentType(Part fileContentType) {
+    this.fileContentType = fileContentType;
+  }
+
+  public Part[] getFileMulti() {
+    return fileMulti;
+  }
+
+  public void setFileMulti(Part[] fileMulti) {
+    this.fileMulti = fileMulti;
+  }
+
+  public Part getFileAjax() {
+    return fileAjax;
+  }
+
+  public void setFileAjax(Part fileAjax) {
+    this.fileAjax = fileAjax;
+  }
+
+  public List<UploadItem> getUploadItems() {
+    return uploadItems;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadItem.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadItem.java
new file mode 100644
index 0000000..56b455e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/UploadItem.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+
+public class UploadItem implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(UploadItem.class);
+
+  private String name;
+  private long size;
+  private String type;
+
+  public UploadItem(final String name, final long size, final String type) {
+    this.name = name;
+    this.size = size;
+    this.type = type;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public long getSize() {
+    return size;
+  }
+
+  public void setSize(final long size) {
+    this.size = size;
+  }
+
+  public String getType() {
+    return type;
+  }
+
+  public void setType(final String type) {
+    this.type = type;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ValidationController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ValidationController.java
new file mode 100644
index 0000000..653d9de
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ValidationController.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.application.FacesMessage;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import javax.faces.validator.ValidatorException;
+import javax.inject.Named;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class ValidationController implements Serializable {
+
+  public void customValidator(final FacesContext context, final UIComponent component, final Object value)
+          throws ValidatorException {
+    if (value == null) {
+      return;
+    }
+    if (!"tobago".equalsIgnoreCase(value.toString())) {
+      throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please type in 'Tobago'",
+              "Please type in 'Tobago'"));
+    }
+  }
+
+  public void passwordValidator(FacesContext context, UIComponent component, Object value) throws ValidatorException {
+    String password = value.toString();
+
+    UIInput confirmationField = (UIInput) component.getAttributes().get("confirmationField");
+    String confirmationFieldValue = confirmationField.getSubmittedValue().toString();
+
+    if (password.isEmpty() || confirmationFieldValue.isEmpty()) {
+      return;
+    }
+
+    if (!password.equals(confirmationFieldValue)) {
+      confirmationField.setValid(false);
+      throw new ValidatorException(new FacesMessage("Passwords must match."));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ValidationJsr303Controller.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ValidationJsr303Controller.java
new file mode 100644
index 0000000..a598634
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/ValidationJsr303Controller.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+
+@RequestScoped
+@Named
+public class ValidationJsr303Controller implements Serializable {
+
+  @NotNull
+  private String required;
+
+  @Size(min = 2, max = 4, message = "Length must be between 2 and 4")
+  private String length;
+
+  public String getRequired() {
+    return required;
+  }
+
+  public void setRequired(String required) {
+    this.required = required;
+  }
+
+  public String getLength() {
+    return length;
+  }
+
+  public void setLength(String length) {
+    this.length = length;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/actionlistener/SimpleTabChangeListener.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/actionlistener/SimpleTabChangeListener.java
new file mode 100644
index 0000000..93b7039
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/actionlistener/SimpleTabChangeListener.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.actionlistener;
+
+import org.apache.myfaces.tobago.event.TabChangeEvent;
+import org.apache.myfaces.tobago.event.TabChangeListener;
+
+public class SimpleTabChangeListener implements TabChangeListener {
+
+  private int count = 0;
+  private int newTabIndex = -1;
+  private int oldTabIndex = -1;
+  private String clientId;
+
+  @Override
+  public void processTabChange(TabChangeEvent tabChangeEvent) {
+    count++;
+    newTabIndex = tabChangeEvent.getNewTabIndex();
+    oldTabIndex = tabChangeEvent.getOldTabIndex();
+    clientId = tabChangeEvent.getComponent().getClientId();
+  }
+
+  public int getCount() {
+    return count;
+  }
+
+  public int getNewTabIndex() {
+    return newTabIndex;
+  }
+
+  public int getOldTabIndex() {
+    return oldTabIndex;
+  }
+
+  public String getClientId() {
+    return clientId;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/BestPracticeController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/BestPracticeController.java
new file mode 100644
index 0000000..e2bd32c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/BestPracticeController.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.bestpractice;
+
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.faces.context.FacesContext;
+import javax.inject.Named;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+
+@RequestScoped
+@Named
+public class BestPracticeController {
+
+  private static final Logger LOG = LoggerFactory.getLogger(BestPracticeController.class);
+
+  private String status;
+
+  public String throwException() {
+    throw new RuntimeException("This exception is forced by the user.");
+  }
+
+  public String viewPdfInBrowser() {
+    return viewFile(false, true);
+  }
+
+  public String viewPdfOutsideOfBrowser() {
+    return viewFile(true, true);
+  }
+
+  public String viewFile(final boolean outside, final boolean pdf) {
+
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+
+    InputStream inputStream = null;
+    try {
+      final String path = "content/30-concept/24-non-faces-response/x-sample." + (pdf ? "pdf" : "txt");
+      inputStream = facesContext.getExternalContext().getResourceAsStream(path);
+      if (inputStream == null) {
+        inputStream = facesContext.getExternalContext().getResourceAsStream("/" + path);
+      }
+      final HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
+      response.setContentType(pdf ? "application/pdf" : "text/plain");
+      if (outside) {
+        response.setHeader("Content-Disposition", "attachment; filename=x-sample." + (pdf ? "pdf" : "txt"));
+      }
+      IOUtils.copy(inputStream, response.getOutputStream());
+    } catch (final IOException e) {
+      LOG.warn("Cannot deliver " + (pdf ? "pdf" : "txt"), e);
+      return "error"; // response via faces
+    } finally {
+      IOUtils.closeQuietly(inputStream);
+    }
+    facesContext.responseComplete();
+    return null;
+  }
+
+  public String getStatus() {
+    return status;
+  }
+
+  public void setStatus(final String status) {
+    this.status = status;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/ToolBarCustomizer.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/ToolBarCustomizer.java
new file mode 100644
index 0000000..61a0664
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/ToolBarCustomizer.java
@@ -0,0 +1,102 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.bestpractice;
+
+import javax.enterprise.context.SessionScoped;
+import javax.faces.component.UIParameter;
+import javax.faces.event.ActionEvent;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+@SessionScoped
+@Named("customizer")
+public class ToolBarCustomizer implements Serializable {
+
+  private List<Item> list;
+
+  public ToolBarCustomizer() {
+    resetList();
+  }
+
+  public String resetList() {
+    list = new ArrayList<Item>(Arrays.asList(
+            new Item("new"),
+            new Item("edit"),
+            new Item("delete")
+    ));
+
+    return null;
+  }
+
+  public void itemUp(final ActionEvent event) {
+    final Item item = (Item) ((UIParameter) event.getComponent().getChildren().get(0)).getValue();
+    final int oldIndex = list.indexOf(item);
+    if (oldIndex > 0) {
+      list.remove(item);
+      list.add(oldIndex - 1, item);
+    }
+  }
+
+  public void itemDown(final ActionEvent event) {
+    final Item item = (Item) ((UIParameter) event.getComponent().getChildren().get(0)).getValue();
+    final int oldIndex = list.indexOf(item);
+    if (oldIndex < list.size() - 1) {
+      list.remove(item);
+      list.add(oldIndex + 1, item);
+    }
+  }
+
+  public List<Item> getList() {
+    return list;
+  }
+
+  public static class Item {
+
+    private String label;
+    private String name;
+
+    private boolean visible = true;
+
+    private Item(final String label) {
+      this.label = label;
+      this.name = "x-buttons-item-" + label.toLowerCase(Locale.ENGLISH) + ".xhtml";
+    }
+
+    public String getLabel() {
+      return label;
+    }
+
+    public String getName() {
+      return name;
+    }
+
+    public boolean isVisible() {
+      return visible;
+    }
+
+    public void setVisible(final boolean visible) {
+      this.visible = visible;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/TransitionController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/TransitionController.java
new file mode 100644
index 0000000..bac766f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/bestpractice/TransitionController.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.bestpractice;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Named;
+
+@RequestScoped
+@Named
+public class TransitionController {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TransitionController.class);
+
+  public String sleep5sAndRedirect() throws InterruptedException {
+    final int sleep = 5000;
+    LOG.info("Waiting " + sleep + " millis.");
+    Thread.sleep(sleep);
+
+    return "/content/30-concept/23-transition/x-transition-after-sleep.xhtml";
+  }
+
+  public String sleep5s() throws InterruptedException {
+    final int sleep = 5000;
+    LOG.info("Waiting " + sleep + " millis.");
+    Thread.sleep(sleep);
+
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/clientConfig/ClientConfigController.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/clientConfig/ClientConfigController.java
new file mode 100644
index 0000000..78d7ff0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/clientConfig/ClientConfigController.java
@@ -0,0 +1,195 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.clientConfig;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.TobagoContext;
+import org.apache.myfaces.tobago.internal.util.ObjectUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.Application;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+public class ClientConfigController {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ClientConfigController.class);
+
+  private Theme theme;
+  private SelectItem[] themeItems;
+
+  private Locale locale;
+
+  public ClientConfigController() {
+
+    // theme
+
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(facesContext);
+
+    final List<Theme> themes = new ArrayList<Theme>(tobagoConfig.getSupportedThemes());
+    themes.add(0, tobagoConfig.getDefaultTheme());
+    themeItems = new SelectItem[themes.size()];
+    for (int i = 0; i < themeItems.length; i++) {
+      final Theme themeItem = themes.get(i);
+      themeItems[i] = new SelectItem(themeItem, themeItem.getDisplayName());
+    }
+
+    // locale
+
+    locale = facesContext.getViewRoot().getLocale();
+
+    // load
+
+    loadFromTobagoContext();
+  }
+
+  public String submit() {
+    if (LOG.isDebugEnabled()) {
+      LOG.debug("invoke!!!");
+    }
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+
+    storeInTobagoContext();
+
+    for (int i = 0; i < ClientConfigPhaseListener.BEAN_NAMES.length; i++) {
+      final String beanName = ClientConfigPhaseListener.BEAN_NAMES[i];
+      final ClientConfigController controller
+          = getCurrentInstance(facesContext, beanName);
+      if (controller != null) {
+        controller.setLocale(locale);
+      }
+    }
+
+    return null;
+  }
+
+/*
+  public String resetTheme() {
+    final ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
+    final Object request = externalContext.getRequest();
+    final Object response = externalContext.getResponse();
+    if (response instanceof HttpServletResponse && request instanceof HttpServletRequest) {
+      CookieUtils.removeThemeNameCookie((HttpServletRequest) request, (HttpServletResponse) response);
+    }
+
+    return null;
+  }
+*/
+
+// ///////////////////////////////////////////// logic
+
+  public void storeInTobagoContext() {
+    final TobagoContext tobagoContext = TobagoContext.getInstance(FacesContext.getCurrentInstance());
+    tobagoContext.setTheme(theme);
+  }
+
+  public void loadFromTobagoContext() {
+    final TobagoContext tobagoContext = TobagoContext.getInstance(FacesContext.getCurrentInstance());
+    theme = tobagoContext.getTheme();
+  }
+
+  public List<SelectItem> getLocaleItems() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final Application application = facesContext.getApplication();
+    final Locale defaultLocale = application.getDefaultLocale();
+    final Iterator supportedLocales = application.getSupportedLocales();
+
+    boolean defaultInList = false;
+    final List<SelectItem> localeItems = new ArrayList<SelectItem>();
+    while (supportedLocales.hasNext()) {
+      final Locale locale = (Locale) supportedLocales.next();
+      localeItems.add(createLocaleItem(locale));
+      if (locale.equals(defaultLocale)) {
+        defaultInList = true;
+      }
+    }
+    // If the default is already in the list, don't add it.
+    // Background: Must the default be in the supported list? Yes or No?
+    // This question is not specified explicit and different implemented in the RI and MyFaces
+    if (!defaultInList && defaultLocale != null) {
+      localeItems.add(0, createLocaleItem(defaultLocale));
+    }
+    return localeItems;
+  }
+
+  private SelectItem createLocaleItem(final Locale localeItem) {
+    if (locale != null) {
+      return new SelectItem(localeItem, localeItem.getDisplayName(locale));
+    } else {
+      return new SelectItem(localeItem, localeItem.getDisplayName(localeItem));
+    }
+  }
+
+  public static ClientConfigController getCurrentInstance(
+      final FacesContext facesContext, final String beanName) {
+    return (ClientConfigController) facesContext.getApplication()
+        .getVariableResolver().resolveVariable(facesContext, beanName);
+  }
+
+  public Theme getTheme() {
+    return theme;
+  }
+
+  public String getLocalizedTheme() {
+    for (int i = 0; i < themeItems.length; i++) {
+      final SelectItem themeItem = themeItems[i];
+      if (ObjectUtils.equals(themeItem.getValue(), theme)) {
+        return themeItem.getLabel();
+      }
+    }
+    return "???";
+  }
+
+  public void setTheme(final Theme theme) {
+    this.theme = theme;
+  }
+
+  public SelectItem[] getThemeItems() {
+    return themeItems;
+  }
+
+  public void setThemeItems(final SelectItem[] themeItems) {
+    this.themeItems = themeItems;
+  }
+
+  public Locale getLocale() {
+    return locale;
+  }
+
+  public String getLocalizedLocale() {
+    if (locale != null) {
+      return locale.getDisplayName(locale);
+    } else{
+      return null;
+    }
+  }
+
+  public void setLocale(final Locale locale) {
+    this.locale = locale;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/clientConfig/ClientConfigPhaseListener.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/clientConfig/ClientConfigPhaseListener.java
new file mode 100644
index 0000000..d419b09
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/clientConfig/ClientConfigPhaseListener.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.clientConfig;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+
+public class ClientConfigPhaseListener implements PhaseListener {
+
+  public static final String[] BEAN_NAMES
+      = {"clientConfigController", "clientConfigController2"};
+
+  @Override
+  public void afterPhase(final PhaseEvent event) {
+  }
+
+  @Override
+  public void beforePhase(final PhaseEvent event) {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    for (int i = 0; i < BEAN_NAMES.length; i++) {
+      final String beanName = BEAN_NAMES[i];
+      final ClientConfigController controller = ClientConfigController
+          .getCurrentInstance(facesContext, beanName);
+
+      if (controller != null) {
+        controller.loadFromTobagoContext();
+      }
+    }
+  }
+
+  @Override
+  public PhaseId getPhaseId() {
+    return PhaseId.RENDER_RESPONSE;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/AbstractConverter.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/AbstractConverter.java
new file mode 100644
index 0000000..7f152ff
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/AbstractConverter.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.formatter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.oro.text.perl.Perl5Util;
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.MatchResult;
+import org.apache.oro.text.regex.Pattern;
+import org.apache.oro.text.regex.PatternMatcherInput;
+import org.apache.oro.text.regex.Perl5Compiler;
+import org.apache.oro.text.regex.Perl5Matcher;
+
+public abstract class AbstractConverter implements Converter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AbstractConverter.class);
+
+  private Pattern pattern;
+
+  private Perl5Matcher matcher = new Perl5Matcher();
+  private Perl5Compiler compiler = new Perl5Compiler();
+  private Perl5Util util = new Perl5Util();
+
+  public abstract Pattern initPattern() throws MalformedPatternException;
+
+  public Perl5Compiler getCompiler() {
+    return compiler;
+  }
+
+  public Perl5Util getUtil() {
+    return util;
+  }
+
+  public Pattern getPattern() {
+    if (pattern == null) {
+      try {
+        pattern = initPattern();
+      } catch (final MalformedPatternException e) {
+        LOG.error("", e);
+      }
+    }
+    return pattern;
+  }
+
+  private String getFragment(final String data, final int start, final int end) {
+    return data.substring(start, end);
+  }
+
+  protected String convertMisc(final String data, final int start, final int end) {
+    return convertMisc(getFragment(data, start, end));
+  }
+
+  protected String convertMatch(final String data, final int start, final int end) {
+    return convertMatch(getFragment(data, start, end));
+  }
+
+  @Override
+  public String convertMisc(final String fragment) {
+    return fragment;
+  }
+
+  @Override
+  public String convert(final String input) {
+    final StringBuilder buffer = new StringBuilder();
+    int lastStart = 0;
+    final PatternMatcherInput patternMatcherInput = new PatternMatcherInput(input);
+    final Pattern pattern = getPattern();
+    if (matcher.contains(patternMatcherInput, pattern)) {
+      do {
+        final MatchResult result = matcher.getMatch();
+        final int start = result.beginOffset(0);
+        final int end = result.endOffset(0);
+        buffer.append(convertMisc(input, lastStart, start));
+        buffer.append(convertMatch(input, start, end));
+        lastStart = end;
+      } while (matcher.contains(patternMatcherInput, pattern));
+    }
+    buffer.append(convertMisc(input, lastStart, input.length()));
+    return buffer.toString();
+  }
+
+  public String highlightStrings(final String input) {
+    return util.substitute("s/(\".*?\")/<span class=\"string\">$1<\\/span>/g", input);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/Converter.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/Converter.java
new file mode 100644
index 0000000..3c2a312
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/Converter.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.formatter;
+
+public interface Converter {
+
+  String convertMisc(String fragment);
+
+  String convertMatch(String fragment);
+
+  String convert(String fragment);
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/JspTagConverter.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/JspTagConverter.java
new file mode 100644
index 0000000..baa9068
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/JspTagConverter.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.formatter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.myfaces.tobago.util.XmlUtils;
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.Pattern;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class JspTagConverter extends AbstractConverter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(JspTagConverter.class);
+
+  private TagConverter tagConverter = new TagConverter();
+  private Map<String, String> tags = new HashMap<String, String>();
+
+  @Override
+  public Pattern initPattern() throws MalformedPatternException {
+//    return compiler.compile("(?s)<%.*?%>");
+//    return compiler.compile("(?s)<%(--)?.*?\\1%>");
+    return getCompiler().compile("(?s)(<!--.*?-->)");
+  }
+
+/*
+  public String highlightJavaKeyword(final String java) {
+    return getUtil().substitute("s/(\\bassert\\b|break\\b|\\bbyte\\b|\\bboolean\\b"
+        + "|\\bcatch\\b|\\bcase\\b|\\bchar\\b|\\bcontinue\\b|\\bdouble\\b"
+        + "|\\bdo\\b|\\belse\\b|\\bextends\\b|\\bfalse\\b|\\bfinal\\b"
+        + "|\\bfloat\\b|\\bfor\\b|\\bfinally\\b|\\bif\\b|\\bimplements\\b"
+        + "|\\bint\\b|\\binterface\\b|\\binstanceof\\b|\\blong\\b|\\blength\\b"
+        + "|\\bnew\\b|\\bnull\\b|\\bprivate\\b|\\bprotected\\b|\\bpublic\\b"
+        + "|\\breturn\\b|\\bswitch\\b|\\bsynchronized\\b|\\bshort\\b"
+        + "|\\bstatic\\b|\\bsuper\\b|\\btry\\b|\\btrue\\b|\\bthis\\b"
+        + "|\\bthrow\\b|\\bthrows\\b|\\bvoid\\b|\\bwhile\\b)"
+        + "/<span class=\"keyword\">$1<\\/span>/g", java);
+  }
+*/
+
+  @Override
+  public String convertMatch(final String fragment) {
+    final String key = "tag" + tags.size();
+    String tag = XmlUtils.escape(fragment, false);
+    if (fragment.startsWith("<%--")) {
+      tag = "<span class=\"jsp-comment\">" + tag + "</span>";
+    } else if (fragment.startsWith("<%@")) {
+      tag = "<span class=\"jsp-directive\">" + tag + "</span>";
+    } else if (fragment.startsWith("<%!")) {
+      // XXX temporarily hide strings to avoid keyword highlighting in strings
+      tag = highlightStrings(tag);
+//      tag = highlightJavaKeyword(tag);
+      tag = "<span class=\"jsp-declaration\">" + tag + "</span>";
+    } else if (fragment.startsWith("<%=")) {
+      tag = highlightStrings(tag);
+      tag = "<span class=\"jsp-scriptlet\">" + tag + "</span>";
+    } else if (fragment.startsWith("<%")) {
+      // XXX temporarily hide strings to avoid keyword highlighting in strings
+      tag = highlightStrings(tag);
+//      tag = highlightJavaKeyword(tag);
+      tag = "<span class=\"jsp-tag\">" + tag + "</span>";
+    } else {
+      LOG.error("error: " + fragment);
+    }
+    tags.put(key, tag);
+    return "${" + key + "}";
+  }
+
+  @Override
+  public String convert(final String input) {
+    String result; // = StringUtils.replace(input, "$", "$$");
+    result = super.convert(input);
+    result = tagConverter.convert(result);
+    final StringExpression stringExpression = new StringExpression(result);
+    return stringExpression.substitute(tags);
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/SourceFormatter.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/SourceFormatter.java
new file mode 100644
index 0000000..39aced2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/SourceFormatter.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.formatter;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.PrintWriter;
+import java.io.Reader;
+
+public class SourceFormatter {
+
+  public static void main(final String[] args) throws Exception {
+    writeJsp(new FileReader(args[0]), new PrintWriter(System.out));
+  }
+
+  public static void writeJsp(final Reader reader, final PrintWriter out)
+      throws IOException {
+    final JspTagConverter formatter = new JspTagConverter();
+    final String source = readJsp(reader);
+    out.println("<html><head>");
+    // out.println("<link rel=\"stylesheet\" href=\"jsp.css\" type=\"text/css\">");
+    out.println("<style>");
+    out.println("body {background-color: white;}");
+    out.println(".jsp-comment {background-color: rgb(227,227,227); color: rgb(128,128,128);}");
+    out.println(".jsp-directive {background-color:  rgb(237,255,237);}");
+    out.println(".jsp-declaration {background-color: rgb(255,252,228);}");
+    out.println(".jsp-scriptlet {background-color: rgb(255,252,228); color: black; font-weight: normal;}");
+    out.println(".jsp-tag {background-color: rgb(255,252,228);}");
+    out.println(".html-tag {background-color: rgb(239,239,239);}");
+    out.println(".string {color: rgb(0,128,0); font-weight: bold;}");
+    out.println(".keyword {color: rgb(0,0,128); font-weight: bold;}");
+    out.println("</style>");
+    out.println("<title>formatted jsp code</title></head><body><pre>");
+    out.println(formatter.convert(source));
+    out.println("</pre></body></html>");
+    out.flush();
+  }
+
+  private static String readJsp(final Reader reader) throws IOException {
+    final LineNumberReader in = new LineNumberReader(reader);
+    final StringBuilder buffer = new StringBuilder();
+    String line = null;
+    while (null != (line = in.readLine())) {
+      buffer.append(line);
+      buffer.append("\n");
+    }
+    in.close();
+    return buffer.toString();
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/StringExpression.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/StringExpression.java
new file mode 100644
index 0000000..b4331ed
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/StringExpression.java
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.formatter;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.Map;
+import java.util.Vector;
+
+public class StringExpression implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(StringExpression.class);
+
+  private static final long serialVersionUID = -152894508593519474L;
+
+  private String string;
+
+  public StringExpression(final String string) {
+    this.string = string;
+  }
+
+  public String toString() {
+    return string;
+  }
+
+  public String substitute(final Map<String, String> variables) {
+    return replaceVariables(string, variables);
+  }
+
+  // implementation copied from ant.ProjectHelper
+  private static String replaceVariables(
+      final String stringExpression, final Map<String, String> variables) {
+    if (stringExpression == null) {
+      return null;
+    }
+
+    final Vector<String> fragments = new Vector<String>();
+    final Vector<String> propertyRefs = new Vector<String>();
+    parsePropertyString(stringExpression, fragments, propertyRefs);
+
+    final StringBuilder sb = new StringBuilder();
+    final Enumeration<String> i = fragments.elements();
+    final Enumeration<String> j = propertyRefs.elements();
+    while (i.hasMoreElements()) {
+      String fragment = i.nextElement();
+      if (fragment == null) {
+        final String propertyName = j.nextElement();
+        if (!variables.containsKey(propertyName)) {
+          // throw exception ?
+          LOG.error("Property ${" + propertyName + "} has not been set");
+        }
+        fragment = (variables.containsKey(propertyName))
+            ? variables.get(propertyName)
+            : "${" + propertyName + "}";
+      }
+      sb.append(fragment);
+    }
+    return sb.toString();
+  }
+
+  private static void parsePropertyString(
+      final String value, final Vector<String> fragments, final Vector<String> propertyRefs) {
+    int prev = 0;
+    int pos;
+    while ((pos = value.indexOf("$", prev)) >= 0) {
+      if (pos > 0) {
+        fragments.addElement(value.substring(prev, pos));
+      }
+      if (pos == (value.length() - 1)) {
+        fragments.addElement("$");
+        prev = pos + 1;
+      } else if (value.charAt(pos + 1) != '{') {
+        fragments.addElement(value.substring(pos + 1, pos + 2));
+        prev = pos + 2;
+      } else {
+        final int endName = value.indexOf('}', pos);
+        if (endName < 0) {
+          throw new IllegalArgumentException("Syntax error in property: " + value);
+        }
+        final String propertyName = value.substring(pos + 2, endName);
+        fragments.addElement(null);
+        propertyRefs.addElement(propertyName);
+        prev = endName + 1;
+      }
+    }
+    if (prev < value.length()) {
+      fragments.addElement(value.substring(prev));
+    }
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/TagConverter.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/TagConverter.java
new file mode 100644
index 0000000..01a31a6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/formatter/TagConverter.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.formatter;
+
+import org.apache.oro.text.regex.MalformedPatternException;
+import org.apache.oro.text.regex.Pattern;
+
+public class TagConverter extends AbstractConverter {
+
+  @Override
+  public Pattern initPattern() throws MalformedPatternException {
+    return getCompiler().compile("(?s)<.*?>");
+  }
+
+  @Override
+  public String convertMatch(final String fragment) {
+    // String escaped = XmlUtils.escape(fragment);
+
+    // XXX invalid
+    final String withLinks = getUtil().substitute("s/^<jsp:include page=\\\"([\\-\\.\\/\\w]+)"
+            + "/<jsp:include page=\\\"<a href='viewSource.jsp?jsp=$1'>$1<\\/a>/", fragment);
+
+    String escaped = getUtil().substitute("s/^(<\\/?)(\\w+):/$1<b>$2<\\/b>:/", withLinks);
+    escaped = highlightStrings(escaped);
+    return "<span class=\"html-tag\">&lt;" + escaped.substring(1, escaped.length()-1) + "></span>";
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/Activity.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/Activity.java
new file mode 100644
index 0000000..544b863
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/Activity.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.info;
+
+import javax.servlet.http.HttpSession;
+import java.io.Serializable;
+import java.util.Date;
+
+public class Activity implements Serializable {
+
+  private String sessionId;
+
+  private Date creationDate;
+
+  private int jsfRequest;
+
+  private int ajaxRequest;
+
+  public Activity(final HttpSession session) {
+    this.sessionId = session.getId();
+    this.creationDate = new Date(session.getCreationTime());
+  }
+
+  public void executeJsfRequest() {
+    jsfRequest++;
+  }
+
+  public void executeAjaxRequest() {
+      ajaxRequest++;
+  }
+
+  public String getSessionId() {
+    return sessionId;
+  }
+
+  public void setSessionId(final String sessionId) {
+    this.sessionId = sessionId;
+  }
+
+  public Date getCreationDate() {
+    return creationDate;
+  }
+
+  public void setCreationDate(final Date creationDate) {
+    this.creationDate = creationDate;
+  }
+
+  public int getJsfRequest() {
+    return jsfRequest;
+  }
+
+  public void setJsfRequest(final int jsfRequest) {
+    this.jsfRequest = jsfRequest;
+  }
+
+  public int getAjaxRequest() {
+    return ajaxRequest;
+  }
+
+  public void setAjaxRequest(final int ajaxRequest) {
+    this.ajaxRequest = ajaxRequest;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivityList.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivityList.java
new file mode 100644
index 0000000..db81edc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivityList.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.info;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+@Named
+@ApplicationScoped
+public class ActivityList implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ActivityList.class);
+
+  // XXX using the session id as key is not good for applications with login, because the container should change
+  // XXX the session id while the login process.
+  private Map<String, Activity> data = new ConcurrentHashMap<String, Activity>();
+
+  public void add(final Activity activity) {
+    LOG.info("Adding session id: " + activity.getSessionId());
+    data.put(activity.getSessionId(), activity);
+  }
+
+  public void remove(final String sessionId) {
+    LOG.info("Removing session id: " + sessionId);
+    data.remove(sessionId);
+  }
+
+  public List<Activity> getValues() {
+    final Collection<Activity> values = data.values();
+    final ArrayList<Activity> result = new ArrayList<Activity>();
+    result.addAll(values);
+    return result;
+  }
+
+  public void executeJsfRequest(final String sessionId) {
+    final Activity activity = data.get(sessionId);
+    if (activity != null) {
+      activity.executeJsfRequest();
+    } else {
+      LOG.error("Ignoring sessionId='{}'", sessionId);
+    }
+  }
+
+  public void executeAjaxRequest(final String sessionId) {
+    final Activity activity = data.get(sessionId);
+    if (activity != null) {
+      activity.executeAjaxRequest();
+    } else {
+      LOG.error("Ignoring sessionId='{}'", sessionId);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivityPhaseListener.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivityPhaseListener.java
new file mode 100644
index 0000000..6c14e51
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivityPhaseListener.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.info;
+
+import org.apache.deltaspike.jsf.api.listener.phase.JsfPhaseListener;
+
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.inject.Inject;
+import javax.servlet.http.HttpSession;
+
+@JsfPhaseListener
+public class ActivityPhaseListener implements PhaseListener {
+
+  @Inject
+  private ActivityList activityList;
+
+  public ActivityPhaseListener() {
+  }
+
+  @Override
+  public void beforePhase(final PhaseEvent event) {
+    final FacesContext facesContext = event.getFacesContext();
+    final String sessionId = ((HttpSession) facesContext.getExternalContext().getSession(true)).getId();
+
+    if (facesContext.getPartialViewContext().isAjaxRequest()) {
+      activityList.executeAjaxRequest(sessionId);
+    } else {
+      activityList.executeJsfRequest(sessionId);
+    }
+  }
+
+  @Override
+  public void afterPhase(final PhaseEvent event) {
+  }
+
+  @Override
+  public PhaseId getPhaseId() {
+    return PhaseId.RENDER_RESPONSE;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivitySessionListener.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivitySessionListener.java
new file mode 100644
index 0000000..0999476
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/info/ActivitySessionListener.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.info;
+
+import org.apache.deltaspike.core.api.provider.BeanProvider;
+
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+public class ActivitySessionListener implements HttpSessionListener {
+
+  @Override
+  public void sessionCreated(final HttpSessionEvent event) {
+    final HttpSession session = event.getSession();
+    final ActivityList activityList = BeanProvider.getContextualReference(ActivityList.class);
+
+    activityList.add(new Activity(session));
+  }
+
+  @Override
+  public void sessionDestroyed(final HttpSessionEvent event) {
+    final HttpSession session = event.getSession();
+    final ActivityList activityList = BeanProvider.getContextualReference(ActivityList.class);
+
+    activityList.remove(session.getId());
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/nonfacesrequest/FishPond.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/nonfacesrequest/FishPond.java
new file mode 100644
index 0000000..03e6a81
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/nonfacesrequest/FishPond.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.nonfacesrequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.enterprise.context.SessionScoped;
+import javax.inject.Named;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+@SessionScoped
+@Named
+public class FishPond implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(FishPond.class);
+
+  private Map<Integer, String> fishes;
+
+  private Integer selectedFishId = null;
+
+  public FishPond() {
+    fishes = new HashMap<Integer, String>();
+    fishes.put(0, "Scholle");
+    fishes.put(1, "Hai");
+    fishes.put(2, "Luce");
+    fishes.put(3, "Halibut");
+    fishes.put(4, "Tamboril");
+  }
+
+  public void action() {
+    LOG.info("Event is called! selectedFishId='{}'", selectedFishId);
+    // not needed for this example
+  }
+
+  public String random() {
+    final Random random = new Random(System.currentTimeMillis());
+    selectedFishId = random.nextInt(fishes.size());
+
+    LOG.info("select via random: '" + getSelectedFish() + "'");
+
+    return null; // is AJAX
+  }
+
+  public String select(final Integer fishId) {
+    selectedFishId = fishId;
+    LOG.info("select via id: '" + getSelectedFish() + "'");
+    return "/content/90-non-faces-request/x-fish-pond.xhtml";
+  }
+
+  public String getSelectedFish() {
+    return fishes.get(selectedFishId);
+  }
+
+  public Integer getSelectedFishId() {
+    return selectedFishId;
+  }
+
+  public void setSelectedFishId(Integer selectedFishId) {
+    this.selectedFishId = selectedFishId;
+    LOG.info("setSelectedFishId via setter: '" + selectedFishId + "'");
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/sudoku/Sudoku.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/sudoku/Sudoku.java
new file mode 100644
index 0000000..049eff1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/java/org/apache/myfaces/tobago/example/demo/sudoku/Sudoku.java
@@ -0,0 +1,263 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.sudoku;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.BitSet;
+import java.util.List;
+import java.util.Random;
+import java.util.Stack;
+
+/**
+ * This is a demo of the logic of a sudoku game.
+ *
+ * The basic idea is not to write yet an other sudoku, but to demonstrate application specific controls.
+ */
+public class Sudoku {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Sudoku.class);
+
+  private static final Random RANDOM = new Random(System.currentTimeMillis());
+
+  private byte[] field;
+  private Stack<Byte> undefined;
+
+  private int depth;
+  private int maxDepth;
+
+  public Sudoku() {
+    field = new byte[]{
+        0, 1, 2, 3, 4, 5, 6, 7, 8,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+        -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    };
+    final RandomList randomList = new RandomList((byte) 81);
+    randomList.removeSmallest(9);
+    depth = 9;
+    undefined = randomList.asStack();
+
+  }
+
+  public Sudoku(final byte[] field) {
+    this.field = field;
+    //XXX  undefined = new RandomList((byte) 81).asStack();
+  }
+
+  public Result solve() {
+    if (undefined.isEmpty()) {
+      LOG.debug("--------------- result ");
+      LOG.debug(this.toString());
+      LOG.debug("--------------- result ");
+      return Result.UNIQUE;
+    }
+    final byte position = undefined.pop();
+    final RandomList list = new RandomList((byte) 9);
+    boolean foundOne = false;
+    while (!list.isEmpty()) {
+      field[position] = list.next();
+//      LOG.debug(depth);
+//      LOG.debug(this);
+      if (checkRules()) {
+//        LOG.debug("ok");
+        final Result result = solve2();
+        switch (result) {
+          case ERROR:
+            break;
+          case MULTIPLE:
+            return Result.MULTIPLE;
+          case UNIQUE:
+            if (foundOne) {
+              return Result.MULTIPLE;
+            } else {
+              foundOne = true;
+            }
+            break;
+          default:
+            assert(false);
+        }
+      }
+    }
+    undefined.push(position);
+    field[position] = -1;
+
+    return Result.ERROR;
+  }
+
+  private Result solve2() {
+    depth++;
+    if (depth > maxDepth) {
+      maxDepth = depth;
+      LOG.debug("new max depth: " + maxDepth);
+    }
+    final Result result = solve();
+    depth--;
+    return result;
+  }
+
+
+  private boolean checkRules() {
+    return checkRowRules() && checkColumnRules() && checkSquareRules();
+  }
+
+  protected boolean checkRowRules() {
+    for (int i = 0; i < 9; i++) {
+      final BitSet xxx = new BitSet();
+      for (int j = 0; j < 9; j++) {
+        final byte value = field[i * 9 + j];
+        if (value != -1) {
+          if (xxx.get(value)) {
+//            LOG.debug("fail h " + i);
+            return false;
+          }
+          xxx.set(value);
+        }
+      }
+    }
+    return true;
+  }
+
+  protected boolean checkColumnRules() {
+    for (int i = 0; i < 9; i++) {
+      final BitSet xxx = new BitSet();
+      for (int j = 0; j < 9; j++) {
+        final byte value = field[j * 9 + i];
+        if (value != -1) {
+          if (xxx.get(value)) {
+//            LOG.debug("fail v " + i);
+            return false;
+          }
+          xxx.set(value);
+        }
+      }
+    }
+    return true;
+  }
+
+  protected boolean checkSquareRules() {
+    for (int i = 0; i < 9; i++) {
+      final BitSet xxx = new BitSet();
+      for (int j = 0; j < 9; j++) {
+        final int i1 = (i % 3) * 3 + i / 3 * 27 + j % 3 + j / 3 * 9;
+        final byte value = field[i1];
+        if (value != -1) {
+          if (xxx.get(value)) {
+//            LOG.debug("fail 3 " + i);
+            return false;
+          }
+          xxx.set(value);
+        }
+      }
+    }
+    return true;
+  }
+
+  public static void main(final String[] args) {
+    LOG.debug("" + new RandomList((byte) 9).list);
+    final Sudoku sudoku = new Sudoku();
+    LOG.debug("---------------------------------------------------------------------------------------------");
+    final Result result = sudoku.solve();
+    LOG.debug("" + result);
+    LOG.debug("---------------------------------------------------------------------------------------------");
+    LOG.debug("" + sudoku);
+  }
+
+  @Override
+  public String toString() {
+    final StringBuilder builder = new StringBuilder();
+    for (int i = 0; i < field.length; i++) {
+      if (field[i] == -1) {
+        builder.append('-');
+      } else {
+        builder.append(field[i] + 1);
+      }
+      if (i % 9 != 8) {
+        builder.append(' ');
+      } else {
+        builder.append('\n');
+      }
+    }
+    return builder.toString();
+  }
+
+  /**
+   * Creates a random list of the numbers 1, 2, 3, ..., n like 4, n-1, 3, ... n-3.
+   */
+  private static class RandomList {
+
+    private byte n;
+    private List<Byte> list;
+
+    private RandomList(final byte n) {
+      this.n = n;
+      list = new ArrayList<Byte>(n);
+      shuffle();
+    }
+
+    public void shuffle() {
+      final List<Byte> temp = new ArrayList<Byte>(n);
+      for (byte i = 0; i < n; i++) {
+        temp.add(i, i);
+      }
+      for (byte i = n; i > 0; i--) {
+        final byte index = (byte) RANDOM.nextInt(i);
+        list.add(temp.remove(index));
+      }
+    }
+
+    public byte next() {
+      return list.remove(0);
+    }
+
+    public boolean isEmpty() {
+      return list.isEmpty();
+    }
+
+    public Stack<Byte> asStack() {
+      final Stack<Byte> stack = new Stack<Byte>();
+      for (final Byte aByte : list) {
+        stack.add(aByte);
+      }
+      return stack;
+    }
+
+    public void removeSmallest(final int n) {
+      for (byte i = 0; i < n; i++) {
+        list.remove((Byte) i);
+      }
+    }
+  }
+
+  private static enum Result {
+    UNIQUE,
+    MULTIPLE,
+    ERROR
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/logback.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/logback.xml
new file mode 100644
index 0000000..c24351d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- Schema is NOT official from logback -->
+<configuration
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="https://raw.github.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{"yyyy-MM-dd'T'HH:mm:ss,SSSXXX", UTC} %-5level [%-20.20thread] %-50.50logger{50}:%-20.20method:%-4.4line [%mdc] %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <logger name="org.apache.myfaces.tobago.example.demo" level="debug"/>
+
+  <root level="info">
+    <appender-ref ref="console" />
+  </root>
+</configuration>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/Demo.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/Demo.xml
new file mode 100644
index 0000000..ec8dbe9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/Demo.xml
@@ -0,0 +1,429 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+ <entry key="tobago_url">http://myfaces.apache.org/tobago</entry>
+
+  <entry key="notTranslated">Sorry, not completely translated yet.</entry>
+  <entry key="pageTitle">Tobago Demo</entry>
+
+  <entry key="login">Login</entry>
+
+  <!-- menu -->
+  <entry key="menu_config">Configuration</entry>
+  <entry key="menu_themes">Theme</entry>
+  <entry key="menu_locale">Language</entry>
+  <entry key="menu_help">Help</entry>
+  <entry key="menu_about">About</entry>
+
+  <!-- navigate -->
+  <entry key="intro">Intro</entry>
+  <entry key="new_in_3_0">New in Tobago 3.0</entry>
+  <entry key="migration">Migration</entry>
+  <entry key="migration15">1.0 to 1.5</entry>
+  <entry key="migration20">1.5 to 2.0</entry>
+  <entry key="migration30">2.0 to 3.0</entry>
+
+  <!-- navigate : components -->
+  <entry key="component">Components</entry>
+  <entry key="input">Input Fields</entry>
+  <entry key="in">Input</entry>
+  <entry key="suggest">Suggest</entry>
+  <entry key="textarea">Text Area</entry>
+  <entry key="date">Date</entry>
+  <entry key="group">Input Group</entry>
+  <entry key="output">Output Fields</entry>
+  <entry key="out">Output</entry>
+  <entry key="label">Label</entry>
+  <entry key="messages">Messages</entry>
+  <entry key="figure">Figure</entry>
+  <entry key="image">Image</entry>
+  <entry key="progress">Progress Bar</entry>
+  <entry key="object">External Object (iframe)</entry>
+  <entry key="select">Select Controls</entry>
+  <entry key="selectBooleanCheckbox">Checkbox</entry>
+  <entry key="selectOneChoice">Dropdown Box</entry>
+  <entry key="selectOneRadio">Radio Button</entry>
+  <entry key="selectOneListbox">Singleselection List</entry>
+  <entry key="selectManyCheckbox">Checkbox Group</entry>
+  <entry key="selectManyListbox">Multiselection List</entry>
+  <entry key="selectManyShuttle">Shuttle List</entry>
+  <entry key="command">Commands</entry>
+  <entry key="button_link">Link &amp; Button</entry>
+  <entry key="default_command">Default Command</entry>
+  <entry key="buttons">Button Group</entry>
+  <entry key="buttons_customizer">Button Group Customizer</entry>
+  <entry key="links">Link Group</entry>
+  <entry key="container">Container</entry>
+  <entry key="box">Content Box</entry>
+  <entry key="panel">Panel</entry>
+  <entry key="separator">Separator</entry>
+  <entry key="section">Section</entry>
+  <entry key="header_footer">Header / Footer</entry>
+  <entry key="bar">Bar</entry>
+  <entry key="popup">Popup Dialog</entry>
+  <entry key="tab">Tab Group</entry>
+  <entry key="tab_client">Client sided</entry>
+  <entry key="tab_ajax">Ajax</entry>
+  <entry key="tab_server">Server sided</entry>
+  <entry key="sheet">Sheet Control</entry>
+  <entry key="sheet_column_content">Column Content</entry>
+  <entry key="sheet_sorting">Sorting</entry>
+  <entry key="sheet_column_selector">Column Selector</entry>
+  <entry key="sheet_event">Event</entry>
+  <entry key="sheet_markup">Markup</entry>
+  <entry key="sheet_dropdown">Dropdown Box</entry>
+  <entry key="sheet_filter">Filtering</entry>
+  <entry key="sheet_static_header">Static Header</entry>
+  <entry key="sheet_multi_header">Multi Header</entry>
+  <entry key="sheet_tree">Column Tree</entry>
+  <entry key="sheet_editable">Editable Sheet</entry>
+  <entry key="tree">Tree Control</entry>
+  <entry key="tree_command_types">Command</entry>
+  <entry key="tree_select">Select</entry>
+  <entry key="tree_editor">Tree Editor</entry>
+  <entry key="tree_menu">Tree Menu</entry>
+  <entry key="tree_listbox">Tree List</entry>
+  <entry key="upload">File Upload</entry>
+  <entry key="wysiwyg_editor">WYSIWYG Editor</entry>
+  <entry key="tinymce">TinyMCE</entry>
+  <entry key="ckeditor">CKEditor</entry>
+
+  <!-- navigate : concept -->
+  <entry key="concept">Concepts</entry>
+  <entry key="validation">Validation</entry>
+  <entry key="content_validation">Content Validation</entry>
+  <entry key="validation_jsr303">JSR 303: Bean Validation</entry>
+  <entry key="severity">Severity</entry>
+  <entry key="conversion">Conversion</entry>
+  <entry key="form">Forms</entry>
+  <entry key="form_required">Required Forms</entry>
+  <entry key="form_ajax">Ajax Forms</entry>
+  <entry key="theme">Themes</entry>
+  <entry key="layout">Layout</entry>
+  <entry key="flow_layout">FlowLayout</entry>
+  <entry key="flex_layout">FlexLayout</entry>
+  <entry key="segment_layout">SegmentLayout</entry>
+  <entry key="labeled_layout">LabeledLayout</entry>
+  <entry key="format">Formatting</entry>
+  <entry key="transition">Transition</entry>
+  <entry key="for_each">For Each</entry>
+  <entry key="collapsible">Collapsible</entry>
+  <entry key="collapsible_box">Content Box</entry>
+  <entry key="collapsible_popup">Popup</entry>
+  <entry key="collapsible_panel">Panel</entry>
+  <entry key="collapsible_section">Section</entry>
+  <entry key="accessKey">Access Keys</entry>
+  <entry key="dataAttribute">Data Attributes</entry>
+  <entry key="roles">Roles</entry>
+
+  <!-- navigate : deprecated -->
+  <entry key="deprecated">Deprecated</entry>
+  <entry key="tx">TX Tag Library</entry>
+  <entry key="suggest_method">SuggestMethod</entry>
+  <entry key="toolBar">Toolbar</entry>
+  <entry key="menubar">Menubar</entry>
+  <entry key="grid_layout">GridLayout</entry>
+
+  <!-- navigate : test -->
+  <entry key="test">Tests</entry>
+  <entry key="sheet_types">Sheet Content</entry>
+  <entry key="manual">Manual Tests</entry>
+
+  <entry key="validation-severity">Severity</entry>
+  <entry key="browser">Browser</entry>
+  <entry key="locale">Locale</entry>
+
+  <entry key="bestPractice">Best Practice</entry>
+  <entry key="error">Error Handling</entry>
+  <entry key="theme">Themes</entry>
+  <entry key="transition">Transition</entry>
+  <entry key="nonFacesResponse">Non Faces Resp.</entry>
+  <entry key="toolBarCustomizer">User Customized UI</entry>
+  <entry key="faceletsAsResources">Facelets As Resource</entry>
+  <entry key="non-faces-request">Non Faces Request</entry>
+
+  <entry key="reference_intro">Ref. (under constr.)</entry>
+  <entry key="reference_command">Command</entry>
+  <entry key="reference_container">Container</entry>
+  <entry key="reference_inputSuggest">Input suggest</entry>
+  <entry key="reference_menu">Menu</entry>
+  <entry key="reference_output">Output</entry>
+  <entry key="reference_object">Object</entry>
+  <entry key="reference_popup">Popup</entry>
+  <entry key="reference_progress">Progress</entry>
+  <entry key="reference_select">Select</entry>
+  <entry key="reference_sheet">Sheet</entry>
+  <entry key="reference_tab">Tab</entry>
+  <entry key="reference_time">Time</entry>
+  <entry key="reference_tree">Tree</entry>
+  <entry key="reference_tool">Tool Bar</entry>
+  <entry key="reference_partial">Partial</entry>
+  <entry key="reference_upload">Upload</entry>
+
+  <entry key="submit">Submit</entry>
+  <entry key="cancel">Cancel</entry>
+
+  <entry key="footer_previous">Prev</entry>
+  <entry key="footer_next">Next</entry>
+  <entry key="footer_viewSource">View Source</entry>
+
+  <!-- Tag Library Documentation URL -->
+  <entry key="tagDocUrl">https://myfaces.apache.org/tobago/doc</entry>
+
+<!--  basicControls -->
+  <entry key="basic_sampleInputTitle">Basic Input Examples</entry>
+  <entry key="basic_sampleSelectTitle">Basic Select Examples</entry>
+  <entry key="basic_sampleLinkTitle">Basic Controls Examples</entry>
+  <entry key="basic_itemUnknown">none</entry>
+  <entry key="basic_itemMr">Mr.</entry>
+  <entry key="basic_itemMrs">Mrs.</entry>
+  <entry key="basic_textboxLabel">Inputfield</entry>
+  <entry key="basic_textboxTip">A simple input field</entry>
+  <entry key="basic_suggestLabel">Suggest (AJAX)</entry>
+  <entry key="basic_suggestTip">Please type in "po" for example</entry>
+  <entry key="basic_dateLabel">Date</entry>
+  <entry key="basic_timeLabel">Time</entry>
+  <entry key="basic_textareaLabel">Textarea</entry>
+  <entry key="basic_linkAction">Click Link</entry>
+  <entry key="basic_buttonAction">Click Button</entry>
+  <entry key="basic_lastActionLabel">Last Click</entry>
+  <entry key="basic_text_input">Input controls for different kinds of text: single-line, multiline, formated.</entry>
+  <entry key="basic_text_select">Select controls allow input of one or multiple options.</entry>
+  <entry key="basic_text_action">Control elements for site navigation and to execute actions.</entry>
+
+
+<!--  sheet -->
+<entry key="sheet_text">The sheet control is a simple solution for displaying table based
+  information. The essential features are:
+    &lt;ul style="margin-top: 2px;"&gt;
+    &lt;li style="line-height: 130%;"&gt;Paging: A defined range of data is displayed.
+      Navigation is done with arrow buttons.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Sorting: By clicking a column header the
+    appropriate column is sorted.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Inline-Editing: If needed, the values of
+    cell contents can be directly changed or inserted by the user.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;The column width can be resized by simply
+    drag and drop the column border.
+    &lt;/ul&gt;
+    This example shows an application specific sorter, which sorts the sun to the top every time.
+</entry>
+<entry key="sheet_resetLabel">Reset</entry>
+<entry key="sheet_resetTip">Reset the modified widths of the columns in the sheet.</entry>
+<entry key="sheet_configTip">Click here to edit display attributes of the sheet.</entry>
+<entry key="sheet_configTitle">Sheet configuration</entry>
+
+<!--  tree -->
+<entry key="tree_text">The tree control displays a tree which is generated from application data. The key features are:
+    &lt;ul style="margin-top: 2px;"&gt;
+    &lt;li style="line-height: 130%;"&gt;Attributes control the rendering of the tree.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;The possibility to define the tree as "single" or "multiselect", i.e. select one or multiple nodes of the tree.
+    &lt;li style="line-height: 130%;"&gt;Editing mode for simple handling of tree structures inside the application.&lt;/li&gt;
+    &lt;/ul&gt;
+    Furthermore there is a TreeListbox Control, which can be described as a vertical tree. This is handy for categorization actions.
+  </entry>
+<entry key="treeShowIcons">show icons</entry>
+<entry key="treeShowRoot">show root node</entry>
+<entry key="treeShowJunctions">show junction tree</entry>
+<entry key="treeShowRootJunction">show first junction</entry>
+<entry key="treeMultiselect">selectable</entry>
+<entry key="treeMutable">mutable</entry>
+<entry key="treeLabel">Tre_e</entry>
+<entry key="treeListboxLabel">Listbo_x</entry>
+
+
+<entry key="none">Not selectable</entry>
+<entry key="single">Single selection</entry>
+<entry key="singleLeafOnly">Single selection, Leafs only</entry>
+<entry key="multi">Multi selection</entry>
+<entry key="multiLeafOnly">Multi selection, Leafs only</entry>
+<entry key="siblingLeafOnly">Multi selection, Leafs on same level only</entry>
+
+
+
+<!--  tab -->
+<entry key="tab_text">The tab control provides so called tab panels.
+    &lt;ul style="margin-top: 2px;"&gt;
+    &lt;li style="line-height: 130%;"&gt;Control can take place on server- or clientside.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Tab controls can be nested.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Inside each tab control any other controls   can be used.&lt;/li&gt;
+    &lt;/ul&gt;
+  </entry>
+<entry key="tabSwitchTypeClient">Client side tabbing</entry>
+<entry key="tabSwitchTypeReloadTag">Server side tabbing (Ajax)</entry>
+<entry key="tabSwitchTypeReloadPage">Server side tabbing (Full Reload)</entry>
+<entry key="tabPlanet">Data of the _Planets</entry>
+<entry key="tabInsolar">In the _Solarsystem</entry>
+<entry key="closeButtonTip">Hide this tab for one request cycle</entry>
+<entry key="tabMoons">_Moons</entry>
+
+
+<!--  solar -->
+<entry key="solarPlanetDiameter">Diameter</entry>
+<entry key="solarPlanetMass">Mass</entry>
+<entry key="solarPlanetSunDistance">Distance of the Sun</entry>
+<entry key="solarPlanetTimeOfCirculation">Time of Circulation</entry>
+<entry key="solarArrayName">Name</entry>
+<entry key="solarArrayNumber">#</entry>
+<entry key="solarArrayNumberTip">Number</entry>
+<entry key="solarArrayOrbit">Orbits</entry>
+<entry key="solarArrayDistance">Distance</entry>
+<entry key="solarArrayPeriod">Period</entry>
+<entry key="solarArrayPopulation">Population</entry>
+<entry key="solarPagingSheet">Sheet with Paging</entry>
+
+
+<!--  toolbar -->
+<entry key="toolbar_closePopupAction">Close popup window</entry>
+<entry key="toolbar_popupText">To close this popup window click close button.</entry>
+<entry key="toolbar_dropDownAction">DropDown</entry>
+<entry key="toolbar_sampleTitle">Toolbar Example</entry>
+<entry key="toolbar_text1">Toolbars can be used for context sensitive actions inside box controls.
+&lt;ul style="margin-top: 2px;"&gt;
+&lt;li style="line-height: 130%;"&gt;Toolbars can consist of images, text or both.&lt;/li&gt;
+&lt;li style="line-height: 130%;"&gt;Toolbars can be completly integrated into a box header.&lt;/li&gt;
+&lt;li style="line-height: 130%;"&gt;Actions can be displayed as drop down menues.&lt;/li&gt;
+&lt;/ul&gt;
+  </entry>
+<entry key="right">right</entry>
+<entry key="bottom">bottom</entry>
+<entry key="off">off</entry>
+<entry key="small">small</entry>
+<entry key="big">big</entry>
+
+
+<!--  validation -->
+<entry key="validation_description">Description</entry>
+<entry key="validation_number">Number</entry>
+<entry key="validation_price">Price</entry>
+<entry key="validation_custom">Custom Validator</entry>  
+<entry key="validation_submit">Submit</entry>
+
+<entry key="validation_text">Tobago provides easy to use possibilities for validation of user input.
+    &lt;ul style="margin-top: 2px;"&gt;
+    &lt;li style="line-height: 130%;"&gt;Syntactic and semantic validation is available.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Error messages can be positioned anywhere in the   user interface.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Input elements, which are affected by the   validation can be highlighted.&lt;/li&gt;
+    &lt;/ul&gt;
+</entry>
+
+<!--  form -->
+<entry key="form_outTitle">Outer form</entry>
+<entry key="form_text1">&lt;li style="line-height: 130%;"&gt;Values in the first form are being
+  stored temporarily by submitting the second form while the value in the second
+  form is written into the model.&lt;/li&gt;
+&lt;li style="line-height: 130%;"&gt;By submitting both form each value is stored into
+  the model.&lt;/li&gt;
+&lt;li style="line-height: 130%;"&gt;If the first input contains an error but the second
+  one validates, the validation of the first form is deactivated.&lt;/li&gt;
+  </entry>
+<entry key="form_in1Title">First inner form</entry>
+<entry key="form_in2Title">Second inner form</entry>
+<entry key="newValue1">New model-value</entry>
+<entry key="modelValue1">Value in model</entry>
+<entry key="submitForm1">Submit Form 1</entry>
+<entry key="newValue2">New model-value</entry>
+<entry key="modelValue2">Value in model</entry>
+<entry key="submitForm2">Submit Form 2</entry>
+<entry key="submitAll">Submit all Forms</entry>
+
+
+
+
+<!--  theme -->
+<entry key="theme_title">Theme settings</entry>
+<entry key="theme_text">Tobago supports a big variety of displaying controls,
+  so called designs or themes.
+    &lt;ul style="margin-top: 2px;"&gt;
+    &lt;li style="line-height: 130%;"&gt;Choosing of themes can be application wide,   user or group specific.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Images and other resources can be theme   dependant as well as the application pages can be designed seperatly   for each supported theme.&lt;/li&gt;
+    &lt;/ul&gt;
+</entry>
+
+<!--  browser -->
+<entry key="browser_sampleTitle">Browser Example</entry>
+<entry key="browser_text">Tobago is completely browser independant. Support of the different
+  browsers takes place in the JSF renderkit and does not have any effect on the
+  business logic development.
+    &lt;ul style="margin-top: 2px;"&gt;
+    &lt;li style="line-height: 130%;"&gt;Tobago supports common browsers: Internet   Explorer, Mozilla and Netscape navigator.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Tobago reacts on the value delivered by the   HTTP header 'User-Agent' to decide which controls have to be rendered.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Control defaulting: The implentation of themes   can be both browser independant and based on other themes to prevent   code redundancy.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;More browsers can be supported easily.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Additional clients are supported, too: HTML, Simple HTML&lt;/li&gt;
+    &lt;/ul&gt;
+</entry>
+
+<!--  locale -->
+<entry key="locale_title">Locale settings</entry>
+<entry key="locale_label">Locale</entry>
+<entry key="locale_submit">Submit</entry>
+<entry key="locale_text">Tobago supports internationalization and localization.
+    &lt;ul style="margin-top: 2px;"&gt;
+    &lt;li style="line-height: 130%;"&gt;Unicode is used internally.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Content in different languages can be provided by resource bundles.&lt;/li&gt;
+    &lt;li style="line-height: 130%;"&gt;Like content, images and scripts can be localized.&lt;/li&gt;
+    &lt;/ul&gt;
+</entry>
+
+  <!-- Themes -->
+  <entry key="themesText1">&lt;b&gt;Theme configuration&lt;/b&gt; &lt;br /&gt;&lt;br
+    /&gt;
+    In Tobago it's easy to give an application a well designed look. You can use
+    prepared themes like speyside or scarborough, just to name two.
+    The only thing you have to do is configure them at the right place. This is
+    done in the tobago-config.xml by defining a default theme.</entry>
+
+  <entry key="themesCodeExampleTitle">Code Example</entry>
+  <entry key="themesCodeExample">...
+&lt;tobago-config&gt;
+            &lt;theme-config&gt;
+                        &lt;default-theme&gt;speyside&lt;/default-theme&gt;
+            &lt;/theme-config&gt;
+            &lt;resource-dir&gt;tobago&lt;/resource-dir&gt;
+&lt;/tobago-config&gt;
+...</entry>
+  <entry key="theme_photo">The Standard Theme doesn't have a photo to show</entry>
+
+  <entry key="foreach_text">
+    There are two possibilities to use iterators:&lt;br/>
+    This example uses &lt;b>&amp;lt;c:forEach&gt;&lt;/b>. It works well with the layout manager.&lt;br/>
+    Using &lt;b>&amp;lt;ui:repeat&gt;&lt;/b> doesn't work with the grid layout manager in the moment.
+    The iterated components are on top of each other in the HTML document,
+    because they got have all the same position attributes.&lt;br/></entry>
+
+  <!-- faceletsAsResources -->
+  <entry key="faceletsAsResources_text">
+    This example demonstrates how to load parts of the view of an application from a library jar file.
+    You have to define a context parameter in the web.xml:
+
+    &lt;context-param>
+      &lt;param-name>javax.faces.FACELETS_RESOURCE_RESOLVER&lt;/param-name>
+      &lt;param-value>org.apache.myfaces.tobago.facelets.MetaInfResourcesClasspathResourceResolver&lt;/param-value>
+    &lt;/context-param>
+
+    The content has to reside in the /META-INF/resources directory.</entry>
+
+  <entry key="format1">The equatorial radius of the sun is {0} km.</entry>
+  <entry key="format3">The temperature of the sun is {0} K on the surface, but {1} K in the center and {2} K in the corona.</entry>
+  <entry key="format9">Just reordering: {4} - {1} - {6} - {8} - {5} - {3} - {0} - {7} - {2}</entry>
+
+
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/Demo_de.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/Demo_de.xml
new file mode 100644
index 0000000..55b0fbd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/Demo_de.xml
@@ -0,0 +1,196 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="notTranslated">Einige Teile dieser Seite sind nicht in allen Sprachen verfügbar.</entry>
+
+<!--  menu -->
+  <entry key="menu_navigate">_Navigation</entry>
+
+<!--  navigate -->
+  <entry key="overview">Übersicht</entry>
+  <entry key="toolbar">Toolbar</entry>
+  <entry key="themes">Designs</entry>
+<!-- browser=Browser -->
+  <entry key="locale">Lokalisierung</entry>
+<!-- layout=Layout -->
+
+  <!--<entry key="bestPractice">Best Practice</entry>-->
+  <entry key="error">Fehlerbehandlung</entry>
+
+  <entry key="submit">Übernehmen</entry>
+  <entry key="cancel">Abbrechen</entry>
+
+<!--  intro -->
+  <entry key="intro_text">&lt;p&gt;Tobago ist ein User-Interface-Framework zur Erstellung von Webanwendungen.
+    Das Framework stützt sich auf JavaServer Faces ab. Das Kernstück bildet ein Theme-orientiertes
+    JSF Render Kit.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Basis Controls&lt;/b&gt;&lt;br/&gt; Tobago stellt alle
+    Standardcontrols von HTML zur Verfügung wie Eingabefelder, Textfelder, Radiobuttons, Checkboxen und Knöpfe.
+    Zusätzlich zu den Basis Controls bietet Tobago eine Anzahl komplexer Controls, die nicht direkt von HTML
+    unterstützt werden. Dazu gehören: Sheet, Baum,
+    Karteireiter&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Validierung&lt;/b&gt;&lt;br/&gt; Das Hauptziel von Tobago ist es,
+    dass Entwickeln von Anwendungen, mit denen der Anwender interagieren kann. Um die Interaktion zu verbessern,
+    verfügt Tobago über Möglichkeiten, die Eingaben des Anwenders zu überprüfen und den Anwender bei der Eingabe
+    korrekter Werte zu unterstützen.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Layout&lt;/b&gt;&lt;br/&gt; Tobago bietet einen
+    rafinierten Layoutmanager, den man als Mischung aus klassischem HTML Tabellen Layout und Swing Gridbag Layout
+    verstehen kann.&lt;/p&gt;  &lt;p&gt;&lt;b&gt;Weiteres&lt;/b&gt;&lt;br/&gt; Themes, Browser,
+    Internationalisierung&lt;/p&gt;</entry>
+
+<!--  basicControls -->
+  <entry key="basic_sampleInputTitle">Eingabe Beispiele</entry>
+  <entry key="basic_sampleSelectTitle">Auswahl Beispiele</entry>
+  <entry key="basic_sampleLinkTitle">Steuerungs Beispiele</entry>
+  <entry key="basic_itemUnknown">keine</entry>
+  <entry key="basic_itemMr">Herr</entry>
+  <entry key="basic_itemMrs">Frau</entry>
+  <entry key="basic_textboxLabel">Eingabefeld</entry>
+  <entry key="basic_textboxTip">Ein einfaches Eingabefeld</entry>
+  <entry key="basic_suggestLabel">Vorschlag (AJAX)</entry>
+  <entry key="basic_suggestTip">Bitte geben Sie beispielsweise "po" ein</entry>
+  <entry key="basic_dateLabel">Datum</entry>
+  <entry key="basic_timeLabel">Uhrzeit</entry>
+  <entry key="basic_textareaLabel">Textfeld</entry>
+  <entry key="basic_linkAction">Klicke Link</entry>
+  <entry key="basic_buttonAction">Klicke Knopf</entry>
+  <entry key="basic_lastActionLabel">Letzter Klick</entry>
+  <entry key="basic_text_input">Eingabefelder für verschiedene Arten von Text: einzeilig, mehrzeilig, formatiert.</entry>
+  <entry key="basic_text_select">Auswahlelemente erlauben die Eingabe von einer oder mehreren Optionen.</entry>
+  <entry key="basic_text_action">Steuerelemente für die Navigation und zum Ausführen von Aktionen.</entry>
+
+<!--  sheet -->
+  <entry key="sheet_text">Das Sheet-Control bietet eine einfache Möglichkeit tabellarische Daten darzustellen.
+    Die wichtigsten Eigenschaften sind: &lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Paging:
+    Es wird nur ein Teil der Gesamtliste angezeigt.   Über die Pfeilknöpfe kann in der Liste navigiert werden.
+    &lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Sortierung: Durch Drücken auf die Spaltenüberschrift
+    kann die entsprechende Spalte sortiert werden.&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Inline-Editing:
+    Es können bei Bedarf Werte   direkt in die Tabelle eingegeben werden.
+    &lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Die Spaltenbreite kann direkt mit der Maus
+    manipuliert werden.&lt;/li&gt; &lt;/ul&gt;
+    In diesem Beispiel ist in applikationsspezifischer Sorter hinterlegt, der die Sonne immer oben erscheinen lässt.
+  </entry>
+  <entry key="sheet_resetTip">Hier klicken um den Orginalzustand der Spaltenbreiten wiederherzustellen.</entry>
+  <entry key="sheet_configTip">Hier klicken zum Einstellen der Tabellenkonfiguration.</entry>
+  <entry key="sheet_configTitle">Tabelle konfigurieren</entry>
+
+<!--  tree -->
+  <entry key="tree_text">Das Tree-Control stellt einen Baum dar, der aus Applikationsdaten erzeugt wird. Die wichtigsten Eigenschaften sind: &lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Die Darstellung von Icons und Baumstruktur wird   über Attribute gesteuert.&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Die Möglichkeit den Baum als "single" oder "multiselect" zu definieren,   also einen oder mehrere Knoten auszuwählbar zu machen.&lt;/li&gt; &lt;li style=" [...]
+  <entry key="treeShowIcons">Symbole darstellen</entry>
+  <entry key="treeShowRoot">Wurzel darstellen</entry>
+  <entry key="treeShowJunctions">Linien darstellen</entry>
+  <entry key="treeShowRootJunction">Wurzellinie darstellen</entry>
+  <entry key="treeMultiselect">Auswählbar</entry>
+  <entry key="treeMutable">Veränderbar</entry>
+  <entry key="treeLabel">Tree</entry>
+  <entry key="treeListboxLabel">Listbox</entry>
+
+  <entry key="none">Nicht Auswählbar</entry>
+  <entry key="single">Einfache Auswahl</entry>
+  <entry key="singleLeafOnly">Einfache Auswahl, nur Blätter</entry>
+  <entry key="multi">Mehrfach Auswahl</entry>
+  <entry key="multiLeafOnly">Mehrfach Auswahl, nur Blätter</entry>
+  <entry key="siblingLeafOnly">Mehrfach Auswahl, nur Blätter einer Ebene</entry>
+
+<!--  tab -->
+  <entry key="tab_text">Das Tab-Control stellt so genannte Tab-Panels zur Verfügung. &lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Die Steuerung kann server- oder clientseitig erfolgen.&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Tab-Controls können verschachtelt werden.&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Innerhalb von Tab-Controls können wiederum   beliebige Controls angeordnet werden.&lt;/li&gt; &lt;/ul&gt;</entry>
+  <entry key="tabSwitchTypeClient">Clientseitiges Umschalten</entry>
+  <entry key="tabSwitchTypeReloadTag">Serverseitges Umschalten per Ajax</entry>
+  <entry key="tabSwitchTypeReloadPage">Vollständig neu laden</entry>
+  <entry key="tabPlanet">_Planetendaten</entry>
+  <entry key="tabInsolar">im _Sonnensystem</entry>
+  <entry key="closeButtonTip">Diesen Reiter für einen Request schließen</entry>
+  <entry key="tabMoons">Monde</entry>
+
+<!--  solar -->
+  <entry key="solarPlanetDiameter">Durchmesser</entry>
+  <entry key="solarPlanetMass">Masse</entry>
+  <entry key="solarPlanetSunDistance">Entfernung zur Sonne</entry>
+  <entry key="solarPlanetTimeOfCirculation">Umlaufzeit</entry>
+ <!--solarArrayName=Name -->
+ <!--solarArrayNumber=raute  -->
+  <entry key="solarArrayNumberTip">Nummer</entry>
+ <!--solarArrayOrbit=Orbits -->
+  <entry key="solarArrayDistance">Entfernung</entry>
+  <entry key="solarArrayPeriod">Umlauf</entry>
+  <entry key="solarArrayPopulation">Bevölkerung</entry>
+  <entry key="solarPagingSheet">Tabelle mit Seitenverwaltung</entry>
+
+<!--  toolbar -->
+  <entry key="toolbar_closePopupAction">Popup Fenster schließen</entry>
+  <entry key="toolbar_popupText">Zum schließen dieses Fensters den Button drücken.</entry>
+  <entry key="toolbar_dropDownAction">DropDown</entry>
+  <entry key="toolbar_buttonAction">Text Button</entry>
+  <entry key="toolbar_sampleTitle">Toolbar Beispiel</entry>
+  <entry key="toolbar_text1">Toolbars werden genutzt um kontextabhängige Aktionen in Box Elementen zur Verfügung zu stellen:
+  &lt;ul style="margin-top: 2px;"&gt;
+  &lt;li style="line-height: 130%;"&gt;Toolbars können aus Bildern, Text oder beidem bestehen.&lt;/li&gt;
+  &lt;li style="line-height: 130%;"&gt;Toolbars können in den Header einer Box integriert werden.&lt;/li&gt;
+  &lt;li style="line-height: 130%;"&gt;Aktionen können als Drop Down Menü dargestellt werden.&lt;/li&gt;
+  &lt;/ul&gt;
+    </entry>
+
+<!--  validation -->
+  <entry key="validation_description">Beschreibung</entry>
+  <entry key="validation_number">Zahl</entry>
+  <entry key="validation_price">Preis</entry>
+  <entry key="validation_submit">Übernehmen</entry>
+  <entry key="validation_text">Tobago unterstützt komfortable Möglichkeiten zur Validierung von Benutzereingaben. &lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Es steht syntaktische und sematische Validierung zur Verfügung.&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Fehlermeldungen können beliebig im Userinterface plaziert werden.&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Eingabeelemente, für die Fehleingaben erfolgt sind, können hervorgehoben werden [...]
+
+<!--  form -->
+  <entry key="form_outTitle">Äusseres Formular</entry>
+  <entry key="form_text1">&lt;li style="line-height: 130%;"&gt;Werte in der ersten Form werden beim submit der zweiten form temporär gespeichert, während der Wert aus der 2. Form ins Model geschrieben wird.&lt;/li&gt;&lt;li style="line-height: 130%;"&gt;Beim submit beider Forms werden beide Werte in Model geschrieben.&lt;/li&gt;&lt;li style="line-height: 130%;"&gt;Ist Das erste Input mit einem ungültigen Wert gefüllt und die zweite Form wird mit einem gültigen Wert submitted, ist die Val [...]
+  <entry key="form_text2">Tobago unterstützt verschachtelte Forms und kann jede Form separat behandeln:&lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Werte können separat im Model gespeichert werden, während bereits ausgefüllte andere Forms Ihre Werte (temporär) behalten.&lt;/li&gt;&lt;li style="line-height: 130%;"&gt;Für den Fall daß für einzelne Forms Validierung aktiviert ist, der Wert aber nur temporär gespeichert wird, ist die Validierung deaktiviert. Erst  [...]
+  <entry key="form_in1Title">Erstes inneres Formular</entry>
+  <entry key="form_in2Title">Zweites inneres Formular</entry>
+  <entry key="newValue1">Neuer Wert</entry>
+  <entry key="modelValue1">Wert im Model</entry>
+  <entry key="submitForm1">Formular 1 Übernehmen</entry>
+  <entry key="newValue2">Neuer Wert</entry>
+  <entry key="modelValue2">Wert im Model</entry>
+  <entry key="submitForm2">Formular 2 Übernehmen</entry>
+  <entry key="submitAll">Alle Formulare Übernehmen</entry>
+
+<!--  theme -->
+  <entry key="theme_title">Einstellung des Designs</entry>
+
+<!--  browser -->
+  <entry key="browser_sampleTitle">Browser Beispiel</entry>
+  <entry key="browser_text">Mit Tobago werden Webanwendungen unabhängig von Browsern entwickelt. Die Unterstützung verschiedener Browser findet im JSF Render Kit statt und hat keinen direkten Einfluss auf die Entwicklung der Businesslogik. &lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Tobago unterstützt gängige Browser: Internet Explorer, Mozilla und Netscape&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Tobago reagiert auf den HTTP Header 'User-Agent' und ka [...]
+
+<!--  locale -->
+  <entry key="locale_title">Sprach- und länderspezifische Einstellungen</entry>
+  <entry key="locale_label">Sprache/Land</entry>
+  <entry key="locale_submit">Übernehmen</entry>
+  <entry key="locale_text">Tobago unterstützt Internationalisierung und Lokalisierung. &lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Intern wird Unicode verwendet&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Texte für verschiedene Länder und Sprachen können in Resource Bundles ausgelagert werden.&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Zusätzlich zu Texten können beliebige Resourcen wie Bilder und Skripte lokalisiert werden.&lt;/li&gt; &lt;/ul&gt;</entry>
+
+<!--  layout -->
+  <entry key="layout_exampleTitle">Layout Beispiel: Persönliche Informationen</entry>
+  <entry key="layout_salutation">Anrede</entry>
+  <entry key="layout_firstName">Vorname</entry>
+  <entry key="layout_lastName">Nachname</entry>
+  <entry key="layout_co">c/o</entry>
+  <entry key="layout_street">Straße</entry>
+  <entry key="layout_streetNumber">Nr.</entry>
+  <entry key="layout_zipCode">PLZ</entry>
+  <entry key="layout_city">Stadt</entry>
+  <entry key="layout_note">Anmerkung</entry>
+  <entry key="layout_text">Tobago vereinfacht das Gestalten von Webseiten. &lt;ul style="margin-top: 2px;"&gt; &lt;li style="line-height: 130%;"&gt;Bequeme Erstellung von ein- und mehrspaltigen Formularen&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Zellen können mehrere Zeilen und Spalten überspannen&lt;/li&gt; &lt;li style="line-height: 130%;"&gt;Automatisches Ausrichten von Beschriftungen für Eingabefelder&lt;/li&gt; &lt;/ul&gt;</entry>
+
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_en.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_en.properties.xml
new file mode 100644
index 0000000..9bd08c2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_en.properties.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="notTranslated"></entry>
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_ja.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_ja.properties.xml
new file mode 100644
index 0000000..7f9b0aa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_ja.properties.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="notTranslated">残念、十分にまだ変換される</entry>
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_ru.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_ru.properties.xml
new file mode 100644
index 0000000..f00c86b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/resources/org/apache/myfaces/tobago/example/demo/demo_ru.properties.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="notTranslated">огорченно, полно переведено пока</entry>
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/META-INF/context.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/META-INF/context.xml
new file mode 100644
index 0000000..e624eee
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/META-INF/context.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+    This file is for Apache Tomcat.
+    The property "antiResourceLocking" is needed for proper redeploy under Windows.
+-->
+
+<Context antiResourceLocking="true" >
+</Context>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/beans.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/beans.xml
new file mode 100644
index 0000000..9b4333e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/beans.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- marker file for CDI -->
+
+<beans xmlns="http://java.sun.com/xml/ns/javaee"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
+
+   <interceptors>
+   </interceptors>
+
+   <decorators>
+   </decorators>
+
+</beans>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/faces-config.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..af119d1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<faces-config
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
+    version="2.0">
+
+  <application>
+    <navigation-handler>
+      org.apache.myfaces.tobago.example.demo.PrettyUrlForMenuNavigationHandler
+    </navigation-handler>
+    <locale-config>
+      <default-locale>en</default-locale>
+      <supported-locale>en_US</supported-locale>
+      <supported-locale>en_GB</supported-locale>
+      <supported-locale>de</supported-locale>
+      <supported-locale>de_DE</supported-locale>
+      <supported-locale>de_AT</supported-locale>
+      <supported-locale>de_CH</supported-locale>
+      <supported-locale>es</supported-locale>
+      <supported-locale>ja</supported-locale>
+      <supported-locale>ja_JP</supported-locale>
+      <supported-locale>ru</supported-locale>
+      <supported-locale>ru_RU</supported-locale>
+      <supported-locale>zh</supported-locale>
+      <supported-locale>zh_TW</supported-locale>
+    </locale-config>
+    <resource-bundle>
+      <base-name>org.apache.myfaces.tobago.example.demo.DemoBundle</base-name>
+      <var>demoBundle</var>
+    </resource-bundle>
+  </application>
+
+  <converter>
+    <converter-id>salutationId</converter-id>
+    <converter-class>org.apache.myfaces.tobago.example.data.SalutationConverter</converter-class>
+  </converter>
+
+  <lifecycle>
+    <phase-listener>org.apache.myfaces.tobago.example.demo.SynchronizeNavigationPhaseListener</phase-listener>
+    <!--<phase-listener>org.apache.myfaces.tobago.util.DebugPhaseListener</phase-listener>-->
+  </lifecycle>
+
+  <lifecycle>
+    <phase-listener>
+      org.apache.myfaces.tobago.example.demo.clientConfig.ClientConfigPhaseListener
+    </phase-listener>
+  </lifecycle>
+
+  <managed-bean>
+    <managed-bean-name>clientConfigController</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.demo.clientConfig.ClientConfigController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>clientConfigController2</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.demo.clientConfig.ClientConfigController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <converter>
+    <converter-id>org.apache.myfaces.tobago.example.demo.OnOffConverter</converter-id>
+    <converter-class>org.apache.myfaces.tobago.example.demo.OnOffConverter</converter-class>
+  </converter>
+
+  <factory>
+    <exception-handler-factory>
+      org.apache.myfaces.tobago.example.demo.TestExceptionHandlerFactory
+    </exception-handler-factory>
+  </factory>
+
+</faces-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/sun-web.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/sun-web.xml
new file mode 100644
index 0000000..132427b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/sun-web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN"
+    "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
+<!--
+  This file is needed to run the application on Glassfish 3.0
+  Also, we have to add EL support to the pom.xml (el-ri.jar)
+  The reason may be: http://java.net/jira/browse/JAVASERVERFACES-1828
+-->
+<sun-web-app>
+  <class-loader delegate="false"/>
+<!--
+  <property name="useMyFaces" value="true"/>
+-->
+  <property name="useBundledJsf" value="true"/>
+</sun-web-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml
new file mode 100644
index 0000000..f08d086
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/tobago-config.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+    version="2.0">
+
+  <name>demo</name>
+
+  <ordering>
+    <after>
+      <name>tobago-theme-speyside</name>
+    </after>
+  </ordering>
+
+<!-- using all available themes, if this is not set -->
+  <theme-config>
+    <default-theme>standard</default-theme>
+    <supported-theme>speyside</supported-theme>
+    <!-- TODO: Can be removed after closing TOBAGO-1664 -->
+    <!--<supported-theme>scarborough</supported-theme>-->
+    <!--<supported-theme>richmond</supported-theme>-->
+    <!--<supported-theme>charlotteville</supported-theme>-->
+  </theme-config>
+
+  <resource-dir>tobago-resource</resource-dir>
+
+  <!-- This is needed for the testing functionality of the demo, it works with iframes -->
+  <prevent-frame-attacks>false</prevent-frame-attacks>
+
+  <!-- XXX for the jQuery tests we need 'report-only' here -->
+  <content-security-policy mode="off">
+    <!-- XXX With CSP Tobago 3.0.x is currently not working 100% see TOBAGO-1534,
+         XXX because of JSF-AJAX we need 'unsafe-eval' -->
+    <directive>script-src 'self' 'unsafe-eval'</directive>
+    <directive>frame-src https://maps.google.com</directive>
+  </content-security-policy>
+
+<!-- this is the default...
+  <sanitizer>
+    <sanitizer-class>org.apache.myfaces.tobago.sanitizer.JsoupSanitizer</sanitizer-class>
+    <properties>
+      &lt;!&ndash;
+       Use one of: basic, basicWithImages, relaxed, simpleText or none
+       &ndash;&gt;
+      <entry key="whitelist">relaxed</entry>
+    </properties>
+  </sanitizer>
+-->
+
+  <renderers>
+
+    <renderer>
+      <name>Sheet</name>
+      <supported-markup>
+        <markup>sun</markup>
+        <markup>planet</markup>
+        <markup>moon</markup>
+        <markup>lightred</markup>
+        <markup>lightgreen</markup>
+      </supported-markup>
+    </renderer>
+
+    <renderer>
+      <name>Out</name>
+      <supported-markup>
+        <markup>demoSeconds</markup>
+      </supported-markup>
+    </renderer>
+
+  </renderers>
+
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/web.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..528c6e3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<web-app
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+    version="3.0">
+
+  <display-name>Tobago Demo Application</display-name>
+
+  <!-- for jetty also check src/test/jetty/override-myfaces-web.xml or src/test/jetty/override-mojarra-web.xml -->
+  <context-param>
+    <param-name>javax.faces.PROJECT_STAGE</param-name>
+    <!--<param-value>Development</param-value>-->
+    <param-value>Production</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>com.sun.faces.validateXml</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+   <!-- disable error handling from myfaces, needed for the demo -->
+  <context-param>
+    <param-name>org.apache.myfaces.ERROR_HANDLING</param-name>
+    <param-value>false</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
+    <param-value>*.xhtml</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.FACELETS_RESOURCE_RESOLVER</param-name>
+    <param-value>org.apache.myfaces.tobago.facelets.MetaInfResourcesClasspathResourceResolver</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <listener>
+    <listener-class>org.apache.myfaces.tobago.example.demo.info.ActivitySessionListener</listener-class>
+  </listener>
+
+  <!-- activate this for some containers -->
+  <!--
+  <listener>
+    <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class>
+  </listener>
+  -->
+
+<!-- this is not needed for websphere 8.5 -->
+  <listener>
+    <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationListener</listener-class>
+  </listener>
+
+<!-- this is an alternative to the WebBeansConfigurationListener
+     you need it e.g. for Tomcat 5.5 or WebSphere 6.1 (see TOBAGO-1043)
+-->
+<!--
+  <filter>
+      <filter-name>webbeans</filter-name>
+      <filter-class>org.apache.webbeans.servlet.WebBeansConfigurationFilter</filter-class>
+    </filter>
+
+  <filter-mapping>
+      <filter-name>webbeans</filter-name>
+      <servlet-name>FacesServlet</servlet-name>
+      <dispatcher>REQUEST</dispatcher>
+      <dispatcher>ERROR</dispatcher>
+  </filter-mapping>
+
+  <listener>
+    <listener-class>org.apache.webbeans.servlet.WebBeansConfigurationHttpSessionListener</listener-class>
+  </listener>
+-->
+
+  <filter>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <filter-class>org.apache.myfaces.tobago.internal.webapp.LoggingMdcFilter</filter-class>
+  </filter>
+  <filter-mapping>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+  <!-- FacesServlet -->
+
+  <servlet>
+    <servlet-name>FacesServlet</servlet-name>
+    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+    <load-on-startup>3</load-on-startup>
+    <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+    <multipart-config>
+      <max-request-size>20000000</max-request-size>
+      <max-file-size>1000000</max-file-size>
+    </multipart-config>
+  </servlet>
+
+  <servlet-mapping>
+    <servlet-name>FacesServlet</servlet-name>
+    <url-pattern>/faces/*</url-pattern>
+  </servlet-mapping>
+
+  <!-- Error Page -->
+
+  <error-page>
+    <error-code>404</error-code>
+    <location>/faces/error/404.xhtml</location>
+  </error-page>
+
+  <error-page>
+    <error-code>500</error-code>
+    <location>/faces/error/exception.xhtml</location>
+  </error-page>
+
+
+  <error-page>
+    <exception-type>java.io.FileNotFoundException</exception-type>
+    <location>/faces/error/404.xhtml</location>
+  </error-page>
+
+  <error-page>
+    <exception-type>java.lang.Exception</exception-type>
+    <location>/faces/error/exception.xhtml</location>
+  </error-page>
+
+  <!-- The Usual Welcome File List -->
+  <welcome-file-list>
+    <welcome-file>index.html</welcome-file>
+  </welcome-file-list>
+
+  <session-config>
+    <cookie-config>
+      <http-only>true</http-only>
+    </cookie-config>
+  </session-config>
+
+  <security-constraint>
+    <display-name>Security Constraint</display-name>
+    <web-resource-collection>
+      <web-resource-name>Application Area</web-resource-name>
+      <url-pattern>/faces/content/30-concept/80-security/20-roles/*</url-pattern>
+      <url-pattern>/content/30-concept/80-security/20-roles/*</url-pattern>
+    </web-resource-collection>
+    <auth-constraint>
+      <role-name>demo-admin</role-name>
+      <role-name>demo-guest</role-name>
+    </auth-constraint>
+  </security-constraint>
+
+  <login-config>
+    <auth-method>FORM</auth-method>
+    <realm-name>demo-realm</realm-name>
+    <form-login-config>
+      <form-login-page>/faces/login.xhtml</form-login-page>
+      <form-error-page>/faces/login.xhtml</form-error-page>
+    </form-login-config>
+  </login-config>
+
+  <security-role>
+    <role-name>demo-admin</role-name>
+  </security-role>
+  <security-role>
+    <role-name>demo-guest</role-name>
+  </security-role>
+
+</web-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml
new file mode 100644
index 0000000..5f1a6cf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/30-new+in+3+0/new+in+3+0.xhtml
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.new_in_3_0}"/>
+  <p>In November 2015 the first alpha version of 3.0.0 has been released,
+    the first final release followed in December 2016.
+    Here was a quick overview over the features and changes made in the last time to release this major revision.</p>
+  <p>Tobago 3.0.0 contains several entries in
+    <tc:link label="Jira"
+             link="http://issues.apache.org/jira/secure/ReleaseNote.jspa?projectId=12310273&amp;styleName=Html&amp;version=12325880"/>
+    and most of them are exclusive in this version.</p>
+  <p>Please take also a look at the <tc:link label="Migration from Tobago 2.0 to 3.0" link="dummy"/> guide.</p>
+
+  <tc:section label="Overview and History">
+    <p>Until Tobago 2.0 the layout was computed on the server, to make advanced features available for comfortable web
+      application.</p>
+    <p>With CSS3 and HTML5 it is possible these days, to make advanced layout managers implemented in the browser.</p>
+  </tc:section>
+
+  <tc:section label="New Features and Enhancements">
+    <b>Bootstrap</b>
+    <p>The base theme that comes with Tobago changes from plain CSS to Twitters Bootstrap.
+      So, you applications have the advantage of modern HTML5 web applications, with less coding.</p>
+
+    <b>New Layout Managers</b>
+    <ul>
+      <li>Segment Layout (uses the 12 columns layout from Bootstrap)</li>
+      <li>Flex Layout (CSS3)<br/>You may replace the GridLayout from Tobago 2.0 with FlexLayout.</li>
+      <li>Flow Layout</li>
+      <li>The new layout managers, have be written be bit more concised: Using as container instead of a facet.</li>
+    </ul>
+
+    <b>tx library</b>
+    <ul>
+      <li>The tx library no longer needed</li>
+      <li>The label is integrated into the tc library.</li>
+      <li>This results in a more intuitive API</li>
+      <li>Rich variations of positioning the label with new attribute labelLayout</li>
+    </ul>
+
+    <b>New tags</b>
+    <ul>
+      <li><tc:link label="&lt;tc:section>"
+                   link="#{request.contextPath}/faces/content/20-component/050-container/40-section/section.xhtml"/>
+      </li>
+      <li><tc:link label="&lt;tc:header> &amp; &lt;tc:footer>"
+                   link="#{request.contextPath}/faces/content/20-component/050-container/50-header+footer/header+footer.xhtml"/>
+      </li>
+      <li><tc:link label="&lt;tc:figure>"
+                   link="#{request.contextPath}/faces/content/20-component/020-output/45-figure/figure.xhtml"/></li>
+    </ul>
+
+    <b>Improved tags</b>
+    <ul>
+      <li>The <code class="language-markup">&lt;tc:in/></code> tag may be extended to an
+        <tc:link label="#{demoBundle.group}"
+                 link="#{request.contextPath}/faces/content/20-component/010-input/50-input-group/group.xhtml"/>.
+      </li>
+      <li>A <code>size</code> attribute is added for
+        <ul>
+          <li><tc:link label="&lt;tc:selectOneListbox>"
+                       link="#{request.contextPath}/faces/content/20-component/030-select/40-selectOneListbox/selectOneListbox.xhtml"/>,
+          </li>
+          <li><tc:link label="&lt;tc:selectManyListbox>"
+                       link="#{request.contextPath}/faces/content/20-component/030-select/60-selectManyListbox/selectManyListbox.xhtml"/>,
+          </li>
+          <li><tc:link label="&lt;tc:selectManyShuffle>"
+                       link="#{request.contextPath}/faces/content/20-component/030-select/70-selectManyShuttle/selectManyShuttle.xhtml"/> and
+          </li>
+          <li><tc:link label="&lt;tc:treeListbox>"
+                       link="#{request.contextPath}/faces/content/20-component/090-tree/04-listbox/tree-listbox.xhtml"/>.
+          </li>
+        </ul>
+      </li>
+      <li>Only <code>disabled="true"</code> must be set to disable an
+        <tc:link label="image"
+                 link="#{request.contextPath}/faces/content/20-component/020-output/40-image/image.xhtml"/>.
+      </li>
+      <li><tc:link label="&lt;tc:sheet>"
+                   link="#{request.contextPath}/faces/content/20-component/080-sheet/sheet.xhtml"/>
+        <ul>
+          <li>Constraints are no londer needed to set a multi-line header.</li>
+          <li>A width can be defined for columns which will influence the auto layout of the browser.</li>
+        </ul>
+      </li>
+    </ul>
+
+    <b>Internal Refactoring</b>
+    <ul>
+      <li>Using standard ajax mechanism.</li>
+      <li>The clientId will be now rendered to the rool element in HTML of a component.</li>
+      <li>Change the icon format from GIF to PNG.</li>
+    </ul>
+
+    <b>Collapsible concept</b>
+    <p>There is a new
+      <tc:link label="collapsible concept"
+               link="#{request.contextPath}/faces/content/30-concept/53-collapsible/collapsible.xhtml"/>
+      for <code class="language-markup">&lt;tc:box></code>, <code class="language-markup">&lt;tc:section></code>,
+      <code class="language-markup">&lt;tc:panel></code> and <code class="language-markup">&lt;tc:popup></code>
+      where the collapse state can be switched via an <code class="language-markup">&lt;tc:operation></code>.
+    </p>
+
+    <b>More changes</b>
+    <ul>
+      <li>File upload now uses Servlet 3.0 instead of Commons Fileupload. This simplifies the setup.</li>
+      <li>Font Awesome as an icon library.</li>
+      <li>ARIA support codes are added. Those can be used in renderer classes.</li>
+      <li>Resources can be excluded from parent theme.</li>
+      <li>ResourceBundles support parameters</li>
+      <li>The <code>lang</code> attribute of the HTML root tag will be rendered now.</li>
+      <li><tc:link label="#{demoBundle.messages}"
+                   link="#{request.contextPath}/faces/content/20-component/020-output/30-messages/messages.xhtml"/>
+        are closeable now.
+      </li>
+      <li>Custom CSS classes can be added to a component.</li>
+      <li>Support more units than 'px'. Now ex, em, mm, cm, in can be used as well.</li>
+      <li>The <code>link</code> attribute of
+        <tc:link label="&lt;tc:link> &amp; &lt;tc:button>"
+                 link="#{request.contextPath}/faces/content/20-component/040-command/00-button+link/button+link.xhtml"/>
+        does support rightClick -&gt; newTab.
+      </li>
+    </ul>
+
+    <b>Removed</b>
+    <ul>
+      <li>The AutoAccessKey feature (using underscore to indicate next character as an access key) is removed.
+        Now the <code>accessKey</code> attribute must be used.
+      </li>
+      <li>JSP support removed.</li>
+      <li>The tag <code lang="language-markup">&lt;tc:time></code> is removed. Use
+        <tc:link label="&lt;tc:date>"
+                 link="#{request.contextPath}/faces/content/20-component/010-input/40-date/date.xhtml"/> instead.
+      </li>
+    </ul>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/97-migration/migration30.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/97-migration/migration30.xhtml
new file mode 100644
index 0000000..9c324fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/97-migration/migration30.xhtml
@@ -0,0 +1,304 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.migration30}"/>
+
+  <tc:section label="Migration from Tobago 2.0 to 3.0">
+
+<p>
+  There a are several migration steps to do, dependent of the application
+  you want to migrate. The steps can be classified by
+</p>
+
+    <ul>
+      <li>Tag library</li>
+      <li>Java API</li>
+      <li>CSS</li>
+      <li>JavaScript</li>
+      <li>External components (for Java, CSS, Javascript)</li>
+    </ul>
+
+    <p>
+      Most of these steps are relatively simple to carry out.
+      Just replace "this" with "that" and so on.
+      Some of them can be done with regular expressions.
+    </p>
+
+    <tc:section label="Tag Library">
+      <tc:section label="JSP">
+        JavaServer Pages are no longer supported. You need to migrate to Facelets as VDL.
+        You may do that before migrating to Tobago 3.
+      </tc:section>
+
+      <tc:section label="Replacing tx with tc">
+        <p>
+          <code class="language-markup">&lt;tx:in label="a" fieldId="b" id="c" /&gt;</code>
+          will be transformed to
+          <code class="language-markup">&lt;tc:in label="a" id="c" /&gt;</code>.
+          The id of the input element in HTML is id="c::field".
+        </p>
+
+        <p> There is a little conflict between the "label" attribute used in the JSF spec. and the Tobago tx: label:
+          Tobago means it should be displayed, and JSF spec. means that this should be used to display messages.
+          In most cases there is no issue for that. But for the case that the application need a message label, but
+          should not be displayed we need a new attribute:
+        </p>
+
+        <p> (preliminary) "labelPosition" or "labelLayout" with value "none"
+          With this attribute we may advise the renderer also the position of the label.
+          Or, using an attribute "renderLable"...
+        </p>
+      </tc:section>
+
+      <tc:section label="&lt;tc:time&gt; -> &lt;tc:date&gt;">
+        You need to set the <code class="language-markup">&lt;f:convertDateTime type="time"\/&gt;</code>
+        inside the <code class="language-markup">&lt;tc:date/&gt;</code>.
+      </tc:section>
+
+      <tc:section label="&lt;tc:cell&gt;">
+        Replace all <code class="language-markup">&lt;tc:cell/&gt;</code>
+        with <code class="language-markup">&lt;tc:panel/&gt;</code>.
+        Dependent of the used layout manager, these tags may be dropped completely.
+      </tc:section>
+
+      <tc:section label="Layout manager no longer as facet.">
+
+        <p>
+          The layout managers are no longer a facet of a container.
+          They are in the tree hierarchy explicitly.
+        </p>
+        <p>
+          Old:
+        </p>
+        <pre><code class="language-markup">&lt;tc:panel&gt;
+  &lt;f:facet name="layout"&gt;
+    &lt;tc:flowLayout/&gt;
+  &lt;/f:facet&gt;
+  ... content ...
+&lt;/tc:panel&gt;</code></pre>
+        <p>
+          New:
+        </p>
+        <pre><code class="language-markup">&lt;tc:flowLayout&gt;
+  ... content ...
+&lt;/tc:flowLayout&gt;</code></pre>
+      </tc:section>
+      <tc:section label="&lt;tc:image&gt;">
+        <code class="language-markup">&lt;tc:image/&gt;</code>
+        has no longer the attributes <code class="language-markup">width</code>
+        and <code class="language-markup">height</code>, please use a
+        <code class="language-markup">&lt;tc:style/&gt;</code>child tag instead.
+      </tc:section>
+      <tc:section label="&lt;tc:sheet&gt;">
+        tc:column with f:facet name="dropDownBox" can now easily and much more flexible implemented with
+        the header facet of the tc:sheet. Example:
+        <tc:link label="Sheet Filter"
+                 link="#{request.contextPath}/faces/content/20-component/080-sheet/50-filter/sheet-filter.xhtml" />
+      </tc:section>
+      <tc:section label="Menu">
+        The Menu tags tc:menu, tc:menuBar, tc:menuCommand and tc:menuSeparator are no longer available and
+        needs to be migrated to tc:links or tc:bar or tc:buttons with tc:link and tc:separator inside.
+      </tc:section>
+      <tc:section label="Popup">
+        The popup was implemented new, using a general concept of collapsible in Tobago.
+        <tc:section label="&lt;tc:popupReference&gt;">
+          This tag is removed.
+        </tc:section>
+        <tc:section label="&lt;tc:popup&gt;">
+          The tc:popup tag is no longer a facet of a command. The tag can be put anywhere on the page.
+          The open/close commands now can be used flexible
+        </tc:section>
+        Example:
+        <tc:link label="popup"
+                 link="#{request.contextPath}/faces/content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.xhtml" />
+      </tc:section>
+
+    </tc:section>
+
+    <tc:section label="Java API">
+      <tc:section label="ActionListenerImpl">
+        Class is no longer present, you should use a JSF 2 exception handler instead.
+      </tc:section>
+      <tc:section label="Renderer classes">
+        The API of the RendererBase class has changed a bit.
+        Also the automatic renderer selection has been dropped.
+        If you write your own renderer for existing classes, you now need to register it in
+        the faces-config.xml as ususal in JSF.
+      </tc:section>
+      <tc:section label="Typesafety">
+        <p>
+          To have typesafe code many Java classes to provide constants are migrated to Java enums,
+          e. g. <code>org.apache.myfaces.tobago.component.Attributes</code>.
+        </p>
+      </tc:section>
+
+    </tc:section>
+
+    <tc:section label="CSS">
+      <tc:section label="Bootstrap">
+        Tobago 3 uses the great <tc:link label="Bootstrap" link="http://v4-alpha.getbootstrap.com/"/> CSS library.
+        Currently in version 4.0.0-alpha.5.
+      </tc:section>
+      <tc:section label="Class names">
+        Because of the use of the Bootstrap lib, some Tobago CSS classes are no longer needed, and
+        has been
+      </tc:section>
+      <tc:section label="box-sizing">
+        Changed from content-box to border-box.
+      </tc:section>
+    </tc:section>
+
+    <tc:section label="JavaScript">
+
+    </tc:section>
+
+    <tc:section label="External components and dependencies">
+      <tc:section label="File upload">
+        <tc:section label="Servlet API 3.0">
+          Tobago 3 requires Servlet API 3.0. Tought the file upload uses
+          <code class="language-java">javax.servlet.http.Part</code>
+          instead of <code class="language-java">org.apache.commons.fileupload.FileItem</code>.
+        </tc:section>
+        <tc:section label="Filter">
+          You no long need to define a TobagoMultipartFormdataFilter in the web.xml.
+        </tc:section>
+        <tc:section label="Dependencies">
+          <p>
+            There is no longer a tobago-fileupload.jar.
+          </p>
+          <p>
+            Remove the dependency to commons-fileupload.jar in your web app, if there is any.
+          </p>
+        </tc:section>
+        <tc:section label="FacesServlet Configuration">
+          If using JSF 2.0 or 2.1 you will need to add a tag <code>&lt;multipart-config&gt;</code>
+          Tag to the FacesServlet config in the <code>web.xml</code>. Since JSF 2.2 this is not needed.
+        </tc:section>
+        Example:
+        <tc:link label="File Upload"
+                 link="#{request.contextPath}/faces/content/20-component/100-upload/upload.xhtml" />
+      </tc:section>
+
+    </tc:section>
+
+
+
+
+    <!-- todo: refactor from APT to HTML -->
+
+<pre>
+
+  <b>TODO:</b>
+
+    Because of the changed layout model (no longer on the server, but with browser CSS) there a some
+    classes, methods and parameters removed.
+
+
+    * AbstractUIPage.getActionPosition()
+
+    * AbstractUIPage.setActionPosition()
+
+    * class Box
+
+    * class Dimension
+
+    * class Position
+
+    * ClientProperties.pageWidth
+
+    * ClientProperties.pageHeight
+
+    * <code class="language-markup">&lt;tc:gridLayoutConstraint&gt;</code> -> <code class="language-markup">&lt;tc:span&gt;</code> (only for attributes columnSpan and rowSpan)
+
+    * <code class="language-markup">&lt;tc:gridLayoutConstraint&gt;</code> -> <code class="language-markup">&lt;tc:style&gt;</code> (all other attributes)
+
+    * <code class="language-markup">&lt;tc:toolBar&gt;</code> -> <code class="language-markup">&lt;tc:buttons&gt;</code>
+    * <code class="language-markup">&lt;tc:toolBarCommand&gt;</code> -> <code class="language-markup">&lt;tc:button&gt;</code>
+
+    * If using <code class="language-markup">&lt;tc:page&gt;</code> with the attributes state, width, height: remove the attributes
+
+    * Replace facet 'action' with 'load' for <code class="language-markup">&lt;tc:page&gt;</code>
+
+    <code class="language-markup">&lt;f:facet name="load"&gt;</code> contain an instance of UICommand (tc:command).
+
+    * TODO: attribute renderPartially is replaced by f:ajax
+
+    * TODO: use ExternalContext.redirect instead of AjaxUtils.redirect
+
+  * Replace <code>AjaxUtils.getRequestPartialIds()</code> with
+    <code>FacesContext.getPartialViewContext().getExecuteIds()</code> or
+    <code>FacesContext.getPartialViewContext().getRenderIds()</code> respectively.
+
+    * TODO: Move data from ClientProperties to TobagoContext
+
+    <code class="language-markup">&lt;tc:mediator&gt;</code> removed
+
+    If you need a Tobago component to set e. g. some style in a renderer as a replacement,
+    use a simple <code class="language-markup">&lt;tc:panel&gt;</code>.
+
+    Tango Icons
+
+    Tango icon lib is no longer part of Tobago. Replaced by Font Awesome. If you need it, please
+    include it in the application.
+
+    Dependencies to JS/CSS libs: jQuery UI
+
+    Tobago uses the jQuery UI library. The library is customizable to limit the amount of JS and CSS content.
+    You will find the used modules in the header of each jQuery UI file.
+
+    * E. g. Tobago 2.0.10 contains jQuery UI 1.10.4 with these contents:
+
+    * jquery.ui.core.js
+
+    * jquery.ui.widget.js
+
+    * jquery.ui.mouse.js
+
+    * jquery.ui.position.js
+
+    * jquery.ui.draggable.js
+
+    * jquery.ui.datepicker.js
+
+    * jquery.ui.slider.js
+
+    * jquery.ui.core.css
+
+    * jquery.ui.datepicker.css
+
+    * jquery.ui.slider.css
+
+    * jquery.ui.theme.css
+
+    * Tobago 3.0.0 contains jQuery UI 1.12.1 with this component:
+
+    * widget.js
+
+    If you are using jQuery UI directly, you may add the required resources via the <code>&lt;tobago-config.xml</code>
+      and exclude the jQuery UI resource that comes with Tobago.
+
+</pre>
+
+    </tc:section>
+
+  </ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/98-migration/migration20.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/98-migration/migration20.xhtml
new file mode 100644
index 0000000..acf4919
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/98-migration/migration20.xhtml
@@ -0,0 +1,192 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.migration20}"/>
+  <tc:section label="Migration from Tobago 1.5 to 2.0">
+    <p>Tobago 2.0 has some API changes compared to Tobago 1.5.</p>
+    <p>The most changes are in the tree API, which is more easy to use, but also more flexible.</p>
+
+    <tc:section label="Artifacts (JAR-Files)">
+      <p>The following JAR files are no longer needed. They have to be removed from the project (depends on your build
+        system).</p>
+      <ul>
+        <li>tobago-taglib-extension-&lt;version>.jar</li>
+        <li>tobago-facelets-&lt;version>.jar</li>
+      </ul>
+    </tc:section>
+
+    <tc:section label="CSP">
+      <p>Tobago supports Content Security Policy (CSP) to prevent cross-site scripting (XSS) and related attacks. It is
+        specified by W3C. In short: The HTML page doesn't contain any JavaScript or CSS information. All allowed sources
+        for JavaScript, CSS and other resources have to be declared in special header. If you have own renderers or own
+        JavaScript in your application, this code also needs to support CSP, to use this feature.</p>
+
+      <b>Warning:</b>
+      <p>CSP requires a different handling of JavaScript and other resources. If you use own JavaScript in the HTML page
+        or including resources from other sites you may need to adapt your application, (or turn this feature off).</p>
+
+      <b>Configuration</b>
+      <p>To add sites to the CSP headers, add <code class="language-markup">&lt;directive></code> tags to
+        <code class="language-markup">&lt;content-security-policy></code> in the <code>tobago-config.xml</code>.</p>
+      <p>To turn off CSP, add an empty <code class="language-markup">&lt;content-security-policy mode="off"></code>
+        tag in the configuration. For development, you may also use mode="report-only", which sets the appropriate
+        header.</p>
+    </tc:section>
+
+    <tc:section label="Clickjacking">
+      <p>By default, it no longer possible to use a Tobago application in an HTML frame or iframe. This is to protect
+        against <tc:link label="Clickjacking" link="https://www.owasp.org/index.php/Clickjacking"/>. To disable this
+        feature consult the <code>tobago-config.xml</code> and set
+        <code class="language-markup">&lt;prevent-frame-attacks>false&lt;/prevent-frame-attacks></code>.</p>
+    </tc:section>
+
+    <tc:section label="Java-API">
+      <p>The class
+        <code>org.apache.myfaces.tobago.model.TreeState</code> which has been deprecated in 1.5.x is used in 2.0.x
+        with a changed API. Please check the occurrences.</p>
+      <p>Class <code>org.apache.myfaces.tobago.component.UIFileInput</code> has been renamed to
+        <code>org.apache.myfaces.tobago.component.UIFile</code>.</p>
+    </tc:section>
+
+    <tc:section label="Renderer classes">
+      <p>The set of existing renderers has been repacked from
+        <code>org.apache.myfaces.tobago.renderkit.html.scarborough.standard.tag</code> to
+        <code>org.apache.myfaces.tobago.renderkit.html.standard.standard.tag</code>.</p>
+      <p>If you have an own theme with own renderer classes implemented, which are extending the Tobago renderer
+        classes, you will need to adapt the package name of the base classes.</p>
+    </tc:section>
+
+    <tc:section label="Facelets">
+      <p>Tobago 2.0.x is using Facelets 2.0. When still using Facelets 1.1 in the current application, this must be
+        removed:</p>
+      <ul>
+        <li>Remove facelets JAR (e.g. <code>jsf-facelets-1.1.14.jar</code>) from the library.</li>
+        <li>Remove <code class="language-markup">&lt;view-handler></code>
+          <code class="language-markup">org.apache.myfaces.tobago.internal.application.ViewHandlerImpl</code>
+          <code class="language-markup">&lt;/view-handler></code> from the <code>faces-config.xml</code> file.
+        </li>
+        <li>Remove the parameter <code>javax.faces.DISABLE_FACELET_JSF_VIEWHANDLER</code> from the <code>web.xml</code>
+          file.
+        </li>
+        <li>Remove or replace the <code>facelets.*</code> entries from the <code>web.xml</code> file.</li>
+        <li>Rename all JSTL declarations from <code>xmlns:c="http://java.sun.com/jstl/core"</code> to
+          <code>xmlns:c="http://java.sun.com/jsp/jstl/core"</code> in the Facelets.
+        </li>
+        <li>Ensure the version of the faces-config tag in the <code>faces-config.xml</code> is at least 2.0.</li>
+      </ul>
+    </tc:section>
+
+    <tc:section label="Deprecated">
+      <p>There are also @Deprecated annotations in the code and some logging warning when using deprecated code via the
+        Deprecation logging category. Before and after migrating you should check your application about that.</p>
+      <p>For the migration phase you may add the tobago-deprecation.jar as dependency to your project. It contains
+        classes that has been moved (e. g. to the new internal package) or removed. So you can resolve any migration
+        steps step by step. It is not recommended to use the tobago-deprecation.jar for production.</p>
+    </tc:section>
+
+    <tc:section label="Internal">
+      <p>The package <code>org.apache.myfaces.tobago.internal</code> contains classes that should not be used directly
+        in an application. This classes may change in minor revisions without announcement. Classes in the package
+        <code>org.apache.myfaces.tobago.renderkit</code> are handled in the same manner.</p>
+    </tc:section>
+
+    <tc:section label="Tag Library">
+      <p>The main changes in the tag library are that the deprecated facets "resizeAction" and "menupopup" has been
+        removed.</p>
+    </tc:section>
+
+    <tc:section label="Suggest">
+      <p>Please use the new <code class="language-markup">&lt;tc:suggest></code> tag instead of using the inline
+        attribute inside of <code class="language-markup">&lt;tc:in></code>.</p>
+      <pre><code class="language-markup">deprecated:
+&lt;tc:in suggestMethod="\#{bean.method}"/>
+
+replacement:
+&lt;tc:in>
+  &lt;tc:suggest suggestMethod="\#{bean.method}"/>
+&lt;/tc:in></code></pre>
+      <pre><code class="language-markup">deprecated:
+&lt;tx:in suggestMethod="\#{bean.method}"/>
+
+replacement:
+&lt;tx:in>
+  &lt;tc:suggest suggestMethod="\#{bean.method}"/>
+&lt;/tx:in></code></pre>
+    </tc:section>
+
+    <tc:section label="Tree">
+      <ul>
+        <li>The Tree now extends a UIData.</li>
+        <li>The <code class="language-markup">&lt;tc:treeData></code> tag shouldn't longer be used.</li>
+        <li>The <code class="language-markup">&lt;tc:treeNode></code> has no longer the attributes: "selected",
+          "expanded", "marked", "treeMarkedListener", "treeExpansionListener"
+        </li>
+        <li>The class <code>org.apache.myfaces.tobago.model.TreeState</code> is no longer deprecated, but the
+          functionality has slightly been changed.
+        </li>
+      </ul>
+    </tc:section>
+
+    <tc:section label="Date/Time">
+      <p>The date and time input controls have been refactored. The old (deprecated) functionality can be activated via
+        <code>tobago-config.xml</code>.</p>
+      <p>If using the new: <code class="language-markup">&lt;tc:date></code> can do the job of
+        <code class="language-markup">&lt;tc:time></code>. You only need to set the
+        <code class="language-markup">&lt;f:convertDateTime type="time"></code> inside the
+        <code class="language-markup">&lt;tc:date></code>.</p>
+    </tc:section>
+
+    <tc:section label="ToolBar with dropDownMenu facet">
+      <p>Usually you need to set <code>omit="true"</code> in the
+        <code class="language-markup">&lt;tc:toolBarCommand></code>, to avoid a submit.</p>
+    </tc:section>
+
+    <tc:section label="Configuration">
+      <p>To define an own theme, please use now a file <code>tobago-config.xml</code> instead of
+        <code>tobago-theme.xml</code>. The content of <code>tobago-theme.xml</code> is a subset of the
+        <code>tobago-config.xml</code>, you have only to change the root node.</p>
+      <p>Please use the
+        <tc:link label="tobago-config-2.0.xsd" link="https://myfaces.apache.org/tobago/tobago-config-2.0.xsd"/>
+        to validate the configuration.</p>
+    </tc:section>
+
+    <tc:section label="JavaScript">
+      <p>Date/Time/Calendar components: The JavaScript for this components has been refactored. All method have now a
+        namespace and are using jQuery. JavaScript code has been removed from the renderers. For data the HTML5 data
+        attribute is used instead of directly coding it into the event handler, or using hidden input fields.</p>
+    </tc:section>
+
+    <tc:section label="CSS">
+      <p>The class <code class="language-css">tobago-sheet-outer</code> is renamed to
+        <code class="language-css">tobago-sheet</code>.<br/>
+        The class <code class="language-css">tobago-sheet-headerSpacerOuter</code> is renamed to
+        <code class="language-css">tobago-sheet-headerResize</code>.<br/>
+        The class <code class="language-css">tobago-sheet-headerSpacer</code> is no longer needed.<br/>
+        The class <code class="language-css">tobago-sheet-headerSpacer-markup-resizable</code> is no longer needed.</p>
+    </tc:section>
+
+    <tc:section label="Internal">
+      <p>The facet name of the picker popup is now named "popup" instead of "pickerPopup".</p>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/99-migration/migration15.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/99-migration/migration15.xhtml
new file mode 100644
index 0000000..b04444e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/99-migration/migration15.xhtml
@@ -0,0 +1,229 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.migration15}"/>
+  <tc:section label="Migration from Tobago 1.0 to 1.5">
+    <p>Tobago 1.5 has a lot of changes compared to Tobago 1.0.</p>
+    <p>The good news: Most of these changes are made internally in Tobago. If you use Tobago, you don't have to change
+      too much.</p>
+    <p>The amount of things you have to change in your application depends on how do you use it. On the Tobago Tag
+      Library are very few changes made. On the Tobago Java Classes and the Themes are more changes. Here you can see
+      which changes has been made.</p>
+
+    <tc:section label="Deprecated">
+      <p>There are also <code>@Deprecated</code> annotations in the code and some logging warning when using deprecated
+        code via the Deprecation logging category. Before migrating you should check your application about that.</p>
+      <p>For the migration phase you may add the tobago-deprecation.jar as dependency to your project. It contains
+        classes that has been moved (e. g. to the new <code>internal</code> package) or removed. So you can resolve any
+        migration steps step by step. It is not recommended to use the tobago-deprecation.jar for production.</p>
+    </tc:section>
+
+    <tc:section label="Internal">
+      <p>The new <code>internal</code> package contains classes that should not be used directly in an application. This
+        classes may change in minor revisions without announcement. Classes in the <code>renderkit</code> package a
+        handled in the same manner.</p>
+    </tc:section>
+
+    <tc:section label="Tag Library">
+      <p>The main changes in the tag library are</p>
+      <tc:segmentLayout extraSmall="6;6">
+        <tc:panel><b>deprecated</b></tc:panel>
+        <tc:panel><b>replacement</b></tc:panel>
+        <tc:panel><code class="language-markup">&lt;tc:menuCheckbox></code></tc:panel>
+        <tc:panel><code class="language-markup">&lt;tx:menuCheckbox></code></tc:panel>
+        <tc:panel><code class="language-markup">&lt;tc:menuItem></code></tc:panel>
+        <tc:panel><code class="language-markup">&lt;tc:menuCommand></code></tc:panel>
+        <tc:panel><code class="language-markup">&lt;tc:message></code></tc:panel>
+        <tc:panel><code class="language-markup">&lt;tc:messages></code></tc:panel>
+      </tc:segmentLayout>
+      <p>In <code class="language-markup">&lt;tc:sheet></code> the default for <code>rows</code> has been changed from
+        100 to 0, which means "unlimited".</p>
+      <p>For JSP and the <code>tx:</code> library all <code>id</code> attributes have to be renamed to
+        <code>fieldId</code>. This is to adjust the JSP library to the Facelet library.</p>
+      <p>The tree tag <code class="language-markup">&lt;tc:tree></code> has changed comprehensive. Please check the
+        documentation and demo examples.</p>
+      <p>The <code>type</code> attribute of commands has been removed. It is no longer needed, when using
+        <code>action</code>, <code>onclick</code> or <code>link</code>.</p>
+    </tc:section>
+
+    <tc:section label="Layout Manager">
+      <p>On of the basic changes in Tobago 1.5 is the reimplementation of the layout manager. The usage if it, has only
+        been changed a bit. The most important is that the constraints will be set with the
+        <code class="language-markup">&lt;tc:gridLayoutConstraint></code> tag. The
+        <code class="language-markup">&lt;tc:cell></code> tag is deprecated now. Spans can be set directly into the
+        component with the <code class="language-markup">&lt;tc:gridLayoutConstraint></code> tag.</p>
+      <p>The keyword "fixed" has been renamed to "auto".</p>
+    </tc:section>
+
+    <tc:section label="UIComponent Classes">
+      <p>Some of the UIComponent classes has been renamed or restructured, to get a consistent naming schema. The used
+        UIComponents where generated and have super classes with an "Abstract" as prefix. All getters and setters are
+        generated in the UIComponent classes. The following code will not work in 1.5
+        <code>uiComponent.getAttributes().remove("attributeName")</code>. Please set the value to null.</p>
+      <p>old name: <code>org.apache.myfaces.tobago.component.UISelectOne</code><br/>
+        new name: <code>org.apache.myfaces.tobago.internal.component.AbstractUISelectOneBase</code></p>
+    </tc:section>
+
+    <tc:section label="Naming Container">
+      <p>UITab is now a naming container, so you may have to change ids of AJAX calls in your application.</p>
+    </tc:section>
+
+    <tc:section label="Other API Classes">
+      <p>The class <code>org.apache.myfaces.tobago.OnComponentCreated</code> is moved to
+        <code>org.apache.myfaces.tobago.component.OnComponentCreated</code>.<br/>
+        The class <code>org.apache.myfaces.tobago.component.ComponentUtil</code> is moved to
+        <code>org.apache.myfaces.tobago.util.ComponentUtils</code>.<br/>
+        The class <code>org.apache.myfaces.tobago.renderkit.RenderUtil</code> is moved to
+        <code>org.apache.myfaces.tobago.renderkit.util.RenderUtils</code>.<br/>
+        The class <code>org.apache.myfaces.tobago.renderkit.html.HtmlRendererUtil</code> is renamed to
+        <code>org.apache.myfaces.tobago.renderkit.html.util.HtmlRendererUtils</code>.</p>
+    </tc:section>
+
+    <tc:section label="Themes and CSS">
+      <p>Note: This effects your application only, when you've written your own theme, or using this classes in a
+        separate style file.</p>
+      <p>The basic changes in CSS are:</p>
+      <ul>
+        <li>Using CSS 2.1 compliant content box model instead of <i>Quirks mode</i> border box model.</li>
+        <li>Changed HTML structure for some components.</li>
+      </ul>
+      <p>The CSS class name schema has been revised. See the JavaDoc of the <code>Classes</code> class to check the
+        naming schema.</p>
+      <tc:segmentLayout extraSmall="6;6">
+        <tc:panel><b>old name</b></tc:panel>
+        <tc:panel><b>new name</b></tc:panel>
+        <tc:panel><code>tobago-[tagName]-default</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-error</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-markup-error</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-required</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-markup-required</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-readonly</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-markup-readonly</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-disabled</code></tc:panel>
+        <tc:panel><code>tobago-[tagName]-markup-disabled</code></tc:panel>
+        <tc:panel><code>tree-junction</code></tc:panel>
+        <tc:panel><code>tobago-treeNode-junction</code></tc:panel>
+        <tc:panel><code>tree-*</code></tc:panel>
+        <tc:panel><code>tobago-treeNode-*</code></tc:panel>
+        <tc:panel><code>tobago-input-picker</code></tc:panel>
+        <tc:panel><code>tobago-datePicker-icon</code></tc:panel>
+        <tc:panel><code>tobago-popup-iframe</code></tc:panel>
+        <tc:panel><code>tobago-popup-ie6bugfix</code></tc:panel>
+        <tc:panel><code>tobago-textArea-*</code></tc:panel>
+        <tc:panel><code>tobago-textarea-*</code></tc:panel>
+        <tc:panel><code>tobago-progress-color1-*</code></tc:panel>
+        <tc:panel><code>tobago-progress-value-*</code></tc:panel>
+      </tc:segmentLayout>
+      <p>The class <code>tobago-progress-color2-*</code> is deleted.</p>
+    </tc:section>
+
+    <tc:section label="JavaScript">
+      <p>The JavaScript API has been refactored. Most application do not use the Tobago JavaScript API directly. But if
+        it does, you have to apply some changes.</p>
+      <p>The most important things, is the additional first parameter on the submitting functions to compute the
+        position of the action element.</p>
+      <p>If you are using <code>submitAction()</code> in the old code, you have to add the action element or just
+        <code>null</code>. If you are using <code>submitAction2()</code> in the old code, you have to rename it to
+        <code>submitAction()</code>.</p>
+      <tc:flexLayout rows="auto;auto">
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>added first parameter and put all parameters after the second to an options map</p></tc:panel>
+          <tc:panel><p><code>submitAction()</code></p></tc:panel>
+          <tc:panel/>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>renamed</p></tc:panel>
+          <tc:panel><p><code>submitAction2()</code></p></tc:panel>
+          <tc:panel><p><code>submitAction()</code></p></tc:panel>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>added first parameter</p></tc:panel>
+          <tc:panel><p><code>openPopupWithAction()</code></p></tc:panel>
+          <tc:panel/>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>renamed</p></tc:panel>
+          <tc:panel><p><code>openPopupWithAction2()</code></p></tc:panel>
+          <tc:panel><p><code>openPopupWithAction()</code></p></tc:panel>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>added first parameter</p></tc:panel>
+          <tc:panel><p><code>reloadComponent()</code></p></tc:panel>
+          <tc:panel/>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>renamed</p></tc:panel>
+          <tc:panel><p><code>reloadComponent2()</code></p></tc:panel>
+          <tc:panel><p><code>reloadComponent()</code></p></tc:panel>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>added first parameter</p></tc:panel>
+          <tc:panel><p><code>Updater.update()</code></p></tc:panel>
+          <tc:panel/>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>renamed</p></tc:panel>
+          <tc:panel><p><code>Updater.update2()</code></p></tc:panel>
+          <tc:panel><p><code>Updater.update()</code></p></tc:panel>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>added first parameter</p></tc:panel>
+          <tc:panel><p><code>Sheet.reloadWithAction()</code></p></tc:panel>
+          <tc:panel/>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>renamed</p></tc:panel>
+          <tc:panel><p><code>Sheet.reloadWithAction2()</code></p></tc:panel>
+          <tc:panel><p><code>Sheet.reloadWithAction()</code></p></tc:panel>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1">
+          <tc:panel><p>added first parameter</p></tc:panel>
+          <tc:panel><p><code>TabGroup.reloadWithAction()</code></p></tc:panel>
+          <tc:panel/>
+        </tc:flexLayout>
+        <tc:flexLayout columns="1;1;1;">
+          <tc:panel><p>renamed</p></tc:panel>
+          <tc:panel><p><code>TabGroup.reloadWithAction2()</code></p></tc:panel>
+          <tc:panel><p><code>TabGroup.reloadWithAction()</code></p></tc:panel>
+        </tc:flexLayout>
+      </tc:flexLayout>
+    </tc:section>
+
+    <tc:section label="Configuration">
+      <p>To define an own theme, please use now a file <code>tobago-config.xml</code> instead of
+        <code>tobago-theme.xml</code>.
+        The content of <code>tobago-theme.xml</code> is a subset of the <code>tobago-config.xml</code>, you have only to
+        change the root node.</p>
+      <p>Please use the
+        <tc:link label="tobago-config-1.5.xsd" link="https://myfaces.apache.org/tobago/tobago-config-1.5.xsd"/> to
+        validate the configuration.</p>
+    </tc:section>
+
+    <tc:section label="Own Components and Renderers">
+      <p>The renderers must now declared inside the <code>faces-config.xml</code>.</p>
+      <p>For the Tobago classes, this will be generated at compile time from annotations like in e. g.
+        <code>org.apache.myfaces.tobago.internal.taglib.component.BoxTagDeclaration</code>.</p>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/migration.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/migration.xhtml
new file mode 100644
index 0000000..4d45d86
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/50-migration/migration.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.migration}"/>
+
+  <tc:section label="Migration of Tobago applications">
+
+    Here you can find migration guides to the major versions of Tobago.
+
+  </tc:section>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/intro.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/intro.xhtml
new file mode 100644
index 0000000..eb7caee
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/10-intro/intro.xhtml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.intro}"/>
+  <p>This is the demo of Tobago 3.
+    It shows the components and concepts of Tobago 3 and also should be a bit of a documentation.</p>
+  <p>If you want to migrate from Tobago 2.0 to 3.0, you'll find further information in the
+    <tc:link label="migration guide" link="#{request.contextPath}/faces/content/10-intro/50-migration/97-migration/migration30.xhtml"/>.</p>
+  <p>If you want to start this demo on you local machine, have a look at the section 'Local Demo'.</p>
+
+  <tc:section label="Description">
+    <p>Tobago is a user interface framework for developing webapplications.
+      The technical basis of the framework is JavaServer Faces. The main core represents a theme oriented
+      JSF Render Kit.</p>
+    <tc:section label="Basic Controls">
+      <p>Tobago provides all standard controls of HTML like inputs, textareas, radiobuttons, checkboxes and buttons.
+        Additionally Tobago provides you with complex controls, which are not natively supportet by simple HTML,
+        including sheets, trees and tabs.</p>
+    </tc:section>
+    <tc:section label="Validation">
+      <p>The main goal of Tobago is the development of applications which are interactive from the users point of view.
+        Tobago makes it easy to validate input and helps the user to enter correct data.</p>
+    </tc:section>
+    <tc:section label="Layout">
+      <p>Tobago provides several advanced layout managers to fit for specific use cases by using CSS3 and HTML5.
+        This includes a 12 columns layout from <tc:link label="Bootstrap" link="https://getbootstrap.com/"/>
+        and a flex layout which replace the old grid layout from Tobago 2.</p>
+    </tc:section>
+    <tc:section label="Versioning">
+      <p>The Tobago project using <tc:link label="semantic versioning" link="https://semver.org/"/> since past 2016.</p>
+      <p>This will lead into more growing minor version number compared to the past.</p>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Local Demo">
+    <p>In case that this demo already run on your local machine,
+      you can follow the link to the
+      <tc:link label="public demo" link="http://www.irian.biz/tobago-example-demo-3.0.x/"/>.</p>
+    <p>If this is the public demo and you want to build it on your own, read the following instructions.</p>
+    <tc:section label="Instructions">
+      <p>First of all you need
+        <tc:link label="maven" link="https://maven.apache.org/"/> (at least version 3.0.4) and
+        <tc:link label="Java SE 6" link="http://www.oracle.com/technetwork/java/javase/downloads/"/> or higher.</p>
+      <p>After that, check out the source code from subversion repository.
+        <br/>
+        <code>svn checkout http://svn.apache.org/repos/asf/myfaces/tobago/trunk tobago3</code>
+        <br/>
+        Alternatively you can get the source code from the
+        <tc:link label="download section" link="https://myfaces.apache.org/tobago/download.html"/>.</p>
+      <p>Go to the tobago3 directory, and build Tobago with <code>mvn install</code>.</p>
+      <p>Go to 'tobago3/tobago-example/tobago-example-demo' and start the demo with <code>mvn jetty:run</code>.</p>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/in.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/in.test.js
new file mode 100644
index 0000000..5332c17
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/in.test.js
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("inputfield with label", function (assert) {
+  var $label = jQueryFrame("#page\\:mainForm\\:iNormal > label");
+  var $inputField = jQueryFrame("#page\\:mainForm\\:iNormal\\:\\:field");
+
+  assert.equal($label.text(), "Input");
+  assert.equal($inputField.val(), "Some Text");
+
+  $inputField.val("abc");
+  assert.equal($inputField.val(), "abc");
+});
+
+QUnit.test("ajax change event", function (assert) {
+  assert.expect(4);
+  var done = assert.async();
+
+  var $inputField = jQueryFrame("#page\\:mainForm\\:inputAjax\\:\\:field");
+  var $outputField = jQueryFrame("#page\\:mainForm\\:outputAjax span:first");
+
+  assert.equal($inputField.val(), "");
+  assert.equal($outputField.text(), "");
+
+  $inputField.val("qwe").trigger("change");
+  assert.equal($inputField.val(), "qwe");
+
+  waitForAjax(function () {
+    $outputField = jQueryFrame($outputField.selector);
+    return $outputField.text() == "qwe";
+  }, function () {
+    $outputField = jQueryFrame($outputField.selector);
+    assert.equal($outputField.text(), "qwe");
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/in.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/in.xhtml
new file mode 100644
index 0000000..f616bc5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/10-in/in.xhtml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.in} &lt;tc:in&gt;"/>
+  <p>The <code class="language-markup">&lt;tc:in/&gt;</code> tag create a classic inputfield.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/in.html"/>
+  <tc:section label="Basics">
+    <p>In most cases, a label should be placed in front of every inputfield. Use the attribute
+      <code>label</code>.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Input" value="Some Text"/&gt;</code></pre>
+    <tc:in id="iNormal" label="Input" value="Some Text"/>
+    <tc:in id="ireadonly" label="Read Only" readonly="true" value="Some Text"/>
+    <tc:in id="i3" label="Disabled" disabled="true" value="Some Text"/>
+    <tc:in id="i4" value="Input without a label"/>
+  </tc:section>
+
+  <tc:section label="Focus">
+    <p>The following inputfield should be selected after reloading the page. Use the <code>focus</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Input (focus)" focus="true" value="Some Text"/&gt;</code></pre>
+    <tc:in id="i5" label="Input (focus)" focus="true" value="Some Text"/>
+  </tc:section>
+
+  <tc:section label="Required">
+    <p>An inputfield can be set as required with the <code>required</code> attribute.
+      Such an inputfield must contain a value, otherwise a submit is not possible.
+      Leave the field blank and press 'submit' to see the errormessage.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Input (required)" required="true"/></code></pre>
+    <tc:in id="ireq" label="Input (required)" required="true"/>
+    <tc:button label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Password">
+    <p>To create an inputfield for passwords, set the
+      <code>password</code> attribute to 'true'. It will hide the text as shown in the following example.</p>
+        <pre><code id="c3"
+                   class="language-markup">&lt;tc:in label="Password" password="true" value="password"/&gt;</code></pre>
+    <tc:in id="i6" label="Password" password="true" value="password"/>
+  </tc:section>
+
+  <tc:section label="Placeholder">
+    <p>A <code>placeholder</code> attribute can be used for explaining a user the meaning of a field.</p>
+    <p>The text of the placeholder is only shown if the value is an empty string.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Placeholder" placeholder="Grey Text"/&gt;</code></pre>
+    <tc:in id="i7" label="Placeholder" placeholder="Short description of the field." value=""/>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>The outputfield in this example, displays the given value on the server.
+      With <code class="language-markup">&lt;f:ajax render="outputAjax" listener="\#{inController.update}"/></code>,
+      the outputfield will be rerendered, after the value has been changed.
+      This is because <code>outputAjax</code> is the id of the <code>&lt;tc:out/></code> tag.
+      and the default event for <code class="language-markup">&lt;tc:in/></code> is <code>change</code>.
+
+      Additional, the <code>listener</code> attribute is set. The given method is called after the inputfield
+      loose focus.</p>
+    <tc:in id="inputAjax" label="On Change" value="#{inController.changeValue}">
+      <f:ajax render="outputAjax" listener="#{inController.update}"/>
+    </tc:in>
+    <tc:out id="outputAjax" label="On Server" value="#{inController.changeValue}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/suggest.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/suggest.test.js
new file mode 100644
index 0000000..a3f20df
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/suggest.test.js
@@ -0,0 +1,541 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Basics: 'C'", function(assert) {
+  var inputString = "C";
+  var expectedLength = 10;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+
+QUnit.test("Basics: 'Ch'", function(assert) {
+  var inputString = "Ch";
+  var expectedLength = 10;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chi'", function(assert) {
+  var inputString = "Chi";
+  var expectedLength = 10;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chil'", function(assert) {
+  var inputString = "Chil";
+  var expectedLength = 10;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile'", function(assert) {
+  var inputString = "Chile";
+  var expectedLength = 7;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile '", function(assert) {
+  var inputString = "Chile ";
+  var expectedLength = 7;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile ('", function(assert) {
+  var inputString = "Chile (";
+  var expectedLength = 7;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (e'", function(assert) {
+  var inputString = "Chile (e";
+  var expectedLength = 3;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (es'", function(assert) {
+  var inputString = "Chile (es";
+  var expectedLength = 3;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (esp'", function(assert) {
+  var inputString = "Chile (esp";
+  var expectedLength = 3;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (espa'", function(assert) {
+  var inputString = "Chile (espa";
+  var expectedLength = 3;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (espan'", function(assert) {
+  var inputString = "Chile (espan";
+  var expectedLength = 2;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (espanj'", function(assert) {
+  var inputString = "Chile (espanj";
+  var expectedLength = 1;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (espanja'", function(assert) {
+  var inputString = "Chile (espanja";
+  var expectedLength = 1;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: 'Chile (espanja)'", function(assert) {
+  var inputString = "Chile (espanja)";
+  var expectedLength = 1;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Basics: Add 'Belgiu' and click first entry.", function(assert) {
+  assert.expect(12);
+  var done = assert.async();
+
+  assert.equal(1, 1);
+  var $in = jQueryFrame("#page\\:mainForm\\:inBasic\\:\\:field");
+  assert.equal(1, 1);
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inBasic");
+  assert.equal(1, 1);
+
+  $in.val("Belgiu").trigger('input');
+  assert.equal($in.val(), "Belgiu");
+
+  waitForAjax(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == 2;
+  }, function() {
+    assert.equal(1, 1);
+    $in = jQueryFrame($in.selector);
+    assert.equal(1, 1);
+    $suggestions = jQueryFrame($suggestions.selector);
+    assert.equal(1, 1);
+
+    assert.equal($suggestions.length, 2);
+    assert.equal($suggestions.eq(0).find("strong").text(), "Belgiu");
+    assert.equal($suggestions.eq(1).find("strong").text(), "Belgiu");
+
+    // click first entry
+    assert.equal($in.val(), "Belgiu");
+    $suggestions.eq(0).click();
+    assert.equal($in.val(), "Belgium (Dutch)");
+
+    done();
+  });
+});
+
+QUnit.test("Advanced: 'H'", function(assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inAdvanced\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inAdvanced");
+  var suggestionDelay = 2000;
+
+  $in.val("H").trigger('input');
+
+  setTimeout(function() {
+    waitForAjax(function() {
+      $suggestions = jQueryFrame($suggestions.selector);
+      return $suggestions.length == 0;
+    }, function() {
+      $suggestions = jQueryFrame($suggestions.selector);
+      assert.equal($suggestions.length, 0);
+      done();
+    });
+  }, suggestionDelay);
+});
+
+QUnit.test("Advanced: 'Ho'", function(assert) {
+  assert.expect(4);
+  var done = assert.async(2);
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inAdvanced\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inAdvanced");
+  var suggestionDelay = 2000;
+
+  $in.val("Ho").trigger('input');
+
+  setTimeout(function() {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    // Nothing happen, because the delay is greater than the default delay.
+    assert.equal($suggestions.length, 0);
+
+    done();
+  }, 200); // default suggestion delay
+
+  setTimeout(function() {
+    waitForAjax(function() {
+      $in = jQueryFrame($in.selector);
+      $suggestions = jQueryFrame($suggestions.selector);
+
+      return $suggestions.length == 2
+          && $suggestions.eq(0).find("strong").text() == "ho"
+          && $suggestions.eq(1).find("strong").text() == "ho";
+    }, function() {
+      $in = jQueryFrame($in.selector);
+      $suggestions = jQueryFrame($suggestions.selector);
+
+      assert.equal($suggestions.length, 2);
+      assert.equal($suggestions.eq(0).find("strong").text(), "ho");
+      assert.equal($suggestions.eq(1).find("strong").text(), "ho");
+
+      done();
+    });
+  }, suggestionDelay);
+});
+
+QUnit.test("Client sided: 'Korean'", function(assert) {
+  assert.expect(5);
+
+  var $in = jQueryFrame("#page\\:mainForm\\:inClient\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:inClient");
+
+  $in.val("Korean").trigger('input');
+
+  $suggestions = jQueryFrame($suggestions.selector);
+  assert.equal($suggestions.length, 4);
+  assert.equal($suggestions.eq(0).find("strong").text(), "Korean");
+  assert.equal($suggestions.eq(1).find("strong").text(), "Korean");
+  assert.equal($suggestions.eq(2).find("strong").text(), "Korean");
+  assert.equal($suggestions.eq(3).find("strong").text(), "Korean");
+});
+
+function getSuggestions(id) {
+  return jQueryFrame(Tobago.Utils.escapeClientId(
+          jQueryFrame(id + " .tobago-suggest").attr("id") + "::popup") + " .tt-suggestion");
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/suggest.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/suggest.xhtml
new file mode 100644
index 0000000..130a3be
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/20-suggest/suggest.xhtml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.suggest} &lt;tc:suggest&gt;"/>
+  <p>A <code class="language-markup">&lt;tc:suggest/></code> tag can be added to an inputfield to make
+    suggestions based on the already entered text.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:suggest/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/suggest.html"/>
+    |
+    <tc:link label="&lt;tc:in/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/in.html"/>
+    |
+    <tc:link label="&lt;tc:selectItems/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItems.html"/></p>
+
+  <tc:section label="Basics">
+    <p>After you type a character in the textfield, a list of suggestions is shown.</p>
+    <p>If <code>update="true"</code> the attribute
+      <code>totalCount</code> should be set to improve performance.
+      It set the amount of items loaded from the server.</p>
+    <p>The suggestion list is calculated in the controller. User the <code>query</code> attribute to pass
+      the query string to the controller.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Language">
+  &lt;tc:suggest totalCount="10" query="\#{suggestController.query}">
+    &lt;tc:selectItems value="\#{suggestController.languages}" var="language" itemValue="\#{language}"/>
+  &lt;/tc:suggest>
+&lt;/tc:in></code></pre>
+    <tc:in id="inBasic" >
+      <tc:suggest totalCount="10" query="#{suggestController.query}">
+        <tc:selectItems value="#{suggestController.languages}" var="language" itemValue="#{language}"/>
+      </tc:suggest>
+    </tc:in>
+  </tc:section>
+
+  <tc:section label="Advanced">
+    <p>This example differs in a few points from the one in the 'Basics' section.
+      There are only two suggestions shown to the user, because the
+      <code>maximumItems</code> attribute is set to '2'.
+      Also you need to type two characters before suggestions are made,
+      because of the <code>minimumCharacters</code> attribute which has the value '2'.
+      And by setting the <code>delay</code> to '2000', the user have to wait two seconds,
+      before the suggestion list is shown.</p>
+    <pre><code class="language-markup">&lt;tc:suggest query="\#{suggestController.query}"
+            maximumItems="2" minimumCharacters="2" delay="2000">
+  &lt;tc:selectItems value="\#{suggestController.languages}" var="language" itemValue="\#{language}"/>
+&lt;/tc:suggest></code></pre>
+    <tc:in id="inAdvanced" label="Language">
+      <tc:suggest query="#{suggestController.query}"
+                  maximumItems="2" minimumCharacters="2" delay="2000">
+        <tc:selectItems value="#{suggestController.languages}" var="language" itemValue="#{language}"/>
+      </tc:suggest>
+    </tc:in>
+  </tc:section>
+
+  <tc:section label="Client sided">
+    <p>Filtering can also be done by the client. For that, set <code>update="false"</code>.</p>
+    <p>If client sided, you can also use <code class="language-markup"><tc:selectItem/></code>
+      instead of <code class="language-markup"><tc:selectItems/></code>.</p>
+    <pre><code class="language-markup">&lt;tc:suggest update="false"/></code></pre>
+    <tc:in id="inClient" label="Language">
+      <tc:suggest update="false">
+        <tc:selectItems value="#{suggestController.allLanguages}"/>
+      </tc:suggest>
+    </tc:in>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/30-textarea/textarea.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/30-textarea/textarea.xhtml
new file mode 100644
index 0000000..26cb7c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/30-textarea/textarea.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.textarea} &lt;tc:textarea&gt;"/>
+  <p>The <code class="language-markup">&lt;tc:textarea/&gt;</code> tag, creates a textfield with one or more rows.
+    The textarea becomes scrollable if the containing text could not displayed in the current size.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/textarea.html"/>
+  <tc:section label="Basics">
+    <p>The textarea should always have a label attached. For this, use the <code>label</code> attribute.</p>
+    <p>Unlike the inputfield TODO:linkToIn there is no placeholder attribute to describe the meaning of a textarea, when no label is set.</p>
+    <pre><code class="language-markup">&lt;tc:textarea label="Text Area" value="Some text, some text, ..."/&gt;</code></pre>
+    <tc:textarea id="t1" label="Text Area"
+                 value="Some text, some text, some text, some text, some text, some text, some text, some text, some text, some text, ..."/>
+    <tc:textarea id="t2" label="Read Only" readonly="true"
+                 value="Some text, some text, some text, some text, some text, some text, some text, some text, some text, some text, ..."/>
+    <tc:textarea id="t3" label="Disabled" disabled="true"
+                 value="Some text, some text, some text, some text, some text, some text, some text, some text, some text, some text, ..."/>
+    <tc:textarea id="t4"
+                 value="Text Area without a label, Text Area without a label, Text Area without a label, Text Area without a label, Text Area without a label, Text Area without a label, Text Area without a label, Text Area without a label, Text Area without a label, ..."/>
+  </tc:section>
+  <tc:section label="Focus">
+    <p>The following textarea should be selected after reloading this page. Use the <code>focus</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:textarea label="Text Area (focus)" focus="true" value="Some Text"/&gt;</code></pre>
+    <tc:textarea id="t5" label="Text Area (focus)" focus="true" value="Some Text"/>
+  </tc:section>
+
+  <tc:section label="Required">
+    <p>A textarea can be set as required with the <code>required</code> attribute.
+      Such a textarea must contain a value, otherwise a submit is not possible.
+      Leave the field blank and press 'submit' to see the errormessage.</p>
+    <pre><code class="language-markup">&lt;tc:textarea id="treq" label="Text Area" required="true"/></code></pre>
+    <tc:textarea id="treq" label="Text Area" required="true"/>
+    <tc:button label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Rows">
+    <p>With the <code>rows</code> attribute, the initial size of the textbox can be set. A value less than 1 has no effect.</p>
+    <p>The following example show a textarea with five rows.</p>
+    <pre><code class="language-markup">&lt;tc:textarea label="Text Area" rows="5" value="\#{textareaController.longText}"/&gt;</code></pre>
+    <tc:textarea id="t6" label="Text Area" rows="5" value="#{textareaController.longText}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/date.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/date.test.js
new file mode 100644
index 0000000..b4cfbb0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/date.test.js
@@ -0,0 +1,111 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function getToday() {
+  var now = new Date();
+  var dd = now.getDate();
+  var mm = now.getMonth() + 1;
+  var yyyy = now.getFullYear();
+  if (dd < 10) {
+    dd = '0' + dd
+  }
+  if (mm < 10) {
+    mm = '0' + mm
+  }
+  return dd + "." + mm + "." + yyyy;
+}
+
+QUnit.test("date with label", function (assert) {
+  var $label = jQueryFrame("#page\\:mainForm\\:dNormal > label");
+  var $dateField = jQueryFrame("#page\\:mainForm\\:dNormal\\:\\:field");
+  var $dateButton = jQueryFrame("#page\\:mainForm\\:dNormal button");
+  var today = getToday();
+
+  assert.equal($label.text(), "Date");
+  assert.equal($dateField.val(), today);
+
+  $dateField.val("32.05.2016");
+  $dateButton.click();
+
+  assert.equal($dateField.val(), today);
+});
+
+QUnit.test("submit", function(assert) {
+  assert.expect(6);
+  var done = assert.async();
+
+  var $dateField = jQueryFrame("#page\\:mainForm\\:formSubmit\\:input\\:\\:field");
+  var $dateButton = jQueryFrame("#page\\:mainForm\\:formSubmit\\:input button");
+  var $outField = jQueryFrame("#page\\:mainForm\\:formSubmit\\:output span");
+  var $submitButton = jQueryFrame("#page\\:mainForm\\:formSubmit\\:button");
+  var $days = jQueryFrame(".bootstrap-datetimepicker-widget .day");
+
+  assert.equal($dateField.val(), "22.05.2016");
+  assert.equal($outField.text(), "22.05.2016");
+
+  $dateButton.click();
+  assert.ok(jQueryFrame(".bootstrap-datetimepicker-widget").get(0),
+      ".bootstrap-datetimepicker-widget should be available");
+
+  $days = jQueryFrame($days.selector);
+  var day22 = 0;
+  for (i = 0; i < $days.length; i++) {
+    $days = jQueryFrame($days.selector);
+    if ($days.eq(i).text() == "22") {
+      day22 = i;
+      break;
+    }
+  }
+  assert.ok(jQueryFrame(".bootstrap-datetimepicker-widget .day").get(i + 10));
+  jQueryFrame(".bootstrap-datetimepicker-widget .day").get(i + 10).click(); // Choose '01.06.2016'.
+
+  assert.equal($dateField.val(), "01.06.2016");
+  $submitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $outField = jQueryFrame("#page\\:mainForm\\:formSubmit\\:output span");
+    assert.equal($outField.text(), "01.06.2016");
+    done();
+  });
+});
+
+QUnit.test("ajax", function (assert) {
+  assert.expect(5);
+  var done = assert.async();
+
+  var $dateField = jQueryFrame("#page\\:mainForm\\:ajaxinput\\:\\:field");
+  var $dateButton = jQueryFrame("#page\\:mainForm\\:ajaxinput button");
+  var $outField = jQueryFrame("#page\\:mainForm\\:outputfield span");
+  var today = getToday();
+
+  assert.equal($dateField.val(), "");
+  assert.equal($outField.text(), "");
+
+  $dateButton.click();
+
+  assert.ok(jQueryFrame(".bootstrap-datetimepicker-widget").get(0));
+  assert.equal($dateField.val(), today);
+
+  waitForAjax(function () {
+    $outField = jQueryFrame($outField.selector);
+    return $outField.text() == today;
+  }, function () {
+    $outField = jQueryFrame($outField.selector);
+    assert.equal($outField.text(), today);
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/date.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/date.xhtml
new file mode 100644
index 0000000..01cfe42
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/40-date/date.xhtml
@@ -0,0 +1,198 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.date} &lt;tc:date&gt;"/>
+  <p>The <code class="language-markup">&lt;tc:date/&gt;</code>
+    tag create an inputfield with a button to open a calendar to edit the date.
+    The date can also be edited in the textfield.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:date/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/date.html"/>
+    |
+    <tc:link label="&lt;f:convertDateTime/>"
+             link="https://docs.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/f/convertDateTime.html"/>
+  </p>
+
+  <tc:section label="Basics">
+    <p>In general, a date should always have a label. To get a label use the <code>label</code> attribute.</p>
+    <p>It is recommended to use a pattern. For that, use <code>&lt;f:convertDateTime&gt;</code>.</p>
+    <p>The <code>value</code> must be a
+      <tc:link label="Date" link="https://docs.oracle.com/javase/8/docs/api/java/util/Date.html"/>
+      or a string with a matching pattern.</p>
+        <pre><code class="language-markup">&lt;tc:date label="Date" value="\#{dateController.now}"&gt;
+  &lt;f:convertDateTime pattern="dd.MM.yyyy"/&gt;
+&lt;/tc:date&gt;</code></pre>
+    <tc:date id="dNormal" label="Date" value="#{dateController.now}">
+      <f:convertDateTime pattern="dd.MM.yyyy"/>
+    </tc:date>
+    <tc:date id="dReadonly" label="Read Only" readonly="true" value="#{dateController.now}">
+      <f:convertDateTime pattern="dd.MM.yyyy"/>
+    </tc:date>
+    <tc:date id="d3" label="Disabled" disabled="true" value="#{dateController.now}">
+      <f:convertDateTime pattern="dd.MM.yyyy"/>
+    </tc:date>
+    <tc:date id="d4" value="#{dateController.now}">
+      <f:convertDateTime pattern="dd.MM.yyyy"/>
+    </tc:date>
+  </tc:section>
+  <tc:section label="Focus">
+    <p>The following date should be selected after reloading the page. This can be done with the attribute
+      <code>focus</code>.</p>
+        <pre><code class="language-markup">&lt;tc:date label="Date (focus)" focus="true"&gt;
+  &lt;f:convertDateTime pattern="dd.MM.yyyy"/&gt;
+&lt;/tc:date&gt;</code></pre>
+    <tc:date id="d5" label="Date (focus)" focus="true">
+      <f:convertDateTime pattern="dd.MM.yyyy"/>
+    </tc:date>
+  </tc:section>
+
+  <tc:section label="Required">
+    <p>A date can be set as required with the <code>required</code> attribute.
+      Such a date must contain a value, otherwise a submit is not possible.
+      Leave the field blank and press 'submit' to see the errormessage.</p>
+    <pre><code class="language-markup">&lt;tc:date label="Date (required)" required="true"
+    value="\#{dateController.once}"></code></pre>
+    <tc:form>
+      <tc:date id="dreq" label="Date (required)" required="true" value="#{dateController.once}">
+        <f:convertDateTime pattern="dd.MM.yyyy"/>
+      </tc:date>
+      <tc:button label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Outputfields">
+    <p>A date can also be displayed in other components.</p>
+    <tc:section label="Input">
+            <pre><code class="language-markup">&lt;tc:in label="Date in Textfield" value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="dd.MM.yyyy"/&gt;
+&lt;/tc:in&gt;</code></pre>
+      <tc:in id="i1" label="Date in Textfield" value="#{dateController.now}">
+        <f:convertDateTime pattern="dd.MM.yyyy"/>
+      </tc:in>
+    </tc:section>
+    <tc:section label="Text Area">
+            <pre><code class="language-markup">&lt;tc:textarea label="Date in Text Area" value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="dd.MM.yyyy"/&gt;
+&lt;/tc:textarea&gt;</code></pre>
+      <tc:textarea id="t1" label="Date in Text Area" value="#{dateController.now}">
+        <f:convertDateTime pattern="dd.MM.yyyy"/>
+      </tc:textarea>
+    </tc:section>
+    <tc:section label="Output">
+            <pre><code class="language-markup">&lt;tc:out label="Date in Output" value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="dd.MM.yyyy"/&gt;
+&lt;/tc:out&gt;</code></pre>
+      <tc:out id="o1" label="Date in Output" value="#{dateController.now}">
+        <f:convertDateTime pattern="dd.MM.yyyy"/>
+      </tc:out>
+    </tc:section>
+    <tc:section label="Label">
+            <pre><code class="language-markup">&lt;tc:label value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="dd.MM.yyyy"/&gt;
+&lt;/tc:label&gt;</code></pre>
+      <tc:label id="l1" value="#{dateController.now}">
+        <f:convertDateTime pattern="dd.MM.yyyy"/>
+      </tc:label>
+    </tc:section>
+  </tc:section>
+  <tc:section label="Pattern And Button">
+    <p>Here are some examples for different pattern. The format is used from java.text.SimpleDateFormat. TODO:setlink</p>
+    <p>Also the type of the button changed with the <code>type</code> attribute.</p>
+    <tc:section label="Month">
+            <pre><code class="language-markup">&lt;tc:date label="Month" value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="MM/yyyy" type="date"/&gt;
+&lt;/tc:date&gt;</code></pre>
+      <tc:date id="d6" label="Month" value="#{dateController.now}">
+        <f:convertDateTime pattern="MM/yyyy" type="date"/>
+      </tc:date>
+    </tc:section>
+    <tc:section label="Minutes">
+            <pre><code class="language-markup">&lt;tc:date label="Time" value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="HH:mm" type="time"/&gt;
+&lt;/tc:date&gt;</code></pre>
+      <tc:date id="d7" label="Time" value="#{dateController.now}">
+        <f:convertDateTime pattern="HH:mm" type="time"/>
+      </tc:date>
+    </tc:section>
+    <tc:section label="Seconds">
+            <pre><code class="language-markup">&lt;tc:date label="Time" value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="HH:mm:ss" type="time"/&gt;
+&lt;/tc:date&gt;</code></pre>
+      <tc:date id="d8" label="Time" value="#{dateController.now}">
+        <f:convertDateTime pattern="HH:mm:ss" type="time"/>
+      </tc:date>
+    </tc:section>
+    <tc:section label="Month with minutes">
+            <pre><code class="language-markup">&lt;tc:date label="Date and time" value="\#{dateController.today}"&gt;
+  &lt;f:convertDateTime pattern="dd.MM. - HH:mm" type="both"/&gt;
+&lt;/tc:date&gt;</code></pre>
+      <tc:date id="d9" label="Date and time" value="#{dateController.now}">
+        <f:convertDateTime pattern="dd.MM. - HH:mm" type="both"/>
+      </tc:date>
+    </tc:section>
+  </tc:section>
+  <tc:section label="Styles">
+    <p>Styles can be set with the attributes <code>dateStyle</code> and <code>timeStyle</code>.
+      Possible values are 'short', 'medium', 'long' and 'full'.</p>
+    <tc:date id="d10" label="Short style" value="#{dateController.now}">
+      <f:convertDateTime dateStyle="short" timeStyle="short" type="both"/>
+    </tc:date>
+    <tc:date id="d11" label="Medium Style" value="#{dateController.now}">
+      <f:convertDateTime dateStyle="medium" timeStyle="medium" type="both"/>
+    </tc:date>
+    <tc:date id="d12" label="Long Style" value="#{dateController.now}">
+      <f:convertDateTime dateStyle="long" timeStyle="long" type="both"/>
+    </tc:date>
+    <tc:date id="d13" label="Full Style" value="#{dateController.now}">
+      <f:convertDateTime dateStyle="full" timeStyle="full" type="both"/>
+    </tc:date>
+  </tc:section>
+  <tc:section label="Submit">
+    <tc:form id="formSubmit">
+      <p>Press the button to submit the date to the server. The output field show the current value.
+        The date can be changed with the datepicker or by entering a valid date in the textfield.</p>
+      <tc:date id="input" label="Input" value="#{dateController.submitDate}">
+        <f:convertDateTime pattern="dd.MM.yyyy"/>
+      </tc:date>
+      <tc:out id="output" label="Output" value="#{dateController.submitDate}">
+        <f:convertDateTime pattern="dd.MM.yyyy"/>
+      </tc:out>
+      <tc:button id="button" label="Submit"/>
+    </tc:form>
+  </tc:section>
+  <tc:section label="Ajax">
+    <p>The outputfield in this example, display the given date.
+      With <code class="language-markup">&lt;f:ajax render="outputfield"/></code>,
+      the <code class="language-markup">&lt;tc:out id="outputfield" .../></code> will be rerendered,
+      after the date changed.
+      The date can be changed by button or by entering a valid date in the textfield. If the date is not valid,
+      it won't be adopted.</p>
+    <tc:date id="ajaxinput" label="On Change" value="#{dateController.onchange}">
+      <f:convertDateTime pattern="dd.MM.yyyy"/>
+      <f:ajax render="outputfield"/>
+    </tc:date>
+    <tc:out id="outputfield" label="On Server" value="#{dateController.onchange}">
+      <f:convertDateTime pattern="dd.MM.yyyy"/>
+    </tc:out>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/group.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/group.test.js
new file mode 100644
index 0000000..35317b9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/group.test.js
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("span(https://example.com/) - inputfield", function(assert) {
+  var $mainForm = jQueryFrame("#page\\:mainForm");
+  var $inputfield = jQueryFrame("#page\\:mainForm\\:itextbefore");
+  var $span = $inputfield.find("span");
+  var $input = $inputfield.find("input");
+  var combinedWidth = $span.outerWidth(true) + $input.outerWidth(true);
+
+  assert.equal($inputfield.outerWidth(true), $mainForm.width());
+  assert.ok(combinedWidth <= $mainForm.width(),
+      "Width of inputfield (" + $span.outerWidth(true) + "px) + span (" + $input.outerWidth(true) + "px) (="
+      + combinedWidth + "px) must be smaller/equal than the width of the content box (" + $mainForm.width() + "px).");
+  assert.equal($span.outerHeight(), $input.outerHeight());
+});
+
+QUnit.test("label(Price) - inputfield - span(.00 €)", function(assert) {
+  var $mainForm = jQueryFrame("#page\\:mainForm");
+  var $inputfield = jQueryFrame("#page\\:mainForm\\:ipriceafter");
+  var $label = $inputfield.find("label");
+  var $input = $inputfield.find("input");
+  var $span = $inputfield.find("span");
+  var combinedWidth = $label.outerWidth(true) + $span.outerWidth(true) + $input.outerWidth(true);
+
+  assert.equal($inputfield.outerWidth(true), $mainForm.width());
+  assert.ok(combinedWidth <= $mainForm.width(),
+      "Width of label (" + $label.outerWidth(true) + "px) + input (" + $input.outerWidth(true) + "px) + span ("
+      + $span.outerWidth(true) + "px) (=" + combinedWidth
+      + "px) must be smaller/equal than the width of the content box (" + $mainForm.width() + "px).");
+  assert.equal($span.outerHeight(), $input.outerHeight());
+});
+
+QUnit.test("span(User Two) - inputfield - button(Send)", function(assert) {
+  var $mainForm = jQueryFrame("#page\\:mainForm");
+  var $inputfield = jQueryFrame("#page\\:mainForm\\:inewmessage");
+  var $span = $inputfield.find("span");
+  var $input = $inputfield.find("input");
+  var $button = $inputfield.find("button");
+  var combinedWidth = $span.outerWidth(true) + $input.outerWidth(true) + $button.outerWidth(true);
+
+  assert.equal($inputfield.outerWidth(true), $mainForm.width());
+  assert.ok(combinedWidth <= $mainForm.width(),
+      "Width of span (" + $span.outerWidth(true) + "px) + input (" + $input.outerWidth(true) + "px) + button ("
+      + $button.outerWidth(true) + "px) (=" + combinedWidth
+      + "px) must be smaller/equal than the width of the content box (" + $mainForm.width() + "px).");
+  assert.equal($span.outerHeight(), $input.outerHeight());
+  assert.equal($span.outerHeight(), $button.outerHeight());
+});
+
+QUnit.test("dropdown-button - inputfield", function(assert) {
+  var $mainForm = jQueryFrame("#page\\:mainForm");
+  var $inputfield = jQueryFrame("#page\\:mainForm\\:isendtoc");
+  var $button = $inputfield.find("button");
+  var $input = $inputfield.find("input");
+  var combinedWidth = $button.outerWidth(true) + $input.outerWidth(true);
+
+  assert.equal($inputfield.outerWidth(true), $mainForm.width());
+  assert.ok(combinedWidth <= $mainForm.width(),
+      "Width of button (" + $button.outerWidth(true) + "px) + input (" + $input.outerWidth(true) + "px) (="
+      + combinedWidth + "px) must be smaller/equal than the width of the content box (" + $mainForm.width() + "px).");
+  assert.equal($button.outerHeight(), $input.outerHeight());
+});
+
+QUnit.test("inputfield - span(Send To:) - dropdown-button", function(assert) {
+  var $mainForm = jQueryFrame("#page\\:mainForm");
+  var $inputfield = jQueryFrame("#page\\:mainForm\\:isendtorb");
+  var $input = $inputfield.find("input");
+  var $span = $inputfield.find(".input-group-addon");
+  var $button = $inputfield.find("button");
+  var combinedWidth = $input.outerWidth(true) + $span.outerWidth(true) + $button.outerWidth(true);
+
+  assert.equal($inputfield.outerWidth(true), $mainForm.width());
+  assert.ok(combinedWidth <= $mainForm.width(),
+      "Width of input (" + $input.outerWidth(true) + "px) + span (" + $span.outerWidth(true) + "px) + button ("
+      + $button.outerWidth(true) + "px) (=" + combinedWidth
+      + "px) must be smaller/equal than the width of the content box (" + $mainForm.width() + "px).");
+  assert.equal($input.outerHeight(), $span.outerHeight());
+  assert.equal($input.outerHeight(), $button.outerHeight());
+});
+
+QUnit.test("inputfield - dropdownbox", function(assert) {
+  var $mainForm = jQueryFrame("#page\\:mainForm");
+  var $inputfield = jQueryFrame("#page\\:mainForm\\:value");
+  var $input = $inputfield.find("input");
+  var $dropdown = $inputfield.find(".input-group-addon");
+  var combinedWidth = $input.outerWidth(true) + $dropdown.outerWidth(true);
+
+  assert.equal($inputfield.outerWidth(true), $mainForm.width());
+  assert.ok(combinedWidth <= $mainForm.width(),
+      "Width of input (" + $input.outerWidth(true) + "px) + dropdown (" + $dropdown.outerWidth(true) + "px) (="
+      + combinedWidth + "px) must be smaller/equal than the width of the content box (" + $mainForm.width() + "px).");
+  assert.equal($input.outerHeight(), $dropdown.outerHeight());
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/group.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/group.xhtml
new file mode 100644
index 0000000..1477995
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/50-input-group/group.xhtml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.group} &lt;tc:in>"/>
+
+  <p>The <code class="language-markup">&lt;tc:in/></code> tag may be extended with the facet tags
+    <code class="language-markup">&lt;f:facet name="before"></code>
+    and <code class="language-markup">&lt;f:facet name="after"></code>.
+    With these, you can add text and dropdown menus to an input field.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/in.html"/>
+
+  <tc:section label="Text">
+    <p>The following example show how to add a text-label inside an input field.</p>
+    <tc:section label="Before">
+      <pre><code class="language-markup">&lt;tc:in>
+  &lt;f:facet name="before">https://example.com/&lt;/f:facet>
+&lt;/tc:in></code></pre>
+      <tc:in id="itextbefore">
+        <f:facet name="before">https://example.com/</f:facet>
+      </tc:in>
+    </tc:section>
+    <tc:section label="After">
+      <pre><code class="language-markup">&lt;tc:in label="Price">
+  &lt;f:facet name="after">.00 €&lt;/f:facet>
+&lt;/tc:in></code></pre>
+      <tc:in id="ipriceafter" label="Price">
+        <f:facet name="after">.00 €</f:facet>
+      </tc:in>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Commands">
+    <p>Press the 'Send'-Button to add your message to the chat.</p>
+    <pre><code class="language-markup">&lt;tc:in value="\#{groupController.newMessage}">
+  ...
+  &lt;f:facet name="after">
+    &lt;tc:button label="Send" action="\#{groupController.sendChat}">
+      &lt;f:ajax execute="inewmessage" render="tachatlog"/>
+    &lt;/tc:button>
+  &lt;/f:facet>
+&lt;/tc:in></code></pre>
+    <tc:textarea id="tachatlog" label="Chat" labelLayout="top" rows="5" value="#{groupController.chatlog}"
+    readonly="true"/>
+    <tc:in id="inewmessage" value="#{groupController.newMessage}">
+      <f:facet name="before">User Two</f:facet>
+      <f:facet name="after">
+        <tc:button label="Send" action="#{groupController.sendChat}">
+          <f:ajax execute="inewmessage" render="tachatlog inewmessage"/>
+        </tc:button>
+      </f:facet>
+    </tc:in>
+  </tc:section>
+
+  <tc:section label="Dropdown Menu">
+    <p>The following two examples show an input field with a dropdown element in front of.
+      Pressing the "SendTo"-Button will display a selectable list.
+      This list is different in the examples.
+      Notice that the <code>omit</code> attribute is set for <code class="language-markup">&lt;tc:link/></code>.</p>
+
+    <tc:section label="Commands">
+      <pre><code class="language-markup">&lt;tc:in placeholder="type a message">
+  &lt;f:facet name="before">
+    &lt;tc:button id="lsendtoc" label="\#{groupController.sendTo}" omit="true">
+      &lt;tc:command label="SendTo: Peter">
+        &lt;f:ajax render="isendtoc" execute="isendtoc" listener="\#{groupController.sendToListener}"/>
+      &lt;/tc:command>
+      ...
+    &lt;/tc:button>
+  &lt;/f:facet>
+&lt;/tc:in></code></pre>
+      <tc:in id="isendtoc" placeholder="type a message">
+        <f:facet name="before">
+          <tc:button id="lsendtoc" label="#{groupController.sendTo}" omit="true">
+            <tc:link label="SendTo: Peter">
+              <f:ajax render="isendtoc" execute="isendtoc" listener="#{groupController.sendToListener}"/>
+            </tc:link>
+            <tc:link label="SendTo: Bob">
+              <f:ajax render="isendtoc" execute="isendtoc" listener="#{groupController.sendToListener}"/>
+            </tc:link>
+            <tc:link label="SendTo: All">
+              <f:ajax render="isendtoc" execute="isendtoc" listener="#{groupController.sendToListener}"/>
+            </tc:link>
+          </tc:button>
+        </f:facet>
+      </tc:in>
+    </tc:section>
+
+    <tc:section label="Radio Buttons">
+      <pre><code class="language-markup">&lt;tc:in id="isendtorb" placeholder="type a message">
+  &lt;f:facet name="after">
+    &lt;tc:button id="lsendtorb" label="\#{groupController.sendTo}" omit="true">
+      &lt;tc:selectOneRadio value="\#{groupController.sendTo}">
+        &lt;tc:selectItem itemValue="SendTo: Peter"/>
+        ...
+        &lt;f:ajax render="isendtorb"/>
+      &lt;/tc:selectOneRadio>
+    &lt;/tc:button>
+  &lt;/f:facet>
+&lt;/tc:in></code></pre>
+      <tc:in id="isendtorb" placeholder="type a message">
+        <f:facet name="after">
+          Send To:
+          <tc:button id="lsendtorb" label="#{groupController.sendTo}" omit="true">
+            <tc:selectOneRadio value="#{groupController.sendTo}">
+              <tc:selectItem itemValue="Peter"/>
+              <tc:selectItem itemValue="Bob"/>
+              <tc:selectItem itemValue="All"/>
+              <f:ajax render="isendtorb"/>
+            </tc:selectOneRadio>
+          </tc:button>
+        </f:facet>
+      </tc:in>
+    </tc:section>
+
+    <tc:section label="Choice">
+      <tc:in id="value" placeholder="type an amount" value="#{groupController.value}">
+        <f:convertNumber maxFractionDigits="2" minFractionDigits="2"/>
+        <f:facet name="after">
+          <tc:selectOneChoice value="#{groupController.currency}">
+            <tc:selectItems value="#{groupController.currencies}" var="currency"
+                           itemValue="#{currency}" itemLabel="#{currency.displayName}"/>
+            <f:ajax listener="#{groupController.compute}" render="valueInEuro" execute="value"/>
+          </tc:selectOneChoice>
+        </f:facet>
+      </tc:in>
+      <tc:out id="valueInEuro" label="Value in €" value="#{groupController.valueInEuro}">
+        <f:convertNumber maxFractionDigits="2" minFractionDigits="2" currencySymbol="€"/>
+      </tc:out>
+    </tc:section>
+
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/input.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/input.xhtml
new file mode 100644
index 0000000..aacfc79
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/010-input/input.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.input}"/>
+  <p>With input components, a text or a date can be entered.
+    Input components should always use the <code>label</code> attribute.</p>
+
+  <tc:section label="#{demoBundle.in}">
+    <pre><code class="language-markup">&lt;tc:in label="Input" value="Some Text"/></code></pre>
+    <tc:in id="i1" label="Input" value="Some Text"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.suggest}">
+    <pre><code class="language-markup">&lt;tc:in label="Language">
+  &lt;tc:suggest query="\#{suggestController.query}">
+    &lt;tc:selectItems value="\#{suggestController.languages}" var="language" itemValue="\#{language}"/>
+  &lt;/tc:suggest>
+&lt;/tc:in></code></pre>
+    <tc:in id="i2" label="Language">
+      <tc:suggest query="#{suggestController.query}">
+        <tc:selectItems value="#{suggestController.languages}" var="language" itemValue="#{language}"/>
+      </tc:suggest>
+    </tc:in>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.textarea}">
+    <pre><code class="language-markup">&lt;tc:textarea label="Text Area" value="Some Text"/></code></pre>
+    <tc:textarea id="t1" label="Text Area" value="Some Text"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.date}">
+    <pre><code class="language-markup">&lt;tc:date label="Date" value="2015-12-21"/></code></pre>
+    <tc:date id="d1" label="Date" value="2015-12-21"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/10-out/out.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/10-out/out.xhtml
new file mode 100644
index 0000000..3883110
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/10-out/out.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.out} &lt;tc:out&gt;"/>
+  <p>The <code class="language-markup">&lt;tc:out/></code> display an outputtext combined with a label.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/out.html"/>
+  <tc:section label="Basics">
+    <p>To put a label in front of a outputtext, use the <code>label</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:out label="Output" value="Some Text"/&gt;</code></pre>
+    <tc:out id="o1" label="Output" value="Some Text"/>
+    <tc:out id="o2" value="Output without a label"/>
+  </tc:section>
+  <tc:section label="Escape">
+    <p>If the given string to the outputfield is HTML/XML code, it will be escaped by default.
+      But you can turn it off with the <code>escape</code> attribute.</p>
+    <tc:section label="Escape on (default)">
+      <pre><code
+              class="language-markup">&lt;tc:out label="Escape on (default)" escape="true" value="\#{outController.html}"/&gt;</code></pre>
+      <tc:out id="o3" label="Escape on (default)" escape="true" value="#{outController.html}"/>
+    </tc:section>
+    <tc:section label="Escape off">
+      <p>Although the HTML code is not escaped, you can see, that the text is not colored.
+        This is, because the code is sanitzed (see next section).</p>
+      <pre><code
+              class="language-markup">&lt;tc:out label="Escape off" escape="false" value="\#{outController.html}"/&gt;</code></pre>
+      <tc:out id="o4" label="Escape off" escape="false" value="#{outController.html}"/>
+    </tc:section>
+  </tc:section>
+  <tc:section label="Sanitize">
+    <p>Sanitize remove HTML/XML-Tags from a given string if not escaped. It can be configured in the tobago-config.xml.
+      If you want to write your own sanitizer, you have to implement
+      <code>org.apache.myfaces.tobago.sanitizer.Sanitizer</code>.</p>
+    <p>Sanitzing can be deactivated for a component using the <code>sanitize</code> attribute.
+      But be careful, because of XSS vulnerability.</p>
+    <pre><code
+            class="language-markup">&lt;tc:out label="Sanitize off" escape="false" sanitize="never" value="\#{outController.html}"/&gt;</code></pre>
+    <tc:out id="o5" label="Sanitize off" escape="false" sanitize="never" value="#{outController.html}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/20-label/label.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/20-label/label.xhtml
new file mode 100644
index 0000000..edc651b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/20-label/label.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.label} &lt;tc:label&gt;"/>
+  <p>With <code class="language-markup">&lt;tc:label/></code>, a single label can be created.
+    Some components already have a <code>label</code> attribute to combine it with a label,
+    which should be used in general.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/label.html"/>
+  <tc:section label="Basics">
+    <pre><code class="language-markup">&lt;tc:label value="Single Label"/&gt;</code></pre>
+    <tc:label id="l1" value="Single Label"/>
+  </tc:section>
+
+  <tc:section label="Input Field">
+    <p>With <code class="language-markup">&lt;tc:flexLayout columns="250px;*;200px"></code> a label is set
+      in front and after an inputfield. The <code>label</code> attribute is not used for
+      <code class="language-markup">&lt;tc:in/></code>.</p>
+    <tc:flexLayout columns="250px;*;200px">
+      <tc:label id="l2" value="Label in front of inputfield"/>
+      <tc:in id="i1" placeholder="Inputfield"/>
+      <tc:label id="l3" value="Label after inputfield"/>
+    </tc:flexLayout>
+  </tc:section>
+
+  <tc:section label="Automatic Label">
+    See <tc:link label="Labeled Layout" link="../../../30-concept/16-layout/00/labeled-layout.xhtml"/>
+  </tc:section>
+
+  <tc:section label="Progress Bar">
+    <p>Some components like <code class="language-markup">&lt;tc:progress/></code> do not have a <code>label</code>
+      attribute. In this example, a label is combined with a progressbar using
+      <code class="language-markup">&lt;tc:flowLayout/></code>.</p>
+    <tc:flowLayout>
+      <tc:label id="l4" value="Progress:"/>
+      <tc:progress value="0.4" max="1"/>
+    </tc:flowLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/30-messages/messages.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/30-messages/messages.xhtml
new file mode 100644
index 0000000..3c1caac
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/30-messages/messages.xhtml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.messages} &lt;tc:messages>"/>
+  <p>Messages are displayed via <code class="language-markup">&lt;tc:messages/></code> tag.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/messages.html"/>
+
+  <tc:section label="Create Message">
+    <p>To create messages, press one of the following buttons. The message will be displayed in the tabgroup.</p>
+    <p>If you are using ajax, make sure to rerender the <code class="language-markup">&lt;tc:message/></code> tag.</p>
+    <tc:button label="Fatal" action="#{messagesController.createFatalMessage}"/>
+    <tc:button label="Error" action="#{messagesController.createErrorMessage}"/>
+    <tc:button label="Warn" action="#{messagesController.createWarnMessage}"/>
+    <tc:button label="Info" action="#{messagesController.createInfoMessage}"/>
+    <tc:button label="7 Messages" action="#{messagesController.createSevenMessages}"/>
+    <tc:button label="7 Messages (Ajax)" action="#{messagesController.createSevenMessages}">
+      <f:ajax render="tabGroup"/>
+    </tc:button>
+  </tc:section>
+
+  <tc:tabGroup id="tabGroup" switchType="reloadPage">
+    <tc:tab label="Without attributes">
+      <p>On this tab, you can see how messages are displayed if no attribute are set for the
+        <code class="language-markup">&lt;tc:messages/></code> tag.</p>
+      <tc:messages/>
+    </tc:tab>
+
+    <tc:tab label="Number of messages">
+      <p>A limit for the number of messages can be set with the <code>maxNumber</code> attribute.</p>
+      <pre><code class="language-markup">&lt;tc:messages maxNumber="2"/></code></pre>
+      <tc:messages maxNumber="2"/>
+    </tc:tab>
+
+    <tc:tab label="Severity">
+      <p>The range, which severities are displayed, can be set with <code>minSeverity</code> and
+        <code>maxSeverity</code>. In this example, only warnings and error should be displayed.</p>
+      <pre><code
+              class="language-markup">&lt;tc:messages minSeverity="#{messagesController.severityWarn}" maxSeverity="#{messagesController.severityError}"/></code></pre>
+      <tc:messages minSeverity="#{messagesController.severityWarn}" maxSeverity="#{messagesController.severityError}"/>
+    </tc:tab>
+
+    <tc:tab label="Details">
+      <p>A message can also contain 'details', you can show it with <code>showDetail</code>.</p>
+      <pre><code class="language-markup">&lt;tc:messages showDetail="true"/></code></pre>
+      <tc:messages showDetail="true"/>
+    </tc:tab>
+
+    <tc:tab label="Hide summary">
+      <p>In this example, only the details are shown. To hide the summary, use <code>showSummary</code>.</p>
+      <pre><code class="language-markup">&lt;tc:messages showSummary="false" showDetail="true"/></code></pre>
+      <tc:messages showSummary="false" showDetail="true"/>
+    </tc:tab>
+
+    <tc:tab label="Order">
+      <tc:segmentLayout medium="6;6">
+        <tc:box label="severity">
+          <p>By default, messages are sorted by severity.
+            Therefor, the <code>orderBy</code> attribute is not needed in this case.</p>
+          <pre><code class="language-markup">&lt;tc:messages orderBy="severity"/></code></pre>
+          <tc:messages orderBy="severity"/>
+        </tc:box>
+        <tc:box label="occurrence">
+          <p>Messages displayed in the order they occurred.</p>
+          <pre><code class="language-markup">&lt;tc:messages orderBy="occurrence"/></code></pre>
+          <tc:messages orderBy="occurrence"/>
+        </tc:box>
+      </tc:segmentLayout>
+    </tc:tab>
+  </tc:tabGroup>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/40-image/image.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/40-image/image.xhtml
new file mode 100644
index 0000000..bf85616
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/40-image/image.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.image} &lt;tc:image&gt;"/>
+  <p>Create an image with <code class="language-markup">&lt;tc:image/&gt;</code>.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/image.html"/>
+  <tc:section label="Basics">
+    <pre><code class="language-markup">&lt;tc:image value="\#{request.contextPath}/image/tobago_head.png"/&gt;</code></pre>
+    <tc:image id="i1" value="#{request.contextPath}/image/tobago_head.png"/>
+  </tc:section>
+  <tc:section label="Set width">
+    <p>To set the size of an image, <code>&lt;tc:style/&gt;</code> can be used.</p>
+    <pre><code class="language-markup">&lt;tc:image value="\#{request.contextPath}/image/tobago_head.png"&gt;
+  &lt;tc:style width="20%"/&gt;
+&lt;/tc:image&gt;</code></pre>
+    <tc:image id="i2" value="#{request.contextPath}/image/tobago_head.png">
+      <tc:style width="20%"/>
+    </tc:image>
+  </tc:section>
+  <tc:section label="Disable">
+    <p>The <code>disabled</code> attribute can be used, to let the picture look more 'disabled'.</p>
+    <tc:section label="Disabled off">
+      <p>Disabled is 'false' by default.</p>
+      <pre><code class="language-markup">&lt;tc:image disabled="false" value="\#{request.contextPath}/image/alps.png"/&gt;</code></pre>
+      <tc:image id="i3" disabled="false" value="#{request.contextPath}/image/alps.png"/>
+    </tc:section>
+    <tc:section label="Disabled on">
+      <pre><code class="language-markup">&lt;tc:image disabled="true" value="\#{request.contextPath}/image/alps.png"/&gt;</code></pre>
+      <tc:image id="i4" disabled="true" value="#{request.contextPath}/image/alps.png"/>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/45-figure/figure.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/45-figure/figure.xhtml
new file mode 100644
index 0000000..53d92f1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/45-figure/figure.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.figure} &lt;tc:figure>"/>
+  <p>Create a figure with <code class="language-markup">&lt;tc:figure/&gt;</code> around an image,
+    video or something else. The label can be set via the label attribute or with the label facet.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/figure.html"/>
+
+  <tc:section label="Label attribute">
+    <p>For simple captions use the <code>label</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:figure label="Picture of the alps.">
+  &lt;tc:image value="image/alps.png"/>
+&lt;/tc:figure></code></pre>
+    <tc:figure label="Picture of the alps.">
+      <tc:image value="#{request.contextPath}/image/alps.png"/>
+    </tc:figure>
+  </tc:section>
+
+  <tc:section label="Label facet">
+    <p>For more complex captions use <code class="language-markup">&lt;f:facet name="label"></code>.
+      In this example the word 'tobago' is colored red.</p>
+    <tc:figure>
+      <f:facet name="label">The <span style="color: red">tobago</span> logo.</f:facet>
+      <tc:image id="image" value="#{request.contextPath}/image/tobago_head.png"/>
+    </tc:figure>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/50-progress/progress.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/50-progress/progress.xhtml
new file mode 100644
index 0000000..35054aa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/50-progress/progress.xhtml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.progress} &lt;tc:progress>"/>
+  <p>The <code class="language-markup">&lt;tc:progress/></code> tag create a progressbar.
+    The most important attribute is <code>value</code>.
+    It could be a <code>double</code> - in that case, you need the attribute <code>max</code> as well.
+    Or it is of type <code>BoundedRangeModel</code>.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:progress/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/progress.html"/>
+    |
+    <tc:link label="BoundedRangeModel"
+             link="https://docs.oracle.com/javase/7/docs/api/javax/swing/BoundedRangeModel.html"/></p>
+
+  <tc:section label="Basics">
+    <p>A static progressbar, with <code>value</code> of type <code>double</code>.</p>
+    <pre><code class="language-markup">&lt;tc:progress value="15.8" max="20"/></code></pre>
+    <tc:progress value="14.9" max="20"/>
+  </tc:section>
+
+  <tc:section label="Style">
+    <p>A static progressbar containing a <code class="language-markup">&lt;tc:style width="50%" height="2px"/></code>
+      tag.</p>
+    <tc:progress value="14.9" max="20">
+      <tc:style width="50%" height="2px"/>
+    </tc:progress>
+  </tc:section>
+
+  <tc:section label="Button">
+    <p>By pressing the button, progress is added to the progressbar.</p>
+    <pre><code class="language-markup">&lt;tc:button label="Add Progress" action="\#{progressController.addProgress}"/>
+&lt;tc:progress value="\#{progressController.progress}"/></code></pre>
+    <tc:button id="b1" label="Add Progress" action="#{progressController.addProgress}"/>
+    <br/>
+    <tc:progress value="#{progressController.progress}"/>
+  </tc:section>
+
+  <tc:section label="Time">
+    <p>In this example, the current time is displayed as progressbars.</p>
+    <pre><code
+            class="language-markup">&lt;tc:progress value="\#{progressController.currentHours}" max="23"/></code></pre>
+    <tc:panel id="reloadPanel">
+      <f:facet name="reload">
+        <tc:reload frequency="1000" update="true"/>
+      </f:facet>
+
+      <p>
+        <span class="tag tag-danger">Warning!</span>
+        <b>The reload feature is preliminary and may be subject of change in later versions!</b>
+      </p>
+
+      <tc:out id="o1" label="Current Date" value="#{progressController.currentDate}">
+        <f:convertDateTime pattern="HH:mm:ss"/>
+      </tc:out>
+
+      <tc:label value="Hour"/>
+      <tc:progress value="#{progressController.currentHours}" max="23"/>
+      <br/>
+      <tc:label value="Minutes"/>
+      <tc:progress value="#{progressController.currentMinutes}" max="59"/>
+      <br/>
+      <tc:label value="Seconds"/>
+      <tc:progress value="#{progressController.currentSeconds}" max="59"/>
+    </tc:panel>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/60-object/object.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/60-object/object.js
new file mode 100644
index 0000000..b869ad7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/60-object/object.js
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function ($) {
+
+
+  $.widget("demo.maps", {
+
+    options: {
+      position: "11.249123,-60.687103", // tobago
+      zoom: 2 // global
+    },
+
+    _create: function () {
+      this._on({
+        click: function (event) {
+          var position = this.element.data("maps-position");
+          if (position == null) {
+            position = this.options.position;
+          }
+          var zoom = this.element.data("maps-zoom");
+          if (zoom == null) {
+            zoom = this.options.zoom;
+          }
+          var target = this.element.data("maps-target");
+          var url = 'https://maps.google.com/maps?'
+              + 'ie=UTF8&ll=' + position + '&t=h&z=' + zoom + '&output=embed&f=q&cd=1';
+          jQuery(Tobago.Utils.escapeClientId(target)).attr('src', url);
+        }
+      });
+    },
+
+    _setOption: function (key, value) {
+    },
+
+    _destroy: function () {
+    }
+
+  });
+
+}(jQuery));
+
+var initMaps = function () {
+  jQuery("[data-maps-target]")
+      .maps()
+      .first()
+      .click();
+};
+
+Tobago.registerListener(initMaps, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/60-object/object.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/60-object/object.xhtml
new file mode 100644
index 0000000..3143568
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/60-object/object.xhtml
@@ -0,0 +1,85 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.object} &lt;tc:object&gt;"/>
+  <tc:script file="#{request.contextPath}/content/20-component/020-output/60-object/object.js"/>
+
+  <p>The <code class="language-markup">&lt;tc:object/></code> tag create an iframe.
+    External objects can be included, when Content Security Policy is activated.
+    You may add a frame-src policy to the 'tobago-config.xml'.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/object.html"/>
+  <tc:section label="Basics">
+    <pre><code class="language-markup">&lt;tc:object src="https://www.google.com/maps/..."/&gt;</code></pre>
+    <tc:object id="o1"
+               src="https://www.google.com/maps/embed?pb=!1m10!1m8!1m3!1d137123.69440217633!2d-60.687103!3d11.249123!3m2!1i1024!2i768!4f13.1!5e1!3m2!1sde!2sus!4v1458208065829"/>
+  </tc:section>
+  <tc:section label="Style">
+    <p>A <code class="language-markup">&lt;tc:object/></code> tag can contain a style tag.
+      In this case it's <code class="language-markup">&lt;tc:style width="100%"/></code>.</p>
+    <tc:object id="o2"
+               src="https://www.google.com/maps/embed?pb=!1m13!1m11!1m3!1d99967845.2048925!2d-60.68710300000001!3d11.249123!2m2!1f0!2f0!3m2!1i1024!2i768!4f13.1!5e1!3m2!1sde!2sus!4v1458208366973">
+      <tc:style width="100%"/>
+    </tc:object>
+  </tc:section>
+  <tc:section label="Tool Bar">
+    <p>There are two <code class="language-markup">&lt;tc:button/></code>
+      within a <code class="language-markup">&lt;tc:buttons/></code> in this example.
+      The first show the island Tobago,
+      the second show the worldmap in <code class="language-markup">&lt;tc:object id="map"></code>.
+      The buttons send the parameter (maps-position, maps-zoom, maps-target) to an <code>object.js</code>,
+      which is shown in the objects.js-box. The JavaScript build the URL for the iframe.</p>
+    <pre><code class="language-markup">&lt;tc:button label="Show Tobago" omit="true"&gt;
+  &lt;tc:dataAttribute name="maps-position" value="11.249123,-60.687103"/&gt;
+  &lt;tc:dataAttribute name="maps-zoom" value="12"/&gt;
+  &lt;tc:dataAttribute name="maps-target" value="page:map"/&gt;
+&lt;/tc:button&gt;</code></pre>
+    <tc:box id="objectJsBox" label="object.js" collapsed="true" collapsedMode="hidden">
+      <f:facet name="bar">
+        <tc:buttons>
+          <tc:button label="show" omit="true">
+            <tc:operation name="show" for="objectJsBox"/>
+          </tc:button>
+          <tc:button label="hide" omit="true">
+            <tc:operation name="hide" for="objectJsBox"/>
+          </tc:button>
+        </tc:buttons>
+      </f:facet>
+      <pre><code class="language-javascript"><tc:out value="#{objectController.javaScriptSource}"/></code></pre>
+    </tc:box>
+    <tc:buttons id="t1">
+      <tc:button id="c1" label="Show Tobago" omit="true">
+        <tc:dataAttribute name="maps-position" value="11.249123,-60.687103"/>
+        <tc:dataAttribute name="maps-zoom" value="12"/>
+        <tc:dataAttribute name="maps-target" value="page:mainForm:map"/>
+      </tc:button>
+      <tc:button id="c2" label="Show World" omit="true">
+        <tc:dataAttribute name="maps-target" value="page:mainForm:map"/>
+      </tc:button>
+    </tc:buttons>
+    <tc:object id="map">
+      <tc:style width="100%" height="500px"/>
+    </tc:object>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/output.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/output.xhtml
new file mode 100644
index 0000000..48c8114
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/020-output/output.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <ui:param name="title" value="#{demoBundle.output}"/>
+  <p>The output components display data in different ways.</p>
+
+  <tc:section label="#{demoBundle.output}">
+    <pre><code class="language-markup">&lt;tc:out label="Output" value="Some Text"/></code></pre>
+    <tc:out id="o1" label="Output" value="Some Text"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.label}">
+    <pre><code class="language-markup">&lt;tc:label value="Some Text"/></code></pre>
+    <tc:label value="Some Text"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.messages}">
+    <pre><code class="language-markup">&lt;tc:messages/></code></pre>
+    <tc:messages/>
+    <tc:button id="b1" label="Create Info Message" action="#{messagesController.createInfoMessage}"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.image}">
+    <pre><code class="language-markup">&lt;tc:image value="image/tobago_head.png"/></code></pre>
+    <tc:image value="/image/tobago_head.png"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.progress}">
+    <pre><code class="language-markup">&lt;tc:progress value="2" max="3"/></code></pre>
+    <tc:progress value="2" max="3"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.object}">
+    <pre><code class="language-markup">&lt;tc:object src="https://www.google.com/maps/..."/></code></pre>
+    <tc:object
+            src="https://www.google.com/maps/embed?pb=!1m10!1m8!1m3!1d137123.69440217633!2d-60.687103!3d11.249123!3m2!1i1024!2i768!4f13.1!5e1!3m2!1sde!2sus!4v1458208065829"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/selectBooleanCheckbox.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/selectBooleanCheckbox.test.js
new file mode 100644
index 0000000..00671aa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/selectBooleanCheckbox.test.js
@@ -0,0 +1,164 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit: select A", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectA = jQueryFrame("#page\\:mainForm\\:selectA input");
+  var $selectB = jQueryFrame("#page\\:mainForm\\:selectB input");
+  var $selectC = jQueryFrame("#page\\:mainForm\\:selectC input");
+  var $submit = jQueryFrame("#page\\:mainForm\\:submit");
+
+  $selectA.prop("checked", true);
+  $selectB.prop("checked", false);
+  $selectC.prop("checked", false);
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:submitOutput span");
+    assert.equal($output.text(), "A ");
+    done();
+  });
+});
+
+QUnit.test("submit: select B and C", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectA = jQueryFrame("#page\\:mainForm\\:selectA input");
+  var $selectB = jQueryFrame("#page\\:mainForm\\:selectB input");
+  var $selectC = jQueryFrame("#page\\:mainForm\\:selectC input");
+  var $submit = jQueryFrame("#page\\:mainForm\\:submit");
+
+  $selectA.prop("checked", false);
+  $selectB.prop("checked", true);
+  $selectC.prop("checked", true);
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:submitOutput span");
+    assert.equal($output.text(), "B C ");
+    done();
+  });
+});
+
+QUnit.test("ajax: select D", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectD = jQueryFrame("#page\\:mainForm\\:selectD input");
+  var $outputD = jQueryFrame("#page\\:mainForm\\:outputD span");
+
+  $selectD.prop("checked", true).trigger("change");
+
+  waitForAjax(function () {
+    $outputD = jQueryFrame($outputD.selector);
+    return $outputD.text() == "true";
+  }, function () {
+    $outputD = jQueryFrame($outputD.selector);
+    assert.equal($outputD.text(), "true");
+    done();
+  });
+});
+
+QUnit.test("ajax: deselect D", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectD = jQueryFrame("#page\\:mainForm\\:selectD input");
+  var $outputD = jQueryFrame("#page\\:mainForm\\:outputD span");
+
+  $selectD.prop("checked", false).trigger("change");
+
+  waitForAjax(function () {
+    $outputD = jQueryFrame($outputD.selector);
+    return $outputD.text() == "false";
+  }, function () {
+    $outputD = jQueryFrame($outputD.selector);
+    assert.equal($outputD.text(), "false");
+    done();
+  });
+});
+
+QUnit.test("ajax: select E", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectE = jQueryFrame("#page\\:mainForm\\:selectE input");
+  var $outputE = jQueryFrame("#page\\:mainForm\\:outputE span");
+
+  $selectE.prop("checked", true).trigger("change");
+
+  waitForAjax(function () {
+    $outputE = jQueryFrame($outputE.selector);
+    return $outputE.text() == "true";
+  }, function () {
+    $outputE = jQueryFrame($outputE.selector);
+    assert.equal($outputE.text(), "true");
+    done();
+  });
+});
+
+QUnit.test("ajax: deselect E", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectE = jQueryFrame("#page\\:mainForm\\:selectE input");
+  var $outputE = jQueryFrame("#page\\:mainForm\\:outputE span");
+
+  $selectE.prop("checked", false).trigger("change");
+
+  waitForAjax(function () {
+    $outputE = jQueryFrame($outputE.selector);
+    return $outputE.text() == "false";
+  }, function () {
+    $outputE = jQueryFrame($outputE.selector);
+    assert.equal($outputE.text(), "false");
+    done();
+  });
+});
+
+QUnit.test("ajax: select F", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectF = jQueryFrame("#page\\:mainForm\\:selectF input");
+  var $outputF = jQueryFrame("#page\\:mainForm\\:outputF span");
+
+  $selectF.prop("checked", true).trigger("change");
+
+  waitForAjax(function () {
+    $outputF = jQueryFrame($outputF.selector);
+    return $outputF.text() == "true";
+  }, function () {
+    $outputF = jQueryFrame($outputF.selector);
+    assert.equal($outputF.text(), "true");
+    done();
+  });
+});
+
+QUnit.test("ajax: deselect F", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $selectF = jQueryFrame("#page\\:mainForm\\:selectF input");
+  var $outputF = jQueryFrame("#page\\:mainForm\\:outputF span");
+
+  $selectF.prop("checked", false).trigger("change");
+
+  waitForAjax(function () {
+    $outputF = jQueryFrame($outputF.selector);
+    return $outputF.text() == "false";
+  }, function () {
+    $outputF = jQueryFrame($outputF.selector);
+    assert.equal($outputF.text(), "false");
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/selectBooleanCheckbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/selectBooleanCheckbox.xhtml
new file mode 100644
index 0000000..a894cd1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/10-selectBooleanCheckbox/selectBooleanCheckbox.xhtml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.selectBooleanCheckbox} &lt;tc:selectBooleanCheckbox&gt;"/>
+  <p>The tag <code class="language-markup">&lt;tc:selectBooleanCheckbox/></code> generate a classic boolean
+    checkbox.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectBooleanCheckbox.html"/>
+  <tc:section label="Basics">
+    <pre><code class="language-markup">&lt;tc:selectBooleanCheckbox label="Checkbox" value="true"/&gt;</code></pre>
+    <tc:selectBooleanCheckbox id="s1" label="Normal Checkbox" value="true"/>
+    <tc:selectBooleanCheckbox id="s2" label="Read Only" readonly="true" value="true"/>
+    <tc:selectBooleanCheckbox id="s3" label="Disabled" disabled="true" value="true"/>
+    <tc:selectBooleanCheckbox id="s4" label="Required" required="true" value="true"/>
+  </tc:section>
+
+  <tc:section label="ItemLabel">
+    <tc:selectBooleanCheckbox id="checkboxItemlabel1" itemLabel="Normal Checkbox" value="true"/>
+    <tc:selectBooleanCheckbox id="checkboxItemlabel11" label="Large Label" itemLabel="Item Label" value="true"/>
+    <tc:selectBooleanCheckbox id="checkboxItemlabel2" itemLabel="Read Only" readonly="true" value="true"/>
+    <tc:selectBooleanCheckbox id="checkboxItemlabel3" itemLabel="Disabled" disabled="true" value="true"/>
+    <tc:selectBooleanCheckbox id="checkboxItemlabel4" itemLabel="Required" required="true" value="true"/>
+  </tc:section>
+
+  <tc:section label="Simple Usage">
+    <p>In this example, the selected items are displayed in an outputfield after the submit-button is pressed.</p>
+    <pre><code class="language-markup">&lt;tc:selectBooleanCheckbox label="A" value="\#{selectBooleanCheckboxController.a}"/>
+&lt;tc:out label="Selected items: " value="\#{selectBooleanCheckboxController.selectedItems}"/></code></pre>
+    <tc:selectBooleanCheckbox id="selectA" label="A" value="#{selectBooleanCheckboxController.a}"/>
+    <tc:selectBooleanCheckbox id="selectB" label="B" value="#{selectBooleanCheckboxController.b}"/>
+    <tc:selectBooleanCheckbox id="selectC" label="C" value="#{selectBooleanCheckboxController.c}"/>
+    <tc:out id="submitOutput" label="Selected items: " value="#{selectBooleanCheckboxController.selectedItems}"/>
+    <tc:button id="submit" label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>The outputfields always shows the current value of the checkbox.
+      With <code class="language-markup">&lt;f:ajax render="output"/></code>, the outputfield will be rerendered,
+      after the value changed in the
+      <code class="language-markup">&lt;tc:selectBooleanCheckbox label="Character" value="#{selectBooleanCheckboxController.d}"/></code>.
+      The ID of the outputfield and the value in the <code>render</code> attribute of the ajax tag
+      has to be the same.</p>
+    <tc:selectBooleanCheckbox id="selectD" label="D" value="#{selectBooleanCheckboxController.d}">
+      <f:ajax render="outputD"/>
+    </tc:selectBooleanCheckbox>
+    <tc:out id="outputD" label="Value is" value="#{selectBooleanCheckboxController.d}"/>
+    <tc:selectBooleanCheckbox id="selectE" label="E" value="#{selectBooleanCheckboxController.e}">
+      <f:ajax render="outputE"/>
+    </tc:selectBooleanCheckbox>
+    <tc:out id="outputE" label="Value is" value="#{selectBooleanCheckboxController.e}"/>
+    <tc:selectBooleanCheckbox id="selectF" label="F" value="#{selectBooleanCheckboxController.f}">
+      <f:ajax render="outputF"/>
+    </tc:selectBooleanCheckbox>
+    <tc:out id="outputF" label="Value is" value="#{selectBooleanCheckboxController.f}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/selectOneChoice.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/selectOneChoice.test.js
new file mode 100644
index 0000000..d1cc277
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/selectOneChoice.test.js
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit: Alice", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $alice = jQueryFrame("#page\\:mainForm\\:selectPerson\\:\\:field option:contains('Alice')");
+  var $bob = jQueryFrame("#page\\:mainForm\\:selectPerson\\:\\:field option:contains('Bob')");
+  var $submit = jQueryFrame("#page\\:mainForm\\:submit");
+
+  $alice.prop("selected", true);
+  $bob.prop("selected", false);
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:outputPerson span");
+    assert.equal($output.text(), "Alice Anderson");
+    done();
+  });
+});
+
+QUnit.test("submit: Bob", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $alice = jQueryFrame("#page\\:mainForm\\:selectPerson\\:\\:field option:contains('Alice')");
+  var $bob = jQueryFrame("#page\\:mainForm\\:selectPerson\\:\\:field option:contains('Bob')");
+  var $submit = jQueryFrame("#page\\:mainForm\\:submit");
+
+  $alice.prop("selected", false);
+  $bob.prop("selected", true);
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:outputPerson span");
+    assert.equal($output.text(), "Bob Brunch");
+    done();
+  });
+});
+
+QUnit.test("ajax: select Mars", function (assert) {
+  assert.expect(2);
+  var done = assert.async();
+  var $mars = jQueryFrame("#page\\:mainForm\\:selectPlanet\\:\\:field option:contains('Mars')");
+  var $jupiter = jQueryFrame("#page\\:mainForm\\:selectPlanet\\:\\:field option:contains('Jupiter')");
+  var $moons = jQueryFrame("#page\\:mainForm\\:moonbox\\:\\:field option");
+
+  $jupiter.prop("selected", false);
+  $mars.prop("selected", true).trigger("change");
+
+  waitForAjax(function () {
+    $moons = jQueryFrame($moons.selector);
+    return $moons.eq(0).text() == "Phobos"
+        && $moons.eq(1).text() == "Deimos";
+  }, function () {
+    $moons = jQueryFrame($moons.selector);
+    assert.equal($moons.eq(0).text(), "Phobos");
+    assert.equal($moons.eq(1).text(), "Deimos");
+    done();
+  });
+});
+
+QUnit.test("ajax: select Jupiter", function (assert) {
+  assert.expect(4);
+  var done = assert.async();
+  var $mars = jQueryFrame("#page\\:mainForm\\:selectPlanet\\:\\:field option:contains('Mars')");
+  var $jupiter = jQueryFrame("#page\\:mainForm\\:selectPlanet\\:\\:field option:contains('Jupiter')");
+  var $moons = jQueryFrame("#page\\:mainForm\\:moonbox\\:\\:field option");
+
+  $mars.prop("selected", false);
+  $jupiter.prop("selected", true).trigger("change");
+
+  waitForAjax(function () {
+    $moons = jQueryFrame($moons.selector);
+    return $moons.eq(0).text() == "Europa"
+        && $moons.eq(1).text() == "Ganymed"
+        && $moons.eq(2).text() == "Io"
+        && $moons.eq(3).text() == "Kallisto";
+  }, function () {
+    $moons = jQueryFrame($moons.selector);
+    assert.equal($moons.eq(0).text(), "Europa");
+    assert.equal($moons.eq(1).text(), "Ganymed");
+    assert.equal($moons.eq(2).text(), "Io");
+    assert.equal($moons.eq(3).text(), "Kallisto");
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/selectOneChoice.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/selectOneChoice.xhtml
new file mode 100644
index 0000000..f826d99
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/20-selectOneChoice/selectOneChoice.xhtml
@@ -0,0 +1,92 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.selectOneChoice} &lt;tc:selectOneChoice>"/>
+  <p>The tag <code class="language-markup">&lt;tc:selectOneChoice/&gt;</code> create a dropdownbox,
+    which contain<br/>
+    <code class="language-markup">&lt;tc:selectItem/></code> for static entries or<br/>
+    <code class="language-markup">&lt;tc:selectItems value="\#{controller.list}"/></code> for entries from
+    a controller.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:selectOneChoice/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectOneChoice.html"/>
+    |
+    <tc:link label="&lt;tc:selectItem/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItem.html"/>
+    |
+    <tc:link label="&lt;tc:selectItems/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItems.html"/></p>
+
+  <tc:section label="Basics">
+    <p>Dropdown Box with hardcoded items. The second item is disabled.
+      To disable an item, use the <code>itemDisable</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:selectOneChoice label="Dropdown Box"/></code></pre>
+    <tc:selectOneChoice id="s1" label="Dropdown Box">
+      <tc:selectItem itemLabel="Item One" itemValue="one"/>
+      <tc:selectItem itemLabel="Item Two" itemValue="two" itemDisabled="true"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice id="s2" label="Read Only" readonly="true">
+      <tc:selectItem itemLabel="Item One" itemValue="one"/>
+      <tc:selectItem itemLabel="Item Two" itemValue="two"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice id="s3" label="Disabled" disabled="true">
+      <tc:selectItem itemLabel="Item One" itemValue="one"/>
+      <tc:selectItem itemLabel="Item Two" itemValue="two"/>
+    </tc:selectOneChoice>
+  </tc:section>
+
+  <tc:section label="Simple Usage">
+    <p>Select a person. The label of the item is shown in the dropdownbox.
+      After submitting, the value of the item is shown in the outputfield.
+      So, if 'Alice' is selected, the text in the outputfield is 'Alice Anderson'.</p>
+    <pre><code class="language-markup">&lt;tc:selectItem itemLabel="Alice" itemValue="Alice Anderson"/></code></pre>
+    <tc:selectOneChoice id="selectPerson" label="Person" value="#{selectOneChoiceController.person}">
+      <tc:selectItem itemLabel="Alice" itemValue="Alice Anderson"/>
+      <tc:selectItem itemLabel="Bob" itemValue="Bob Brunch"/>
+    </tc:selectOneChoice>
+    <tc:out id="outputPerson" label="Selected Person" value="#{selectOneChoiceController.person}"/>
+    <tc:button id="submit" label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>Select a planet and a moon. The list of moons depends on the selected planet.
+      The planet-dropdownbox contain a <code class="language-markup">&lt;f:ajax render="moonbox"/></code>.
+      With it, the moon-dropdownbox will be rerendered, after a value changed in planet-dropdownbox.</p>
+    <pre><code class="language-markup">&lt;tc:selectOneChoice label="Planet"
+      value="\#{selectOneChoiceController.planet}">
+  &lt;f:selectItems value="\#{selectOneChoiceController.planets}"/>
+  &lt;f:ajax render="moonbox"/>
+&lt;/tc:selectOneChoice>
+&lt;tc:selectOneChoice id="moonbox" label="Moon">
+  &lt;f:selectItems value="\#{selectOneChoiceController.moons}"/>
+&lt;/tc:selectOneChoice></code></pre>
+    <tc:selectOneChoice id="selectPlanet" label="Planet" value="#{selectOneChoiceController.planet}">
+      <f:selectItems value="#{selectOneChoiceController.planets}"/>
+      <f:ajax render="moonbox"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice id="moonbox" label="Moon">
+      <f:selectItems value="#{selectOneChoiceController.moons}"/>
+    </tc:selectOneChoice>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/selectOneRadio.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/selectOneRadio.test.js
new file mode 100644
index 0000000..d68d8d8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/selectOneRadio.test.js
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit: Addition (2 + 4)", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $number1 = jQueryFrame("#page\\:mainForm\\:selectNum1 input");
+  var $number2 = jQueryFrame("#page\\:mainForm\\:selectNum2 input");
+  var $submitAdd = jQueryFrame("#page\\:mainForm\\:submitAdd");
+
+  $number1.eq(0).prop("checked", false);
+  $number1.eq(1).prop("checked", true); // Select 2
+  $number1.eq(2).prop("checked", false);
+  $number2.eq(0).prop("checked", false);
+  $number2.eq(1).prop("checked", false);
+  $number2.eq(2).prop("checked", true); // Select 4
+  $submitAdd.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:resultOutput span");
+    assert.equal($output.text(), "6");
+    done();
+  });
+});
+
+QUnit.test("submit: Subtraction (4 - 1)", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $number1 = jQueryFrame("#page\\:mainForm\\:selectNum1 input");
+  var $number2 = jQueryFrame("#page\\:mainForm\\:selectNum2 input");
+  var $submitSub = jQueryFrame("#page\\:mainForm\\:submitSub");
+
+  $number1.eq(0).prop("checked", false);
+  $number1.eq(1).prop("checked", false);
+  $number1.eq(2).prop("checked", true); // Select 4
+  $number2.eq(0).prop("checked", true); // Select 1
+  $number2.eq(1).prop("checked", false);
+  $number2.eq(2).prop("checked", false);
+  $submitSub.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:resultOutput span");
+    assert.equal($output.text(), "3");
+    done();
+  });
+});
+
+QUnit.test("ajax: select Mars", function (assert) {
+  assert.expect(2);
+  var done = assert.async();
+  var $planet = jQueryFrame("#page\\:mainForm\\:selectPlanet input");
+  var $moons = jQueryFrame("#page\\:mainForm\\:moonradio li label");
+
+  $planet.eq(0).prop("checked", false);
+  $planet.eq(2).prop("checked", false);
+  $planet.eq(1).prop("checked", true).trigger("change"); // Mars.
+
+  waitForAjax(function () {
+    $moons = jQueryFrame($moons.selector);
+    return $moons.eq(0).text() == "Phobos"
+        && $moons.eq(1).text() == "Deimos";
+  }, function () {
+    $moons = jQueryFrame($moons.selector);
+    assert.equal($moons.eq(0).text(), "Phobos");
+    assert.equal($moons.eq(1).text(), "Deimos");
+    done();
+  });
+});
+
+QUnit.test("ajax: select Jupiter", function (assert) {
+  assert.expect(4);
+  var done = assert.async();
+  var $planet = jQueryFrame("#page\\:mainForm\\:selectPlanet input");
+  var $moons = jQueryFrame("#page\\:mainForm\\:moonradio li label");
+
+  $planet.eq(0).prop("checked", false);
+  $planet.eq(1).prop("checked", false);
+  $planet.eq(2).prop("checked", true).trigger("change"); // Jupiter.
+
+  waitForAjax(function () {
+    $moons = jQueryFrame($moons.selector);
+    return $moons.eq(0).text() == "Europa"
+        && $moons.eq(1).text() == "Ganymed"
+        && $moons.eq(2).text() == "Io"
+        && $moons.eq(3).text() == "Kallisto";
+  }, function () {
+    $moons = jQueryFrame($moons.selector);
+    assert.equal($moons.eq(0).text(), "Europa");
+    assert.equal($moons.eq(1).text(), "Ganymed");
+    assert.equal($moons.eq(2).text(), "Io");
+    assert.equal($moons.eq(3).text(), "Kallisto");
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/selectOneRadio.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/selectOneRadio.xhtml
new file mode 100644
index 0000000..3b8daee
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/30-selectOneRadio/selectOneRadio.xhtml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Select One Radio: &lt;tc:selectOneRadio>"/>
+  <p>A group of radiobuttons will be created with the <code class="language-markup">&lt;tc:selectOneRadio/></code> tag.
+    Static entries are added with <code class="language-markup">&lt;tc:selectItem/></code> tag.
+    A list from a controller is added with
+    <code class="language-markup">&lt;tc:selectItems value="\#{controller.list}"/></code>.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:selectOneRadio/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectOneRadio.html"/>
+    |
+    <tc:link label="&lt;tc:selectItem/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItem.html"/>
+    |
+    <tc:link label="&lt;tc:selectItems/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItems.html"/></p>
+
+  <tc:section label="Basics">
+    <p>Radiobutton group with a label. The last item is disabled.
+      Also the label set on top with the <code>labelLayout</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:selectOneRadio label="Radio Group" labelLayout="top"/></code></pre>
+    <tc:segmentLayout large="4;4;4">
+      <tc:selectOneRadio id="s1" label="Radio Group" labelLayout="top">
+        <tc:selectItem itemLabel="Sun" itemValue="solis"/>
+        <tc:selectItem itemLabel="Moon" itemValue="luna"/>
+        <tc:selectItem itemLabel="Stars" itemValue="stella" itemDisabled="true"/>
+      </tc:selectOneRadio>
+      <tc:selectOneRadio id="s2" label="Read Only" labelLayout="top" readonly="true">
+        <tc:selectItem itemLabel="Sun" itemValue="solis"/>
+        <tc:selectItem itemLabel="Moon" itemValue="luna"/>
+        <tc:selectItem itemLabel="Stars" itemValue="stella" itemDisabled="true"/>
+      </tc:selectOneRadio>
+      <tc:selectOneRadio id="s3" label="Disabled" labelLayout="top" disabled="true">
+        <tc:selectItem itemLabel="Sun" itemValue="solis"/>
+        <tc:selectItem itemLabel="Moon" itemValue="luna"/>
+        <tc:selectItem itemLabel="Stars" itemValue="stella" itemDisabled="true"/>
+      </tc:selectOneRadio>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="Inline">
+    <p>To display the radio buttons horizontally use the <code>inline="true"</code> attribute.</p>
+    <tc:selectOneRadio id="sInline" label="Radio Group" inline="true">
+      <tc:selectItem itemLabel="Sun" itemValue="solis"/>
+      <tc:selectItem itemLabel="Moon" itemValue="luna"/>
+      <tc:selectItem itemLabel="Stars" itemValue="stella"/>
+    </tc:selectOneRadio>
+  </tc:section>
+
+  <tc:section label="Simple Usage">
+    <p>Add number1 to number2 or subtract number2 from number1.</p>
+    <p>The radiobuttons are hardcoded with
+      <code class="language-markup">&lt;tc:selectItem itemLabel="1" itemValue="1"/></code>.
+      The buttons trigger an action in the controller:
+      <code class="language-markup">&lt;tc:button label="Addition" action="\#{selectOneRadioController.add}"/></code>
+    </p>
+    <tc:segmentLayout large="6;6">
+      <tc:selectOneRadio id="selectNum1" label="Number 1" labelLayout="top" required="true"
+                         value="#{selectOneRadioController.numberOne}">
+        <tc:selectItem itemLabel="1" itemValue="1"/>
+        <tc:selectItem itemLabel="2" itemValue="2"/>
+        <tc:selectItem itemLabel="4" itemValue="4"/>
+      </tc:selectOneRadio>
+      <tc:selectOneRadio id="selectNum2" label="Number 2" labelLayout="top" required="true"
+                         value="#{selectOneRadioController.numberTwo}">
+        <tc:selectItem itemLabel="1" itemValue="1"/>
+        <tc:selectItem itemLabel="2" itemValue="2"/>
+        <tc:selectItem itemLabel="4" itemValue="4"/>
+      </tc:selectOneRadio>
+    </tc:segmentLayout>
+    <tc:out id="resultOutput" label="Result" value="#{selectOneRadioController.result}"/>
+    <tc:flowLayout>
+      <tc:button id="submitAdd" label="Addition" action="#{selectOneRadioController.add}"/>
+      <tc:button id="submitSub" label="Subtraction" action="#{selectOneRadioController.subtract}"/>
+    </tc:flowLayout>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>Select a planet on the left. One the right side, you can select one of the moons.</p>
+    <p>The planets are added with
+      <code class="language-markup">&lt;f:selectItems value="\#{selectOneRadioController.planets}"/></code>.
+      The radiogroup of the planets also contain a
+      <code class="language-markup">&lt;f:ajax render="moonradio"></code> element,
+      which allows to rerender the radiogroup with the ID 'moonradio' every time, the value changed in the
+      planet-radiogroup.</p>
+    <tc:segmentLayout large="6;6">
+      <tc:selectOneRadio id="selectPlanet" label="Planet" labelLayout="top" value="#{selectOneRadioController.planet}">
+        <f:selectItems value="#{selectOneRadioController.planets}"/>
+        <f:ajax render="moonradio"/>
+      </tc:selectOneRadio>
+      <tc:selectOneRadio id="moonradio" label="Moon" labelLayout="top">
+        <f:selectItems value="#{selectOneRadioController.moons}"/>
+      </tc:selectOneRadio>
+    </tc:segmentLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/selectOneListbox.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/selectOneListbox.test.js
new file mode 100644
index 0000000..b3ddbfa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/selectOneListbox.test.js
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit: select 'Nile'", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $rivers = jQueryFrame("#page\\:mainForm\\:riverList option");
+  var $submit = jQueryFrame("#page\\:mainForm\\:riverSubmit");
+
+  $rivers.eq(0).prop("selected", true); // Nile
+  $rivers.eq(1).prop("selected", false); // Amazon
+  $rivers.eq(2).prop("selected", false); // Yangtze
+  $rivers.eq(3).prop("selected", false); // Yellow River
+  $rivers.eq(4).prop("selected", false); // Paraná River
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:riverOutput span");
+    assert.equal($output.text(), "6853 km");
+    done();
+  });
+});
+
+QUnit.test("submit: select 'Yangtze'", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $rivers = jQueryFrame("#page\\:mainForm\\:riverList option");
+  var $submit = jQueryFrame("#page\\:mainForm\\:riverSubmit");
+
+  $rivers.eq(0).prop("selected", false); // Nile
+  $rivers.eq(1).prop("selected", false); // Amazon
+  $rivers.eq(2).prop("selected", true); // Yangtze
+  $rivers.eq(3).prop("selected", false); // Yellow River
+  $rivers.eq(4).prop("selected", false); // Paraná River
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:riverOutput span");
+    assert.equal($output.text(), "6300 km");
+    done();
+  });
+});
+
+QUnit.test("ajax: select Everest", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $mountains = jQueryFrame("#page\\:mainForm\\:mountainList option");
+  var $output = jQueryFrame("#page\\:mainForm\\:selectedMountain span");
+
+  $mountains.eq(1).prop("selected", false);
+  $mountains.eq(2).prop("selected", false);
+  $mountains.eq(3).prop("selected", false);
+  $mountains.eq(4).prop("selected", false);
+  $mountains.eq(0).prop("selected", true).trigger("change"); // Everest
+
+  waitForAjax(function () {
+    $output = jQueryFrame($output.selector);
+    return $output.text() == "8848 m";
+  }, function () {
+    $output = jQueryFrame($output.selector);
+    assert.equal($output.text(), "8848 m");
+    done();
+  });
+});
+
+QUnit.test("ajax: select Makalu", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $mountains = jQueryFrame("#page\\:mainForm\\:mountainList option");
+  var $output = jQueryFrame("#page\\:mainForm\\:selectedMountain span");
+
+  $mountains.eq(0).prop("selected", false);
+  $mountains.eq(1).prop("selected", false);
+  $mountains.eq(2).prop("selected", false);
+  $mountains.eq(3).prop("selected", false);
+  $mountains.eq(4).prop("selected", true).trigger("change"); // Everest
+
+  waitForAjax(function () {
+    $output = jQueryFrame($output.selector);
+    return $output.text() == "8481 m";
+  }, function () {
+    $output = jQueryFrame($output.selector);
+    assert.equal($output.text(), "8481 m");
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/selectOneListbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/selectOneListbox.xhtml
new file mode 100644
index 0000000..dbadead
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/40-selectOneListbox/selectOneListbox.xhtml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.selectOneListbox} &lt;tc:selectOneListbox>"/>
+  <p>The <code class="language-markup">&lt;tc:selectOneListbox/></code> create a list of entries, where only one
+    entry can be selected. Items can be added with <code class="language-markup">&lt;tc:selectItem/></code>
+    or <code class="language-markup">&lt;tc:selectItems/></code>.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:selectOneListbox/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectOneListbox.html"/>
+    |
+    <tc:link label="&lt;tc:selectItem/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItem.html"/>
+    |
+    <tc:link label="&lt;tc:selectItems/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItems.html"/></p>
+
+  <tc:section label="Basics">
+    <p>If the number of rows is not set, die height of the list depends on the number of entries.
+      The number of rows can be set by the <code>size</code> attribute.
+      A list has at least two rows, therefor values
+      less than two have no effect.</p>
+    <pre><code class="language-markup">&lt;tc:selectOneListbox label="List" size="3">
+  &lt;tc:selectItem itemLabel="Alpha"/>
+  ...
+&lt;/tc:selectOneListbox></code></pre>
+    <tc:selectOneListbox id="s1" label="List" size="3">
+      <tc:selectItem itemLabel="Alpha"/>
+      <tc:selectItem itemLabel="Beta"/>
+      <tc:selectItem itemLabel="Gamma"/>
+      <tc:selectItem itemLabel="Delta"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox id="s2" label="Read Only" readonly="true" size="3">
+      <tc:selectItem itemLabel="Alpha"/>
+      <tc:selectItem itemLabel="Beta"/>
+      <tc:selectItem itemLabel="Gamma"/>
+      <tc:selectItem itemLabel="Delta"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox id="s3" label="Disabled" disabled="true" size="3">
+      <tc:selectItem itemLabel="Alpha"/>
+      <tc:selectItem itemLabel="Beta"/>
+      <tc:selectItem itemLabel="Gamma"/>
+      <tc:selectItem itemLabel="Delta"/>
+    </tc:selectOneListbox>
+  </tc:section>
+
+  <tc:section label="Simple Usage">
+    <p>Select a river in the list. After pressing the submit-button, the length of the river is shown in the
+      outputfield.</p>
+    <p>Items are added with
+      <code class="language-markup">&lt;tc:selectItem itemLabel="Nile" itemValue="6853 km"/></code>.</p>
+    <tc:selectOneListbox id="riverList" label="River" value="#{selectOneListboxController.river}">
+      <tc:selectItem itemLabel="Nile" itemValue="6853 km"/>
+      <tc:selectItem itemLabel="Amazon" itemValue="6437 km"/>
+      <tc:selectItem itemLabel="Yangtze" itemValue="6300 km"/>
+      <tc:selectItem itemLabel="Yellow River" itemValue="5464 km"/>
+      <tc:selectItem itemLabel="Paraná River" itemValue="4880 km"/>
+    </tc:selectOneListbox>
+    <tc:out id="riverOutput" label="Length" value="#{selectOneListboxController.river}"/>
+    <tc:button id="riverSubmit" label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>Select a mountain in the list. The height will be displayed by
+      <code class="language-markup">&lt;tc:out id="selectedMountain" .../></code>. The
+      <code class="language-markup">&lt;tc:selectOneListbox/></code> contain a
+      <code class="language-markup">&lt;f:ajax render="selectedMountain"/></code>, which rerender the outputfield.</p>
+    <tc:selectOneListbox id="mountainList" label="Mountains" value="#{selectOneListboxController.mountain}">
+      <tc:selectItems value="#{selectOneListboxController.mountains}" var="mountain"
+                      itemLabel="#{mountain.label}" itemValue="#{mountain.value}"/>
+      <f:ajax render="selectedMountain"/>
+    </tc:selectOneListbox>
+    <tc:out id="selectedMountain" label="Height" value="#{selectOneListboxController.mountain}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/selectManyCheckbox.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/selectManyCheckbox.test.js
new file mode 100644
index 0000000..1beaace
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/selectManyCheckbox.test.js
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit: select cat", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $animals = jQueryFrame("#page\\:mainForm\\:animals input");
+  var $submit = jQueryFrame("#page\\:mainForm\\:submit");
+
+  $animals.eq(0).prop("checked", true);
+  $animals.eq(1).prop("checked", false);
+  $animals.eq(2).prop("checked", false);
+  $animals.eq(3).prop("checked", false);
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:animalsOutput span");
+    assert.equal($output.text(), "Cat ");
+    done();
+  });
+});
+
+QUnit.test("submit: select fox and rabbit", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $animals = jQueryFrame("#page\\:mainForm\\:animals input");
+  var $submit = jQueryFrame("#page\\:mainForm\\:submit");
+
+  $animals.eq(0).prop("checked", false);
+  $animals.eq(1).prop("checked", false);
+  $animals.eq(2).prop("checked", true);
+  $animals.eq(3).prop("checked", true);
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    var $output = jQueryFrame("#page\\:mainForm\\:animalsOutput span");
+    assert.equal($output.text(), "Fox Rabbit ");
+    done();
+  });
+});
+
+QUnit.test("ajax: click 'Two'", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $number2 = jQueryFrame("#page\\:mainForm\\:numbers\\:\\:1");
+  var $output = jQueryFrame("#page\\:mainForm\\:resultOutput span");
+
+  var newOutputValue;
+
+  if ($number2.attr("checked") === "checked") {
+    $number2.prop("checked", false).trigger("change");
+    newOutputValue = parseInt($output.text()) - 2;
+  } else {
+    $number2.prop("checked", true).trigger("change");
+    newOutputValue = parseInt($output.text()) + 2;
+  }
+
+  waitForAjax(function () {
+    $output = jQueryFrame($output.selector);
+    return $output.text() == newOutputValue;
+  }, function () {
+    $output = jQueryFrame($output.selector);
+    assert.equal($output.text(), newOutputValue);
+    done();
+  });
+});
+
+QUnit.test("ajax: click 'Three'", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $number3 = jQueryFrame("#page\\:mainForm\\:numbers\\:\\:2");
+  var $output = jQueryFrame("#page\\:mainForm\\:resultOutput span");
+
+  var newOutputValue;
+
+  if ($number3.prop("checked")) {
+    $number3.prop("checked", false).trigger("change");
+    newOutputValue = parseInt($output.text()) - 3;
+  } else {
+    $number3.prop("checked", true).trigger("change");
+    newOutputValue = parseInt($output.text()) + 3;
+  }
+
+  waitForAjax(function () {
+    $output = jQueryFrame($output.selector);
+    return $output.text() == newOutputValue;
+  }, function () {
+    $output = jQueryFrame($output.selector);
+    assert.equal($output.text(), newOutputValue);
+    done();
+  });
+});
+
+QUnit.test("ajax: click 'Two'", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+  var $number2 = jQueryFrame("#page\\:mainForm\\:numbers\\:\\:1");
+  var $output = jQueryFrame("#page\\:mainForm\\:resultOutput span");
+
+  var newOutputValue;
+
+  if ($number2.prop("checked")) {
+    $number2.prop("checked", false).trigger("change");
+    newOutputValue = parseInt($output.text()) - 2;
+  } else {
+    $number2.prop("checked", true).trigger("change");
+    newOutputValue = parseInt($output.text()) + 2;
+  }
+
+  waitForAjax(function () {
+    $output = jQueryFrame($output.selector);
+    return $output.text() == newOutputValue;
+  }, function () {
+    $output = jQueryFrame($output.selector);
+    assert.equal($output.text(), newOutputValue);
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/selectManyCheckbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/selectManyCheckbox.xhtml
new file mode 100644
index 0000000..bd5bd19
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/50-selectManyCheckbox/selectManyCheckbox.xhtml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.selectManyCheckbox} &lt;tc:selectManyCheckbox>"/>
+  <p>With <code class="language-markup">&lt;tc:selectManyCheckbox/></code>, you can create a group of checkboxes.
+    The items are added via <code class="language-markup">&lt;tc:selectItem/></code> for static entries or
+    <code class="language-markup">&lt;tc:selectItems value="\#{controller.list}"/></code> for entries from a
+    controller.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:selectManyCheckbox/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectManyCheckbox.html"/>
+    |
+    <tc:link label="&lt;tc:selectItem/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItem.html"/>
+    |
+    <tc:link label="&lt;tc:selectItems/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItems.html"/></p>
+
+  <tc:section label="Basics">
+    <p>Checkbox Group with two items. The second one is disabled.</p>
+    <pre><code class="language-markup">&lt;tc:selectManyCheckbox label="Checkbox Group"></code></pre>
+    <tc:selectManyCheckbox label="Checkbox Group">
+      <tc:selectItem itemLabel="Item One" itemValue="one"/>
+      <tc:selectItem itemLabel="Item Two (disabled)" itemValue="two" itemDisabled="true"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox label="Read Only" readonly="true">
+      <tc:selectItem itemLabel="Item One" itemValue="one"/>
+      <tc:selectItem itemLabel="Item Two (disabled)" itemValue="two" itemDisabled="true"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox label="Disabled" disabled="true">
+      <tc:selectItem itemLabel="Item One" itemValue="one"/>
+      <tc:selectItem itemLabel="Item Two (disabled)" itemValue="two" itemDisabled="true"/>
+    </tc:selectManyCheckbox>
+  </tc:section>
+
+  <tc:section label="Inline">
+    <p>To display the radio buttons horizontally use the <code>inline="true"</code> attribute.</p>
+    <tc:selectManyCheckbox id="sInline" label="Checkbox Group" inline="true">
+      <tc:selectItem itemLabel="One" itemValue="one"/>
+      <tc:selectItem itemLabel="Two" itemValue="two"/>
+      <tc:selectItem itemLabel="Three" itemValue="three"/>
+    </tc:selectManyCheckbox>
+  </tc:section>
+
+  <tc:section label="Simple Usage">
+    <p>Select an animal. The selection is shown in the outputfield, after pressing 'Submit'.</p>
+    <p><code
+            class="language-markup">&lt;tc:selectManyCheckbox label="Checkbox Group" value="\#{selectManyCheckboxController.animals}"></code>
+      save the selected value in the controller.
+      The available items are added with <code class="language-markup">&lt;tc:selectItem .../></code>.
+      The
+      <code class="language-markup">&lt;tc:out ... value="\#{selectManyCheckboxController.animal}"/></code>
+      get the value from the controller.</p>
+    <tc:selectManyCheckbox id="animals" label="Checkbox Group" value="#{selectManyCheckboxController.animals}">
+      <tc:selectItem itemLabel="Cat" itemValue="Cat"/>
+      <tc:selectItem itemLabel="Dog" itemValue="Dog"/>
+      <tc:selectItem itemLabel="Fox" itemValue="Fox"/>
+      <tc:selectItem itemLabel="Rabbit" itemValue="Rabbit"/>
+    </tc:selectManyCheckbox>
+    <tc:out id="animalsOutput" label="Selected Animals" value="#{selectManyCheckboxController.animal}"/>
+    <tc:button id="submit" label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>Select a number. Those numbers are added and displayed in the
+      <code class="language-markup">&lt;tc:out id="resultOutput" .../></code>.
+      <code class="language-markup">&lt;tc:selectManyCheckbox .../></code> contain a
+      <code class="language-markup">&lt;f:ajax render="resultOutput"/></code>, which rerenders the outputfield after
+      check/uncheck a checkbox.</p>
+    <tc:selectManyCheckbox id="numbers" label="Checkbox Group" value="#{selectManyCheckboxController.numbers}">
+      <tc:selectItem itemLabel="One" itemValue="1"/>
+      <tc:selectItem itemLabel="Two" itemValue="2"/>
+      <tc:selectItem itemLabel="Three" itemValue="3"/>
+      <tc:selectItem itemLabel="Four" itemValue="4"/>
+      <f:ajax render="resultOutput"/>
+    </tc:selectManyCheckbox>
+    <tc:out id="resultOutput" label="Selected Animals" value="#{selectManyCheckboxController.result}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/60-selectManyListbox/selectManyListbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/60-selectManyListbox/selectManyListbox.xhtml
new file mode 100644
index 0000000..033dc4a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/60-selectManyListbox/selectManyListbox.xhtml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.selectManyListbox} &lt;tc:selectManyListbox>"/>
+  <p>The <code class="language-markup">&lt;tc:selectManyListbox/></code> create a list,
+    where more than one entry could be selected. Entries are added with
+    <code class="language-markup">&lt;tc:selectItem/></code> (static) or
+    <code class="language-markup">&lt;tc:selectItems value="\#{controller.list}"/></code> (from controller).</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:selectManyListbox/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectManyListbox.html"/>
+    |
+    <tc:link label="&lt;tc:selectItem/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItem.html"/>
+    |
+    <tc:link label="&lt;tc:selectItems/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItems.html"/></p>
+
+  <tc:section label="Basics">
+    <p>In this example, there is a list with three items. The second one is disabled with the
+      <code>itemDisabled</code> attribute of the <code class="language-markup"><tc:selectItem/></code> tag.</p>
+    <tc:selectManyListbox id="s1" label="List">
+      <tc:selectItem itemLabel="Item1" itemValue="item1"/>
+      <tc:selectItem itemLabel="Item2 (disabled)" itemValue="item2" itemDisabled="true"/>
+      <tc:selectItem itemLabel="Item3" itemValue="item3"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox id="s2" label="Read Only" readonly="true">
+      <tc:selectItem itemLabel="Item1" itemValue="item1"/>
+      <tc:selectItem itemLabel="Item2 (disabled)" itemValue="item2" itemDisabled="true"/>
+      <tc:selectItem itemLabel="Item3" itemValue="item3"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox id="s3" label="Disabled" disabled="true">
+      <tc:selectItem itemLabel="Item1" itemValue="item1"/>
+      <tc:selectItem itemLabel="Item2 (disabled)" itemValue="item2" itemDisabled="true"/>
+      <tc:selectItem itemLabel="Item3" itemValue="item3"/>
+    </tc:selectManyListbox>
+  </tc:section>
+
+  <tc:section label="Simple Usage">
+    <p>Select an entry and press the submit-button. The text in the outputfield depends on the selection.</p>
+    <pre><code class="language-markup">&lt;tc:selectManyListbox label="List" value="\#{selectManyListboxController.celestials}">
+  &lt;tc:selectItem itemLabel="Sun" itemValue="The sun, "/>
+  ...
+&lt;/tc:selectManyListbox>
+&lt;tc:out label="Selection" value="\#{selectManyListboxController.celestial}"/></code></pre>
+    <tc:selectManyListbox id="s4" label="List" value="#{selectManyListboxController.celestials}">
+      <tc:selectItem itemLabel="Sun" itemValue="The sun, "/>
+      <tc:selectItem itemLabel="Moon" itemValue="the moon, "/>
+      <tc:selectItem itemLabel="Stars" itemValue="the stars..."/>
+    </tc:selectManyListbox>
+    <tc:out id="o1" label="Selection" value="#{selectManyListboxController.celestial}"/>
+    <tc:button id="b1" label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Ajax" id="ajax">
+    <p>The selected deserts from the list, are shown in the
+      <code class="language-markup">&lt;tc:out id="desertOutput" .../></code>.
+      The value in the outputfield will be rerendered, after the selection in the list changed. For that,
+      <code class="language-markup">&lt;tc:selectManyListbox label="Deserts" size="4" ...></code> contain a
+      <code class="language-markup">&lt;f:ajax render="desertOutput"/></code> tag.</p>
+    <p>The number of rows is set to four by the <code>size</code> attribute. Is no size set, the height of the list
+      depends of the number of rows. The list shows at least two rows. Values lower than two have no effect.</p>
+    <tc:selectManyListbox id="s5" label="Deserts" size="4" value="#{selectManyListboxController.selectedDeserts}">
+      <f:selectItems value="#{selectManyListboxController.deserts}"/>
+      <f:ajax render="desertOutput"/>
+    </tc:selectManyListbox>
+    <tc:out id="desertOutput" label="Selected Desets" value="#{selectManyListboxController.selectedDeserts}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/70-selectManyShuttle/selectManyShuttle.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/70-selectManyShuttle/selectManyShuttle.xhtml
new file mode 100644
index 0000000..cb46a6d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/70-selectManyShuttle/selectManyShuttle.xhtml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.selectManyShuttle} &lt;tc:selectManyShuttle>"/>
+  <p>The shuttlelist component can be created with <code class="language-markup">&lt;tc:selectManyShuttle/></code>.
+    In general, the height of the list depends on the number of items and is set to an amount, where no
+    scrollbar is needed. You can set the number of rows with the <code>size</code> attribute. The shuttle list
+    has at least seven rows, values less than seven have no effect.
+    Items are added via <code class="language-markup">&lt;tc:selectItem></code> (static) or
+    <code class="language-markup">&lt;tc:selectItems></code> (dynamic).</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:selectManyShuttle/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectManyShuttle.html"/>
+    |
+    <tc:link label="&lt;tc:selectItem/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItem.html"/>
+    |
+    <tc:link label="&lt;tc:selectItems/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/selectItems.html"/></p>
+
+  <tc:section label="Basics">
+    <pre><code class="language-markup">&lt;tc:selectManyShuttle label="Shuttle List" size="7"></code></pre>
+    <tc:selectManyShuttle id="s1" label="Shuttle List" size="7">
+      <tc:selectItem itemLabel="Item1"/>
+      <tc:selectItem itemLabel="Item2"/>
+      <tc:selectItem itemLabel="Item3"/>
+      <tc:selectItem itemLabel="Item4"/>
+      <tc:selectItem itemLabel="Item5"/>
+      <tc:selectItem itemLabel="Item6"/>
+      <tc:selectItem itemLabel="Item7"/>
+      <tc:selectItem itemLabel="Item8"/>
+      <tc:selectItem itemLabel="Item9"/>
+      <tc:selectItem itemLabel="Item10"/>
+      <tc:selectItem itemLabel="Item11"/>
+      <tc:selectItem itemLabel="Item12"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle id="s2" label="Read Only" readonly="true" size="7">
+      <tc:selectItem itemLabel="Item1"/>
+      <tc:selectItem itemLabel="Item2"/>
+      <tc:selectItem itemLabel="Item3"/>
+      <tc:selectItem itemLabel="Item4"/>
+      <tc:selectItem itemLabel="Item5"/>
+      <tc:selectItem itemLabel="Item6"/>
+      <tc:selectItem itemLabel="Item7"/>
+      <tc:selectItem itemLabel="Item8"/>
+      <tc:selectItem itemLabel="Item9"/>
+      <tc:selectItem itemLabel="Item10"/>
+      <tc:selectItem itemLabel="Item11"/>
+      <tc:selectItem itemLabel="Item12"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle id="s3" label="Disabled" disabled="true" size="7">
+      <tc:selectItem itemLabel="Item1"/>
+      <tc:selectItem itemLabel="Item2"/>
+      <tc:selectItem itemLabel="Item3"/>
+      <tc:selectItem itemLabel="Item4"/>
+      <tc:selectItem itemLabel="Item5"/>
+      <tc:selectItem itemLabel="Item6"/>
+      <tc:selectItem itemLabel="Item7"/>
+      <tc:selectItem itemLabel="Item8"/>
+      <tc:selectItem itemLabel="Item9"/>
+      <tc:selectItem itemLabel="Item10"/>
+      <tc:selectItem itemLabel="Item11"/>
+      <tc:selectItem itemLabel="Item12"/>
+    </tc:selectManyShuttle>
+  </tc:section>
+
+  <tc:section label="Simple Usage">
+    <p>After a submit, the entries in the right list are shown in the outputfield with name and distance from the
+      sun.</p>
+    <p>A label is added to the left list via the <code>unselectedLabel</code> attribute and to the right list
+      via <code>selectedLabel</code>. The label for the whole component is set on top by
+      <code>labelLayout="top"</code>.</p>
+    <p>In this example, the entries are added by
+      <code class="language-markup">&lt;tc:selectItems ... var="planet" itemLabel="\#{planet.name}" itemValue="\#{planet}"/></code>.
+      The name of a variable is defined by<code>var</code>. In this case, the <code>itemLabel</code> get the name of
+      the planet, while the <code>itemValue</code> is object itself.</p>
+    <pre><code class="language-markup">&lt;tc:selectManyShuttle label="Planets" ...>
+  &lt;tc:selectItems value="\#{selectManyShuttleController.planets}" .../>
+&lt;/tc:selectManyShuttle></code></pre>
+    <tc:selectManyShuttle id="s4" label="Planets" labelLayout="top"
+                          unselectedLabel="Left List" selectedLabel="Right List"
+                          value="#{selectManyShuttleController.selectedPlanets}">
+      <tc:selectItems value="#{selectManyShuttleController.planets}"
+                      var="planet" itemLabel="#{planet.name}" itemValue="#{planet}"/>
+    </tc:selectManyShuttle>
+    <tc:out id="o1" label="Selected Planets" value="#{selectManyShuttleController.selectedPlanetsAsString}"/>
+    <tc:button label="Submit"/>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>The entries in the right list are shown in
+      <code class="language-markup">&lt;tc:out id="outputStars" .../></code>.
+      <code class="language-markup">&lt;tc:selectManyShuttle .../></code> contain
+      <code class="language-markup">&lt;f:ajax render="outputStars"/></code>. Every time, the value in the shuttle list
+      change, the outputfield is rerendered.</p>
+    <tc:selectManyShuttle id="s5" label="Stars" labelLayout="top" value="#{selectManyShuttleController.selectedStars}">
+      <tc:selectItems value="#{selectManyShuttleController.stars}"/>
+      <f:ajax render="outputStars"/>
+    </tc:selectManyShuttle>
+    <tc:out id="outputStars" label="Selected Stars" value="#{selectManyShuttleController.selectedStarsAsString}"/>
+  </tc:section>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/select.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/select.xhtml
new file mode 100644
index 0000000..5d96395
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/030-select/select.xhtml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.select}"/>
+  <p>Tobago provides several ways to select an option.
+    Entries are added with <code class="language-markup">&lt;tc:selectItem/></code> or
+    <code class="language-markup">&lt;tc:selectItems value="\#{controller.list}"/></code>
+    for most select components.</p>
+
+  <tc:section label="#{demoBundle.selectBooleanCheckbox}">
+    <pre><code class="language-markup">&lt;tc:selectBooleanCheckbox label="Checkbox"/></code></pre>
+    <tc:selectBooleanCheckbox label="Checkbox" itemLabel="OK?"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.selectOneChoice}">
+    <pre><code class="language-markup">&lt;tc:selectOneChoice label="Dropdown Box"></code></pre>
+    <tc:selectOneChoice label="Dropdown Box">
+      <tc:selectItems value="#{selectController.entries}"/>
+    </tc:selectOneChoice>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.selectOneRadio}">
+    <pre><code class="language-markup">&lt;tc:selectOneRadio label="Radio Group" labelLayout="top"></code></pre>
+    <tc:selectOneRadio id="radio" label="Radio Group" labelLayout="top">
+      <tc:selectItem itemLabel="Option One"/>
+      <tc:selectItem itemLabel="Option Two"/>
+    </tc:selectOneRadio>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.selectOneListbox}">
+    <pre><code class="language-markup">&lt;tc:selectOneListbox label="Listbox" size="3"></code></pre>
+    <tc:selectOneListbox label="Listbox" size="3">
+      <tc:selectItems value="#{selectController.entries}"/>
+    </tc:selectOneListbox>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.selectManyCheckbox}">
+    <pre><code class="language-markup">&lt;tc:selectManyCheckbox label="Checkbox Group" labelLayout="top"></code></pre>
+    <tc:selectManyCheckbox label="Checkbox Group" labelLayout="top">
+      <tc:selectItem itemLabel="Checkbox One"/>
+      <tc:selectItem itemLabel="Checkbox Two"/>
+    </tc:selectManyCheckbox>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.selectManyListbox}">
+    <pre><code class="language-markup">&lt;tc:selectManyListbox label="List" size="3"></code></pre>
+    <tc:selectManyListbox label="List" size="3">
+      <tc:selectItems value="#{selectController.entries}"/>
+    </tc:selectManyListbox>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.selectManyShuttle}">
+    <pre><code class="language-markup">&lt;tc:selectManyShuttle label="Shuttle List" size="7"></code></pre>
+    <tc:selectManyShuttle label="Shuttle List" size="7">
+      <tc:selectItems value="#{selectController.entries}"/>
+    </tc:selectManyShuttle>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/button+link.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/button+link.xhtml
new file mode 100644
index 0000000..f0de902
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/button+link.xhtml
@@ -0,0 +1,154 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.button_link} &lt;tc:link> &lt;tc:button>"/>
+  <p>A classic link can be set with the <code class="language-markup">&lt;tc:link/></code> tag.
+    You can also set a link by <code class="language-markup">&lt;tc:button/></code>.
+    The behavior of a link and a button is the same, it differs in the appearance.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:link/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/link.html"/>
+    |
+    <tc:link label="&lt;tc:button/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/button.html"/></p>
+
+  <tc:section label="Basics">
+    <p>The next two sections show how a link and a button is set.</p>
+    <p>'apache.org' leads to the appropriated website.<br/>
+      'Disable' show a disabled link/button.<br/>
+      'Action' use the <code>action</code> attribute to link the #{demoBundle.component} section.<br/>
+      The image leads to www.apache.org.</p>
+    <tc:section label="&lt;tc:link>">
+      <pre><code class="language-markup">&lt;tc:link label="apache.org" link="https://www.apache.org/"/></code></pre>
+      <tc:link id="l1" label="apache.org" link="https://www.apache.org/"/>
+      |
+      <tc:link id="l2" label="Disabled" disabled="true" link="https://www.apache.org/"/>
+      |
+      <tc:link id="l4" label="Action" action="#{buttonLinkController.linkToComponentsRoot}"/>
+      |
+      <tc:link id="l5" label="Link with an image" image="#{request.contextPath}/image/feather-leaf.png" link="https://www.apache.org/"/>
+    </tc:section>
+    <tc:section label="&lt;tc:button>">
+      <pre><code class="language-markup">&lt;tc:button label="apache.org" link="https://www.apache.org/"/></code></pre>
+      <tc:button id="b1" label="apache.org" link="https://www.apache.org/"/>
+      <tc:button id="b2" label="Disabled" disabled="true" link="https://www.apache.org/"/>
+      <tc:button id="b4" label="Action" action="#{buttonLinkController.linkToComponentsRoot}"/>
+      <tc:button id="b5" image="#{request.contextPath}/image/feather-leaf.png" link="https://www.apache.org/"/>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Dropdown">
+    <p>Links and buttons can also be dropdown elements.
+      You can just put a link tag in another link or button tag
+      and set the <code>omit</code> attribute for the parent.</p>
+
+    <tc:section label="Dropdown Link">
+      <pre><code class="language-markup">&lt;tc:link label="MusicPlayer" omit="true">
+  &lt;tc:link image="fa-play-circle" label="Play"/>
+  ...
+&lt;/tc:link></code></pre>
+      <tc:link label="MusicPlayer" omit="true">
+        <tc:link image="fa-play-circle" label="Play"/>
+        <tc:link image="fa-pause-circle" label="Pause"/>
+        <tc:link image="fa-stop-circle" label="Stop"/>
+        <tc:link label="Track">
+          <tc:link label="1"/>
+          <tc:link label="2"/>
+          <tc:link label="3"/>
+        </tc:link>
+      </tc:link>
+    </tc:section>
+
+    <tc:section label="Dropdown Button">
+      <pre><code class="language-markup">&lt;tc:button label="MusicPlayer" omit="true">
+  &lt;tc:link image="fa-play-circle" label="Play"/>
+  ...
+&lt;/tc:button></code></pre>
+      <tc:button label="MusicPlayer" omit="true">
+        <tc:link image="fa-play-circle" label="Play"/>
+        <tc:link image="fa-pause-circle" label="Pause"/>
+        <tc:link image="fa-stop-circle" label="Stop"/>
+        <tc:link label="Track">
+          <tc:link label="1"/>
+          <tc:link label="2"/>
+          <tc:link label="3"/>
+        </tc:link>
+      </tc:button>
+    </tc:section>
+
+    <tc:section label="Dropdown with Radio Buttons">
+      <pre><code class="language-markup">&lt;tc:button label="Options" omit="true">
+  &lt;tc:selectOneRadio>
+    &lt;tc:selectItem itemValue="Option 1"/>
+    ...
+  &lt;/tc:selectOneRadio>
+&lt;/tc:button></code></pre>
+      <tc:button label="Options" omit="true">
+        <tc:selectOneRadio>
+          <tc:selectItem itemValue="Option 1"/>
+          <tc:selectItem itemValue="Option 2"/>
+          <tc:selectItem itemValue="Option 3"/>
+        </tc:selectOneRadio>
+      </tc:button>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Confirmation">
+    <p>A confirmation dialog can be added to a link or a button via
+      <code class="language-markup">&lt;f:facet name="confirmation"></code>.
+      The messagetext is added with <code class="language-markup">&lt;tc:out/></code>.</p>
+    <tc:link id="l6" label="apache.org" link="https://www.apache.org/" confirmation="Are you sure?"/>
+    <tc:button id="b6" label="apache.org" link="https://www.apache.org/">
+      <f:facet name="confirmation">
+        <tc:out value="Are you sure?"/>
+      </f:facet>
+    </tc:button>
+    <tc:link id="l7" label="Action" confirmation="Are you sure?"/>
+    <tc:button id="b7" label="Action">
+      <f:facet name="confirmation">
+        <tc:out value="Are you sure?"/>
+      </f:facet>
+    </tc:button>
+  </tc:section>
+
+  <tc:section label="Target">
+    <p>The destination of the link can be set with the <code>target</code> attribute.
+      For example a new window/tab or a specific iframe (<code class="language-markup">&lt;tc:object/></code>).</p>
+    <tc:section label="New Window">
+      <pre><code
+              class="language-markup">&lt;tc:link label="open https://www.apache.org/ in new window"
+        link="https://www.apache.org/" target="_blank"/></code></pre>
+      <p><tc:link label="open https://www.apache.org/ in new window" link="https://www.apache.org/" target="_blank"/>
+      </p>
+    </tc:section>
+    <tc:section label="IFrame">
+      <p>The iframe is set with <code class="language-markup">&lt;tc:object name="objectframe" .../></code>
+        (see <tc:link label="#{demoBundle.object}"
+                      link="/faces/content/20-component/020-output/60-object/object.xhtml"/>).
+        The value of the <code>target</code> attribute is in this case 'objectframe'.</p>
+      <p><tc:link label="apache.org" link="https://www.apache.org/" target="objectframe"/>
+        |
+        <tc:link label="myfaces.apache.org/tobago" link="https://myfaces.apache.org/tobago/" target="objectframe"/></p>
+      <tc:object id="o1" name="objectframe" src="https://www.apache.org/">
+        <tc:style width="100%" height="500px"/>
+      </tc:object>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/sample.html b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/sample.html
new file mode 100644
index 0000000..8b19066
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/sample.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html>
+<body>
+Sample HTML page (default locale).
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/sample_de.html b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/sample_de.html
new file mode 100644
index 0000000..32e0839
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/00-button+link/sample_de.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html>
+<body>
+Beispiel HTML Seite (deutsch).
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/10-default/default-command.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/10-default/default-command.xhtml
new file mode 100644
index 0000000..177bb5b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/10-default/default-command.xhtml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.default_command} &lt;tc:button>"/>
+  <p>A normal button, created with <code class="language-markup">&lt;tc:button/></code>, must be actively pressed,
+    to run the action. A default-button can be activated, even if not selected.
+    For example, the cursor is in an inputfield and the enter key is pressed.</p>
+  <p>A button can be made to a default button with the <code>defaultCommand</code> attribute.
+    The default button is highlighted by another color.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/button.html"/>
+
+  <tc:section label="Last Active Button ID">
+    <p>To make the examples more clear, the ID of the last active button is displayed in the
+      following outputfield.</p>
+    <tc:out id="o1" label="Id" value="#{defaultCommandController.lastActiveButtonId}"/>
+  </tc:section>
+
+  <tc:section label="Basics">
+    <p>After writing some text into the textfield, the user can press 'ENTER' to activate the submit-button.</p>
+    <tc:form>
+      <tc:in id="i1" label="Textfield" placeholder="add some text..." value="#{defaultCommandController.value1}"/>
+      <tc:out id="o2" label="Value Textfield" value="#{defaultCommandController.value1}"/>
+      <tc:button id="submit1" label="Submit 1" defaultCommand="true"
+                 actionListener="#{defaultCommandController.click}"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Multiple Default Buttons">
+    <p>The related default-button is searched in the current <code class="language-markup">&lt;tc:form/></code>.
+      If there no default-button could found, the search is continued in the parent form and so on.
+      If no default-button found on this way, the button is search outside of a form.</p>
+    <p>In this example, the 'Submit A'-button is in a form together with a intputfield and outputfield.
+      The 'Submit B'-button is outside a form.</p>
+    <p>Now, if the cursor is in 'Textfield A' and the enter key is pressed, the 'Submit A'-button is activated.
+      Therefor only the 'Textfield A'-value will be submitted.</p>
+    <p>If the cursor is in 'Textfield B' and the enter key is pressed, the 'Submit B'-button is activated.
+      This will submit the 'Textfield A'-value as well as the 'Textfield B'-value.</p>
+    <tc:form>
+      <tc:box>
+        <tc:form>
+          <tc:in id="i2" label="Textfield A" placeholder="add some text..." value="#{defaultCommandController.value2}"/>
+          <tc:out id="o3" label="Value Textfield A" value="#{defaultCommandController.value2}"/>
+          <tc:button id="submitA" label="Submit A" defaultCommand="true"
+                     actionListener="#{defaultCommandController.click}"/>
+        </tc:form>
+      </tc:box>
+      <tc:box>
+        <tc:form>
+          <tc:in id="i3" label="Textfield B" placeholder="add some text..." value="#{defaultCommandController.value3}"/>
+          <tc:out id="o4" label="Value Textfield B" value="#{defaultCommandController.value3}"/>
+        </tc:form>
+      </tc:box>
+      <tc:button id="submitB" label="Submit B" defaultCommand="true"
+                 actionListener="#{defaultCommandController.click}"/>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/20-buttons/buttons.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/20-buttons/buttons.xhtml
new file mode 100644
index 0000000..87c9f26
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/20-buttons/buttons.xhtml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.buttons}  &lt;tc:buttons>"/>
+  <p>Buttons can be grouped with the <code class="language-markup">&lt;tc:buttons/></code> tag.
+    Just add some <code class="language-markup">&lt;tc:button/></code> tags.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:buttons/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/buttons.html"/>
+    |
+    <tc:link label="&lt;tc:button/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/button.html"/></p>
+
+  <tc:section label="Basics">
+    <p>A simple example with three buttons.</p>
+    <pre><code class="language-markup">&lt;tc:buttons>
+  &lt;tc:button label="Left"/>
+  &lt;tc:button label="Center"/>
+  &lt;tc:button label="Right"/>
+&lt;/tc:buttons></code></pre>
+    <tc:buttons>
+      <tc:button label="Left"/>
+      <tc:button label="Center"/>
+      <tc:button label="Right"/>
+    </tc:buttons>
+  </tc:section>
+
+  <tc:section label="Default Button">
+    <p>It is also possible to set a default button.</p>
+    <pre><code class="language-markup">&lt;tc:buttons>
+  &lt;tc:button label="Left" defaultCommand="true"/>
+  &lt;tc:button label="Center"/>
+  &lt;tc:button label="Default"/>
+&lt;/tc:buttons></code></pre>
+    <tc:buttons>
+      <tc:button label="Left" defaultCommand="true"/>
+      <tc:button label="Center"/>
+      <tc:button label="Default"/>
+    </tc:buttons>
+  </tc:section>
+
+  <tc:section label="Dropdown Button">
+    <p>A dropdown button can also be placed in a <code class="language-markup">&lt;tc:buttons/></code> tag.</p>
+    <pre><code class="language-markup">&lt;tc:buttons>
+  &lt;tc:button label="Dropdown" omit="true">
+    &lt;tc:link label="Action 1"/>
+    ...
+  &lt;/tc:button>
+  &lt;tc:button label="Center"/>
+  &lt;tc:button label="Right"/>
+&lt;/tc:buttons></code></pre>
+    <tc:buttons>
+      <tc:button label="Dropdown" omit="true">
+        <tc:link label="Action 1"/>
+        <tc:link label="Action 2"/>
+        <tc:link label="Action 3">
+          <tc:link label="Action 3.1"/>
+          <tc:link label="Action 3.2"/>
+        </tc:link>
+      </tc:button>
+      <tc:button label="Center"/>
+      <tc:button label="Right"/>
+    </tc:buttons>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/buttons-customizer.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/buttons-customizer.xhtml
new file mode 100644
index 0000000..cc157ab
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/buttons-customizer.xhtml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition
+        template="/main.xhtml"
+        xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:ui="http://java.sun.com/jsf/facelets"
+        xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:c="http://java.sun.com/jsp/jstl/core">
+  <ui:param name="title" value="#{demoBundle.buttons_customizer}  &lt;tc:buttons>"/>
+  <p>The data of the model can also be loaded directly from the webapp directory.
+    So we can define an item for each facelet matching buttons-item-*.xhtml.
+    With this, we can create applications with pluggable UI. And we don't have to fight with bindings and
+    creating components in Java code.</p>
+
+  <tc:section label="Customizable Button Group">
+    <p>This example shows a flexible possiblility, but for most cases there are much simpler solutions.</p>
+
+    <tc:buttons id="buttons">
+      <c:forEach items="#{customizer.list}" var="item">
+        <c:if test="#{item.visible}">
+          <ui:include src="#{item.name}"/>
+        </c:if>
+      </c:forEach>
+    </tc:buttons>
+
+    <tc:sheet var="item" value="#{customizer.list}" columns="*;*;*;*" id="sheet">
+      <tc:column label="Item Name">
+        <tc:out value="#{item.label}"/>
+      </tc:column>
+      <tc:column label="Visible">
+        <tc:selectBooleanCheckbox value="#{item.visible}">
+          <f:ajax render=":::buttons :::sheet"/>
+        </tc:selectBooleanCheckbox>
+      </tc:column>
+      <tc:column>
+        <tc:link actionListener="#{customizer.itemUp}" label="Up">
+          <f:param value="#{item}" name="item"/>
+          <f:ajax render=":::buttons :::sheet"/>
+        </tc:link>
+      </tc:column>
+      <tc:column>
+        <tc:link actionListener="#{customizer.itemDown}" label="Down">
+          <f:param value="#{item}" name="item"/>
+          <f:ajax render=":::buttons :::sheet"/>
+        </tc:link>
+      </tc:column>
+    </tc:sheet>
+
+    <tc:button label="Reset List" action="#{customizer.resetList}" image="fa-refresh"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-delete.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-delete.xhtml
new file mode 100644
index 0000000..1b14bf0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-delete.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tc:button xmlns:tc="http://myfaces.apache.org/tobago/component" label="Delete" image="fa-remove"/>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-edit.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-edit.xhtml
new file mode 100644
index 0000000..44666ac
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-edit.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tc:button xmlns:tc="http://myfaces.apache.org/tobago/component" label="Edit" image="fa-edit"/>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-new.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-new.xhtml
new file mode 100644
index 0000000..673a75a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/21-buttons-customizer/x-buttons-item-new.xhtml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tc:button xmlns:tc="http://myfaces.apache.org/tobago/component" label="New" image="fa-plus"/>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/25-links/links.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/25-links/links.xhtml
new file mode 100644
index 0000000..4b0bf4f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/25-links/links.xhtml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.links}  &lt;tc:links>"/>
+  <p>Links can be grouped with the <code class="language-markup">&lt;tc:links/></code> tag.
+    Just add some <code class="language-markup">&lt;tc:link/></code> or
+    <code class="language-markup">&lt;tc:links/></code> tags.</p>
+  <p>Currently there is no difference between <code class="language-markup">&lt;tc:link/></code> and
+    <code class="language-markup">&lt;tc:links/></code>.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/buttons.html"/>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:links/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/links.html"/>
+    |
+    <tc:link label="&lt;tc:link/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/link.html"/></p>
+
+  <tc:section label="Basics">
+    <p>A simple example with three links.</p>
+    <pre><code class="language-markup">&lt;tc:links>
+  &lt;tc:link label="Left"/>
+  &lt;tc:link label="Center"/>
+  &lt;tc:link label="Right"/>
+&lt;/tc:links></code></pre>
+    <tc:links>
+      <tc:link label="Left"/>
+      <tc:link label="Center"/>
+      <tc:link label="Right"/>
+    </tc:links>
+  </tc:section>
+
+  <tc:section label="Dropdown Button">
+    <p>A dropdown menu can also be created.</p>
+    <pre><code class="language-markup">&lt;tc:links>
+  &lt;tc:link label="Dropdown" omit="true">
+    &lt;tc:link label="Action 1"/>
+    ...
+  &lt;/tc:link>
+  &lt;tc:link label="Center"/>
+  &lt;tc:link label="Right"/>
+&lt;/tc:links></code></pre>
+    <tc:links>
+      <tc:link label="Dropdown" omit="true">
+        <tc:link label="Action 1"/>
+        <tc:link label="Action 2"/>
+        <tc:link label="Action 3"/>
+        <tc:link label="Submenu">
+          <tc:link label="Action 1"/>
+          <tc:link label="Action 2"/>
+          <tc:link label="Action 3"/>
+        </tc:link>
+      </tc:link>
+      <tc:link label="Center"/>
+      <tc:link label="Right"/>
+    </tc:links>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/command.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/command.xhtml
new file mode 100644
index 0000000..b7633a1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/040-command/command.xhtml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.command}"/>
+  <p>Commands are ways to execute actions after clicked by a user.</p>
+
+  <tc:section label="Link">
+    <pre><code class="language-markup">&lt;tc:link label="Apache Website" link="https://www.apache.org"/></code></pre>
+    <tc:link label="Apache Website" link="https://www.apache.org"/>
+  </tc:section>
+
+  <tc:section label="Button">
+    <pre><code class="language-markup">&lt;tc:button label="Submit"/></code></pre>
+    <tc:button label="Submit"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.buttons}">
+    <pre><code class="language-markup">&lt;tc:buttons>
+  &lt;tc:button label="Left" omit="true"/>
+  &lt;tc:button label="Center" omit="true"/>
+  &lt;tc:button label="Right" omit="true"/>
+&lt;/tc:buttons></code></pre>
+    <tc:buttons>
+      <tc:button label="Left" omit="true"/>
+      <tc:button label="Center" omit="true"/>
+      <tc:button label="Right" omit="true"/>
+    </tc:buttons>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.links}">
+    <pre><code class="language-markup">&lt;tc:links>
+  &lt;tc:link label="Apache Website" link="https://www.apache.org"/>
+  &lt;tc:link label="Wikipedia" link="https://en.wikipedia.org/wiki/Apache_Software_Foundation"/>
+&lt;/tc:links></code></pre>
+    <tc:links>
+      <tc:link label="Apache Website" link="https://www.apache.org"/>
+      <tc:link label="Wikipedia" link="https://en.wikipedia.org/wiki/Apache_Software_Foundation"/>
+    </tc:links>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/10-box/box.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/10-box/box.xhtml
new file mode 100644
index 0000000..5600f0a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/10-box/box.xhtml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.box} &lt;tc:box>"/>
+  <p>A content box is created with <code class="language-markup">&lt;tc:box/></code>.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/box.html"/>
+  <tc:section label="Basics">
+    <p>The title of the box is set by the <code>label</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:box label="Box">Content&lt;/tc:box></code></pre>
+    <tc:box id="b1" label="Box">Content</tc:box>
+    <tc:box>Contentbox without a title.</tc:box>
+  </tc:section>
+
+  <tc:section label="Collapse/Expand">
+    <p>A contentbox can be collapsed or expanded via the <code>collapsed</code> attribute.
+      To define the behavior of hidden content, use the <code>collapseMode</code> attribute.
+      For more information have a look at the
+      <tc:link label="#{demoBundle.collapsible_box}"
+               link="/faces/content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.xhtml"/> page
+      in the <tc:link label="#{demoBundle.collapsible}"
+                      link="/faces/content/30-concept/53-collapsible/collapsible.xhtml"/> section.</p>
+  </tc:section>
+
+  <tc:section label="Bar">
+    <p>It's possible to add a bar to the header of a content box. For that, the content box must contain the tag
+      <code class="language-markup">&lt;f:facet name="bar"></code>. The facet may contain
+      <code class="language-markup">&lt;tc:bar></code> or other suitable tags.</p>
+    <tc:box>
+      <f:facet name="label">
+        Label
+      </f:facet>
+      <f:facet name="bar">
+        <tc:buttons>
+          <tc:button label="Button 1"/>
+          <tc:button label="Button 2"/>
+        </tc:buttons>
+      </f:facet>
+      Content
+    </tc:box>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/20-panel/panel.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/20-panel/panel.xhtml
new file mode 100644
index 0000000..1f87305
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/20-panel/panel.xhtml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.panel} &lt;tc:panel>"/>
+  <p>A <code class="language-markup">&lt;tc:panel/></code> is a simple content container.
+    In the most cases it's invisible and wrapping other components.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/panel.html"/>
+
+  <tc:section label="Basics">
+    <p>The panel has a custom class, which set a blue background color. The class of the panel is set via the
+      <code class="language-markup">&lt;tc:style customClass="blue"/></code> tag.</p>
+    <pre><code class="language-markup">&lt;tc:panel>
+  &lt;tc:style customClass="blue"/>
+  ...
+&lt;/tc:panel></code></pre>
+    <tc:panel>
+      <tc:style customClass="blue"/>
+      <p>Content of the panel with the blue background.</p>
+    </tc:panel>
+  </tc:section>
+
+  <tc:section label="Reload">
+    <p>To reload the panel in a dedicated frequency, you can use the
+      <code class="language-markup">&lt;f:facet name="reload"></code> tag.
+      The content of the panel is an outputtext, which display the current time.</p>
+    <pre><code class="language-markup">&lt;tc:panel>
+  &lt;f:facet name="reload">
+    &lt;tc:reload frequency="1000" update="true"/>
+      ...</code></pre>
+    <tc:panel>
+      <f:facet name="reload">
+        <tc:reload frequency="1000" update="true"/>
+      </f:facet>
+      <tc:out id="o1" label="Current Date" value="#{panelController.currentDate}">
+        <f:convertDateTime pattern="HH:mm:ss"/>
+      </tc:out>
+    </tc:panel>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>A panel can also be useful if more than one component should be rerendered.
+      A component for rerendering can be set with the <code>render</code> attribute in the
+      <code class="language-markup">&lt;f:ajax/></code> tag.
+      In this example, 'Outputfield One' and 'Outputfield Two' should be rerendered.
+      To do so, the outputfields are wrapped in a panel.
+      After the inputfield loosing the focus, the given text is shown by the outputfields.</p>
+    <tc:in id="i1" label="Inputfield" value="#{panelController.text}">
+      <f:ajax render="outputfields"/>
+    </tc:in>
+    <tc:panel id="outputfields">
+      <tc:out id="o2" label="Outputfield One" value="#{panelController.text}"/>
+      <tc:out id="o3" label="Outputfield Two" value="#{panelController.text}"/>
+    </tc:panel>
+  </tc:section>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/30-separator/separator.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/30-separator/separator.xhtml
new file mode 100644
index 0000000..dcddec5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/30-separator/separator.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.separator} &lt;tc:separator>"/>
+  <p>A separator can be added with <code class="language-markup">&lt;tc:separator/></code></p>
+
+  <tc:section label="Separator with label">
+    <pre><code class="language-markup">&lt;tc:separator label="Separator with label"/></code></pre>
+    <tc:in id="i1" label="Text 1"/>
+    <tc:separator label="Separator with label"/>
+    <tc:in id="i2" label="Text 2"/>
+  </tc:section>
+
+  <tc:section label="Separator without label">
+    <pre><code class="language-markup">&lt;tc:separator/></code></pre>
+    <tc:in id="i3" label="Text 1"/>
+    <tc:separator/>
+    <tc:in id="i4" label="Text 2"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/40-section/section.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/40-section/section.xhtml
new file mode 100644
index 0000000..0162ec0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/40-section/section.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.section} &lt;tc:section>"/>
+  <p>A section can be added with <code class="language-markup">&lt;tc:section/></code> tag.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/section.html"/>
+
+  <tc:section label="Basics">
+    <p>A section can have a title. It is added with the <code>label</code> attribute.
+      This text is the content of a section.</p>
+    <pre><code class="language-markup">&lt;tc:section label="Basics"></code></pre>
+  </tc:section>
+
+  <tc:section label="Cascading">
+    <p>A section can contain one or more sections. In this example, the sections are cascaded to level six.</p>
+    <tc:section label="Section 2">
+      <p>Level two. The section "Cascading" is level one.</p>
+      <tc:section label="Section 3">
+        <p>Level three.</p>
+        <tc:section label="Section 4">
+          <p>Level four.</p>
+          <tc:section label="Section 5">
+            <p>Level five.</p>
+            <tc:section label="Section 6">
+              <p>Level six.</p>
+            </tc:section>
+          </tc:section>
+        </tc:section>
+      </tc:section>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Image">
+    <p>A section can have an image in the header. The following section have pie-chart in the header.</p>
+    <pre><code class="language-markup">&lt;tc:section label="Pie-Chart" image="fa-pie-chart"></code></pre>
+    <tc:section label="Pie-Chart" image="fa-pie-chart">
+      <p>It's also possible to use image files, instead of font awesome.</p>
+    </tc:section>
+    <tc:section label="Image Files" image="image/alps.png">
+      <p><b>(TODO: currently not working!)</b></p>
+      <!-- todo: this image is only a reminder. -->
+      <tc:image value="image/alps.png"/>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/50-header+footer/header+footer.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/50-header+footer/header+footer.xhtml
new file mode 100644
index 0000000..14abf96
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/50-header+footer/header+footer.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.header_footer} &lt;tc:header> &lt;tc:footer>"/>
+  <p>A header / footer can be set via the <code class="language-markup">&lt;tc:header/></code>
+    respectively <code class="language-markup">&lt;tc:footer/></code> tag.</p>
+
+  <tc:section label="Basics">
+    <p>In this simple example, a <code class="language-markup">&lt;tc:object/></code> show a page with a fixed
+      header and footer. Also you can access this site in a
+      <tc:link label="new tab" link="x-header-footer-example.xhtml" target="_blank"/>.</p>
+    <pre><code class="language-markup">&lt;tc:header fixed="true">
+  &lt;tc:style customClass="bg-inverse"/>
+    &lt;p>This is the header.&lt;/p>
+  &lt;/tc:header>
+  &lt;p>Content between header and footer.&lt;/p>
+  ...
+  &lt;tc:footer fixed="true">
+    &lt;p>This is the footer.&lt;/p>
+&lt;/tc:footer></code></pre>
+    <tc:object src="x-header-footer-example.xhtml">
+      <tc:style height="300px" width="100%"/>
+    </tc:object>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/50-header+footer/x-header-footer-example.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/50-header+footer/x-header-footer-example.xhtml
new file mode 100644
index 0000000..fe94886
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/50-header+footer/x-header-footer-example.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/plain.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <tc:header fixed="true">
+    <tc:style customClass="bg-inverse"/>
+    <p>This is the header.</p>
+  </tc:header>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <p>Content between header and footer.</p>
+  <tc:footer fixed="true">
+    <p>This is the footer.</p>
+  </tc:footer>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/60-bar/bar.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/60-bar/bar.xhtml
new file mode 100644
index 0000000..830ee1a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/60-bar/bar.xhtml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.bar} &lt;tc:bar>"/>
+  <p><code class="language-markup">&lt;tc:bar/></code> is a container which display elements in one single line
+    as long as there is enough space.
+    If space is too narrow, the bar collapse. Hidden items are accessible by clicking on the bar-icon.
+    This makes <code class="language-markup">&lt;tc:bar/></code> great for navigation menus.</p>
+  <p>Additionally the facet <code class="language-markup">&lt;f:facet name="brand"/></code> can be added.
+    It show the 'brand', a logo a text or both on the left site of the bar.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/bar.html"/>
+
+  <tc:section label="Example">
+    <p>This example show a Bar with a 'brand' facet and several components.
+      Buttons and links don't have any functionality.</p>
+    <tc:bar>
+      <f:facet name="brand">
+        <tc:link id="brand" label="Tobago Demo" image="#{request.contextPath}/image/feather-leaf.png" link="/"/>
+      </f:facet>
+      <tc:links>
+        <tc:link label="Home"/>
+        <tc:link label="Configuration" omit="true">
+          <tc:link label="Theme" omit="true">
+            <tc:link label="Standard Theme"/>
+            <tc:link label="Scarborough"/>
+            <tc:link label="Richmond"/>
+            <tc:link label="Charlotteville"/>
+            <tc:link label="Speyside"/>
+          </tc:link>
+          <tc:link image="fa-language" label="Language" omit="true">
+            <tc:link label="English"/>
+            <tc:link label="German"/>
+            <tc:link label="Japanese"/>
+            <tc:link label="Russian"/>
+            <tc:link label="Spanish"/>
+          </tc:link>
+          <tc:link label="Reset"/>
+        </tc:link>
+        <tc:link image="fa-info" label="Help"/>
+      </tc:links>
+      <tc:flowLayout>
+        <tc:style textAlign="right"/>
+        <tc:in placeholder="Search"/>
+        <tc:button label="Go"/>
+      </tc:flowLayout>
+    </tc:bar>
+
+  </tc:section>
+
+  <tc:section label="TODO: radio: (also for tc:links)">
+    <tc:bar>
+      <tc:link omit="true" label="Radio">
+        <tc:selectOneRadio value="#{demoController.radioValue}">
+          <tc:selectItems value="#{demoController.currencyItems}"
+                          var="currency" itemValue="#{currency.currencyCode}" itemLabel="#{currency.displayName}"
+                          itemImage="data/#{currency.currencyCode}-14.png" />
+        </tc:selectOneRadio>
+      </tc:link>
+    </tc:bar>
+  </tc:section>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/container.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/container.xhtml
new file mode 100644
index 0000000..d292081
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/050-container/container.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.container}"/>
+  <p>With the container components, content can be shown in different ways.</p>
+
+  <tc:section label="#{demoBundle.box}">
+    <pre><code class="language-markup">&lt;tc:box label="Box">Content&lt;/tc:box></code></pre>
+    <tc:box label="Box">Content</tc:box>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.panel}">
+    <pre><code class="language-markup">&lt;tc:panel>Content&lt;/tc:panel></code></pre>
+    <tc:panel>Content</tc:panel>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.separator}">
+    <pre><code class="language-markup">&lt;p>Content&lt;/p>
+&lt;tc:separator/>
+&lt;p>Content&lt;/p></code></pre>
+    <p>Content</p>
+    <tc:separator/>
+    <p>Content</p>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.section}">
+    <pre><code class="language-markup">&lt;tc:section label="Section">Content&lt;/tc:section></code></pre>
+    <tc:section label="Section">Content</tc:section>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.header_footer}">
+    <pre><code class="language-markup">&lt;tc:header>Header-Content&lt;/tc:header>
+&lt;p>Content between header and footer.&lt;/p>
+&lt;tc:footer>Footer-Content&lt;/tc:footer></code></pre>
+    <tc:header>Header-Content</tc:header>
+    <p>Content between header and footer.</p>
+    <tc:footer>Footer-Content</tc:footer>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/popup.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/popup.test.js
new file mode 100644
index 0000000..a0875f0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/popup.test.js
@@ -0,0 +1,373 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Open 'Simple Popup' and press 'Cancel'.", function(assert) {
+  assert.expect(3);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form1\\:popup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form1\\:openPopup");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:cancel1");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 1) {
+      $popup = jQueryFrame($popup.selector);
+      assert.equal($popup.attr("value"), "false");
+
+      $cancelButton = jQueryFrame($cancelButton.selector);
+      $cancelButton.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $popup = jQueryFrame($popup.selector);
+      assert.equal($popup.attr("value"), "true");
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Open 'Simple Popup', press 'Submit' while field is empty. Press 'Cancel'.", function(assert) {
+  assert.expect(5);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form1\\:popup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form1\\:openPopup");
+  var $output = jQueryFrame("#page\\:mainForm\\:form1\\:output span");
+  var outputValue = $output.text();
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:in1\\:\\:field");
+  var $submitButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:submit1");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:cancel1");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 1) {
+      $popup = jQueryFrame($popup.selector);
+      $inputField = jQueryFrame($inputField.selector);
+      $submitButton = jQueryFrame($submitButton.selector);
+
+      assert.equal($popup.attr("value"), "false");
+      $inputField.val("");
+      $submitButton.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $popup = jQueryFrame($popup.selector);
+      $cancelButton = jQueryFrame($cancelButton.selector);
+
+      assert.equal($popup.attr("value"), "false");
+      $cancelButton.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $popup = jQueryFrame($popup.selector);
+      $output = jQueryFrame($output.selector);
+
+      assert.equal($popup.attr("value"), "true");
+      assert.equal($output.text(), outputValue);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Open 'Simple Popup', press 'Submit' while field has content. Press 'Cancel'.", function(assert) {
+  assert.expect(5);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form1\\:popup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form1\\:openPopup");
+  var $output = jQueryFrame("#page\\:mainForm\\:form1\\:output span");
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:in1\\:\\:field");
+  var $submitButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:submit1");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:cancel1");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 1) {
+      $popup = jQueryFrame($popup.selector);
+      $inputField = jQueryFrame($inputField.selector);
+      $submitButton = jQueryFrame($submitButton.selector);
+
+      assert.equal($popup.attr("value"), "false");
+      $inputField.val("Hello Popup!");
+      $submitButton.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $popup = jQueryFrame($popup.selector);
+      $cancelButton = jQueryFrame($cancelButton.selector);
+
+      assert.equal($popup.attr("value"), "false");
+      $cancelButton.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $popup = jQueryFrame($popup.selector);
+      $output = jQueryFrame($output.selector);
+
+      assert.equal($popup.attr("value"), "true");
+      assert.equal($output.text(), "Hello Popup!");
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Open 'Simple Popup', press 'Submit & Close' while field is empty. Press 'Cancel'.", function(assert) {
+  assert.expect(5);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form1\\:popup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form1\\:openPopup");
+  var $output = jQueryFrame("#page\\:mainForm\\:form1\\:output span");
+  var outputValue = $output.text();
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:in1\\:\\:field");
+  var $submitCloseButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:submitClose1");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:cancel1");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 1) {
+      $popup = jQueryFrame($popup.selector);
+      $inputField = jQueryFrame($inputField.selector);
+      $submitCloseButton = jQueryFrame($submitCloseButton.selector);
+
+      assert.equal($popup.attr("value"), "false");
+      $inputField.val("");
+      $submitCloseButton.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $popup = jQueryFrame($popup.selector);
+      $cancelButton = jQueryFrame($cancelButton.selector);
+
+      assert.equal($popup.attr("value"), "false");
+      $cancelButton.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $popup = jQueryFrame($popup.selector);
+      $output = jQueryFrame($output.selector);
+
+      assert.equal($popup.attr("value"), "true");
+      assert.equal($output.text(), outputValue);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Open 'Simple Popup', press 'Submit & Close' while field has content.", function(assert) {
+  assert.expect(4);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form1\\:popup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form1\\:openPopup");
+  var $output = jQueryFrame("#page\\:mainForm\\:form1\\:output span");
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:in1\\:\\:field");
+  var $submitCloseButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:submitClose1");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form1\\:popup\\:cancel1");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 1) {
+      $popup = jQueryFrame($popup.selector);
+      $inputField = jQueryFrame($inputField.selector);
+      $submitCloseButton = jQueryFrame($submitCloseButton.selector);
+
+      assert.equal($popup.attr("value"), "false");
+      $inputField.val("press submit and close test");
+      $submitCloseButton.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $popup = jQueryFrame($popup.selector);
+      $output = jQueryFrame($output.selector);
+
+      assert.equal($popup.attr("value"), "true");
+      assert.equal($output.text(), "press submit and close test");
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Open 'Client Popup' and press 'Cancel'.", function(assert) {
+  assert.expect(3);
+  var step = 1;
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form2\\:open");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:cancel2");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+  assert.equal($popup.attr("value"), "false");
+  $cancelButton.click();
+  assert.equal($popup.attr("value"), "true");
+});
+
+QUnit.test("Open 'Client Popup', press 'Submit' while field is empty. Press 'Cancel'.", function(assert) {
+  assert.expect(5);
+  var done = assert.async(1);
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form2\\:open");
+  var $output = jQueryFrame("#page\\:mainForm\\:form2\\:output span");
+  var outputValue = $output.text();
+  var $messages = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:messages");
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:in2\\:\\:field");
+  var $submitButton = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:submit2");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:cancel2");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+  assert.equal($popup.attr("value"), "false");
+  $inputField.val("");
+  $submitButton.click();
+
+  waitForAjax(function() {
+    $messages = jQueryFrame($messages.selector);
+    return $messages.length == 1;
+  }, function() {
+    $output = jQueryFrame($output.selector);
+    $messages = jQueryFrame($messages.selector);
+    $cancelButton = jQueryFrame($cancelButton.selector);
+
+    assert.equal($messages.length, 1);
+    $cancelButton.click();
+    assert.equal($popup.attr("value"), "true");
+    assert.equal($output.text(), outputValue);
+
+    done();
+  });
+});
+
+QUnit.test("Open 'Client Popup', press 'Submit' while field has content. Press 'Cancel'.", function(assert) {
+  assert.expect(5);
+  var done = assert.async(1);
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form2\\:open");
+  var $output = jQueryFrame("#page\\:mainForm\\:form2\\:out span");
+  var $messages = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:messages");
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:in2\\:\\:field");
+  var $submitButton = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:submit2");
+  var $cancelButton = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:cancel2");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+  assert.equal($popup.attr("value"), "false");
+  $inputField.val("test client popup - submit button");
+  $submitButton.click();
+
+  waitForAjax(function() {
+    $messages = jQueryFrame($messages.selector);
+    return $messages.length == 0;
+  }, function() {
+    $output = jQueryFrame($output.selector);
+    $messages = jQueryFrame($messages.selector);
+    $cancelButton = jQueryFrame($cancelButton.selector);
+
+    assert.equal($messages.length, 0);
+    $cancelButton.click();
+    assert.equal($popup.attr("value"), "true");
+    assert.equal($output.text(), "test client popup - submit button");
+
+    done();
+  });
+});
+
+QUnit.test("Open 'Client Popup', press 'Submit & Close' while field is empty.", function(assert) {
+  assert.expect(4);
+  var done = assert.async(1);
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form2\\:open");
+  var $output = jQueryFrame("#page\\:mainForm\\:form2\\:output span");
+  var outputValue = $output.text();
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:in2\\:\\:field");
+  var $submitCloseButton = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:submitClose2");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+  assert.equal($popup.attr("value"), "false");
+  $inputField.val("");
+  $submitCloseButton.click();
+
+  jQuery("#page\\:testframe").load(function() {
+    $popup = jQueryFrame($popup.selector);
+    $output = jQueryFrame($output.selector);
+
+    assert.equal($popup.attr("value"), "true");
+    assert.equal($output.text(), outputValue);
+
+    done();
+  });
+});
+
+QUnit.test("Open 'Simple Popup', press 'Submit & Close' while field has content.", function(assert) {
+  assert.expect(4);
+  var done = assert.async(1);
+
+  var $popup = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup input");
+  var $openButton = jQueryFrame("#page\\:mainForm\\:form2\\:open");
+  var $output = jQueryFrame("#page\\:mainForm\\:form2\\:out span");
+  var $inputField = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:in2\\:\\:field");
+  var $submitCloseButton = jQueryFrame("#page\\:mainForm\\:form2\\:clientPopup\\:submitClose2");
+
+  assert.equal($popup.attr("value"), "true");
+  $openButton.click();
+  assert.equal($popup.attr("value"), "false");
+  $inputField.val("test client popup - submit and close button");
+  $submitCloseButton.click();
+
+  jQuery("#page\\:testframe").load(function() {
+    $popup = jQueryFrame($popup.selector);
+    $output = jQueryFrame($output.selector);
+
+    assert.equal($popup.attr("value"), "true");
+    assert.equal($output.text(), "test client popup - submit and close button");
+
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/popup.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/popup.xhtml
new file mode 100644
index 0000000..835097d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/060-popup/popup.xhtml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.popup} &lt;tc:popup>"/>
+  <p>A popup dialog is created with <code class="language-markup">&lt;tc:popup/></code>.
+    It can be filled with other components.</p>
+  <p>The popup dialog is based on the
+    <tc:link label="#{demoBundle.collapsible}"
+             link="#{request.contextPath}/faces/content/30-concept/53-collapsible/collapsible.xhtml"/> concept.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:popup/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/popup.html"/>
+    |
+    <tc:link label="&lt;tc:operation/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/operation.html"/></p>
+
+  <!--todo: use tc:operations-->
+  <tc:section label="Simple Popup (to be refactored with tc:operations)">
+    <tc:form id="form1">
+      <p>A simple popup realised with a controller. The open button calls the <code>openPopup1</code> action.</p>
+      <tc:button id="openPopup" label="Open" action="#{popupController.openPopup1}"/>
+      <tc:out id="output" label="Text from Popup" value="#{popupController.popup1Text}"/>
+      <tc:popup id="popup" collapsed="#{popupController.popup1Collapsed}">
+        <tc:box label="Simple Popup">
+          <p>This is a popup dialog with an inputfield.</p>
+
+          <p><b>Submit</b><br/>
+            <code class="language-markup">&lt;tc:button label="Submit"/></code>
+            <br/>The 'Submit'-button submit the value in the inputfield.</p>
+
+          <p><b>Submit &amp; Close</b><br/>
+            <code class="language-markup">&lt;tc:button label="Submit &amp; Close" action="\#{popupController.closePopup1}"/></code>
+            <br/>The 'Submit &amp; Close'-button submit the value in the inputfield and
+            call the close-method in the controller.</p>
+
+          <p><b>Cancel</b><br/>
+            <code class="language-markup">&lt;tc:button label="Cancel" immediate="true"
+              action="\#{popupController.closePopup1}"/></code>
+            <br/>The 'Cancel'-button calls the close-method in the controller and
+            has <code>immediate="true"</code>, so no submit is executed.</p>
+
+          <tc:in focus="true" id="in1" label="Required Field" required="true" value="#{popupController.popup1Text}"/>
+          <tc:buttons>
+            <tc:button id="submit1" label="Submit"/>
+            <tc:button id="submitClose1" label="Submit &amp; Close" action="#{popupController.closePopup1}"/>
+            <tc:button id="cancel1" label="Cancel" immediate="true" action="#{popupController.closePopup1}"/>
+          </tc:buttons>
+        </tc:box>
+      </tc:popup>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Client Sided Popup">
+    <tc:form id="form2">
+      <p>To create a client sided popup you have to know about <code>collapsedMode</code>.
+        The mode indicated whether a collapsed popup should be rendered.
+        If <code>collapsedMode="absent"</code>, which is default, a hidden popup dialog will no be rendered.
+        If <code>collapsedMode="hidden"</code>, a hidden popup dialog will be rendered ob the page, but hidden by CSS.
+      </p>
+      <p>Be careful with validations. For example, hidden required input fields will be validated after submit.</p>
+      <p>So to create the popup, use
+        <code class="language-markup">&lt;tc:popup collapsedMode="hidden"></code>.
+        The attribute <code class="language-markup">collapsed="true"</code> is default,
+        because the popup should normally not be opened after loading the page.
+        The hidden popup must be already rendered, so the client don't have to send any requests to the server.</p>
+      <p>Client sided opening and closing can be done with the
+        <code class="language-markup">&lt;tc:operation name="show|hide" for="[ID]"/></code> tag.
+        The attribute <code>name</code> must be set and can have the value 'show' and 'hide'
+        which is to show and hide the popup, obviously.
+        The other mandatory attribute is the <code>for</code> attribute.
+        It contain the ID of the popup on which the transition should be executed.</p>
+
+      <pre><code class="language-markup">&lt;tc:button label="Open" omit="true">
+  &lt;tc:operation name="show" for="clientPopup"/>
+&lt;/tc:button></code></pre>
+      <tc:button id="open" label="Open" omit="true">
+        <tc:operation name="show" for="clientPopup"/>
+      </tc:button>
+      <tc:out id="out" label="Text from Popup" value="#{popupController.popup2Text}"/>
+
+      <tc:popup id="clientPopup" collapsedMode="hidden">
+        <tc:box label="Client Sided Popup">
+          <tc:panel id="clientPopupMessages">
+            <tc:messages id="messages"/>
+          </tc:panel>
+          <p>This is a popup dialog with an inputfield.</p>
+
+          <b>Submit</b>
+          <pre><code class="language-markup">&lt;tc:button label="Submit">
+  &lt;f:ajax execute="in" render="in :::out clientPopupMessages"/>
+&lt;/tc:button></code></pre>
+          <p>The 'Submit'-button send an ajax request to submit the value in the inputfield.
+          </p>
+
+          <b>Submit &amp; Close</b>
+          <pre><code class="language-markup">&lt;tc:button label="Submit &amp; Close">
+  &lt;tc:operation name="hide" for="clientPopup"/>
+&lt;/tc:button></code></pre>
+          <p>The 'Submit &amp; Close'-button execute a submit and run the operation 'hide' to close the popup.</p>
+
+          <b>Cancel</b>
+          <pre><code class="language-markup">&lt;tc:button label="Cancel" omit="true">
+  &lt;tc:operation name="hide" for="clientPopup"/>
+&lt;/tc:button></code></pre>
+          <p>The 'Cancel'-button execute a 'hide'-operation to close the popup.
+            Also the attribute <code>omit="true"</code> is set to prevent submit.</p>
+
+          <tc:in id="in2" label="Required Field" required="true" value="#{popupController.popup2Text}"/>
+          <tc:buttons>
+            <tc:button id="submit2" label="Submit">
+              <f:ajax execute="in2" render="in2 :::out clientPopupMessages"/>
+            </tc:button>
+            <tc:button id="submitClose2" label="Submit &amp; Close">
+              <tc:operation name="hide" for="clientPopup"/>
+            </tc:button>
+            <tc:button id="cancel2" label="Cancel" omit="true">
+              <tc:operation name="hide" for="clientPopup"/>
+            </tc:button>
+          </tc:buttons>
+        </tc:box>
+      </tc:popup>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/00-client/tab-client.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/00-client/tab-client.xhtml
new file mode 100644
index 0000000..da1857c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/00-client/tab-client.xhtml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.tab} - #{demoBundle.tab_client} &lt;tc:tab>"/>
+  <p>Tabs can be created with one or more <code class="language-markup">&lt;tc:tab/></code> within a
+    <code class="language-markup">&lt;tc:tabGroup></code>.
+    Within a tab, content can be added like in a section or a panel.</p>
+  <p>Changing tabs is client sided by default.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:tabGroup/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tabGroup.html"/>
+    |
+    <tc:link label="&lt;tc:tab/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tab.html"/>
+    |
+    <tc:link label="&lt;tc:tabChangeListener/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tabChangeListener.html"/></p>
+
+  <tc:section label="Basics">
+    <p>A simple tabgroup. The second tab is disabled.</p>
+    <tc:tabGroup id="tg1">
+      <tc:tab id="t11" label="One">
+        First tab.
+      </tc:tab>
+      <tc:tab id="t12" label="Two" disabled="true">
+        Second tab.
+      </tc:tab>
+      <tc:tab id="t13" label="Three">
+        Third tab.
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="Header">
+    <p>This example show the different headers if the <code>label</code> or the <code>image</code> is used.</p>
+    <tc:tabGroup id="tg2">
+      <tc:tab id="t21" label="Only label">
+        <p>Only a label is set.</p>
+        <pre><code class="language-markup">&lt;tc:tab label="Only label"/></code></pre>
+      </tc:tab>
+      <tc:tab id="t22" label="Label with image" image="#{request.contextPath}/image/feather-leaf.png">
+        <p>A label and an image are set.</p>
+        <pre><code
+                class="language-markup">&lt;tc:tab label="Label with image" image="\#{request.contextPath}/image/feather-leaf.png"></code></pre>
+      </tc:tab>
+      <tc:tab id="t23" image="#{request.contextPath}/image/feather-leaf.png">
+        <p>Only an image is set.</p>
+        <pre><code class="language-markup">&lt;tc:tab image="\#{request.contextPath}/image/feather-leaf.png"></code></pre>
+      </tc:tab>
+      <tc:tab id="t24">
+        <p>Neither a label or an image are set. In this case the header gets a label with the indexnumber of the tab in
+          the tabgroup.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/01-ajax/tab-ajax.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/01-ajax/tab-ajax.xhtml
new file mode 100644
index 0000000..c6fe353
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/01-ajax/tab-ajax.xhtml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.tab} - #{demoBundle.tab_ajax} &lt;tc:tab>"/>
+  <p>Tabs can be created with one or more <code class="language-markup">&lt;tc:tab/></code> within a
+    <code class="language-markup">&lt;tc:tabGroup></code>.
+    Within a tab, content can be added like in a section or a panel.</p>
+  <p>To activate Ajax, the <code>switchType</code> attribute must have the value "reloadTab".
+    On all tabgroups on this page, Ajax is activated.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:tabGroup/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tabGroup.html"/>
+    |
+    <tc:link label="&lt;tc:tab/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tab.html"/>
+    |
+    <tc:link label="&lt;tc:tabChangeListener/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tabChangeListener.html"/></p>
+
+  <tc:section label="Basics">
+    <p>A simple tabgroup. The second tab is disabled.</p>
+    <tc:tabGroup id="tg1" switchType="reloadTab">
+      <tc:tab id="t11" label="One">
+        First tab.
+      </tc:tab>
+      <tc:tab id="t12" label="Two" disabled="true">
+        Second tab.
+      </tc:tab>
+      <tc:tab id="t13" label="Three">
+        Third tab.
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="Header">
+    <p>This example show the different headers if the <code>label</code> or the <code>image</code> is used.</p>
+    <tc:tabGroup id="tabGroupHead" switchType="reloadTab">
+      <tc:tab id="tabHead1" label="Only label">
+        <p>Only a label is set.</p>
+        <pre><code id="tabHead1Code" class="language-markup">&lt;tc:tab label="Only label"/></code></pre>
+        <f:verbatim><script type="text/javascript">Prism.highlightElement($('#tabHead1Code')[0]);</script></f:verbatim>
+      </tc:tab>
+      <tc:tab id="tabHead2" label="Label with image" image="#{request.contextPath}/image/feather-leaf.png">
+        <p>A label and an image are set.</p>
+        <pre><code id="tabHead2Code"
+                class="language-markup">&lt;tc:tab label="Label with image" image="\#{request.contextPath}/image/feather-leaf.png"></code></pre>
+        <f:verbatim><script type="text/javascript">Prism.highlightElement($('#tabHead2Code')[0]);</script></f:verbatim>
+      </tc:tab>
+      <tc:tab id="tabHead3" image="#{request.contextPath}/image/feather-leaf.png">
+        <p>Only an image is set.</p>
+        <pre><code id="tabHead3Code" class="language-markup">&lt;tc:tab image="\#{request.contextPath}/image/feather-leaf.png"></code></pre>
+        <f:verbatim><script type="text/javascript">Prism.highlightElement($('#tabHead3Code')[0]);</script></f:verbatim>
+      </tc:tab>
+      <tc:tab id="tabHead4">
+        <p>Neither a label or an image are set. In this case the header gets a label with the indexnumber of the tab in
+          the tabgroup.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="Open Folder Example">
+    <p>The image in the header depends on what tab is currently selected.</p>
+    <pre><code class="language-markup">&lt;tc:tabGroup selectedIndex="\#{tabController.index}"></code></pre>
+    <tc:tabGroup id="ft" switchType="reloadTab" selectedIndex="#{tabController.index}">
+      <tc:tab id="ft1" label="One" image="#{tabController.tabOneImage}">
+        <p>First folder open.</p>
+      </tc:tab>
+      <tc:tab id="ft2" label="Two" image="#{tabController.tabTwoImage}">
+        <p>Second folder open.</p>
+      </tc:tab>
+      <tc:tab id="ft3" label="Three" image="#{tabController.tabThreeImage}">
+        <p>Third folder open.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="TabChangeListener">
+    <p>The <code class="language-markup">&lt;tc:tabChangeListener/></code> tag is used to bind a
+      <code>TabChangeListener</code>. The <code>TabChangeListener</code> is an interface,
+      which is implemented in this example by <code>SimpleTabChangeListener</code>.</p>
+    <code class="language-markup">&lt;tc:tabChangeListener type="org.apache.myfaces.tobago.example
+      .demo.actionlistener.SimpleTabChangeListener"
+      binding="\#{tabController.tabChangeListener}"/></code>
+    <tc:tabGroup switchType="reloadTab">
+      <f:ajax render="outPanel"/>
+      <tc:tabChangeListener type="org.apache.myfaces.tobago.example.demo.actionlistener.SimpleTabChangeListener"
+                            binding="#{tabController.tabChangeListener}"/>
+      <tc:tab label="One">
+        <p>Changed to tab one.</p>
+      </tc:tab>
+      <tc:tab label="Two">
+       <!-- <f:ajax render=":page:header:headerInfo"/> -->
+        <p>Changed to tab two.</p>
+      </tc:tab>
+      <tc:tab label="Three">
+        <p>Changed to tab three.</p>
+      </tc:tab>
+    </tc:tabGroup>
+    <tc:box label="Data from the tab group above" id="outPanel">
+      <tc:out label="NewTabIndex" value="#{tabController.newTabIndex}"/>
+      <tc:out label="ClientID" value="#{tabController.clientId}"/>
+      <tc:out label="TabChangedCount" value="#{tabController.count}"/>
+    </tc:box>
+  </tc:section>
+
+  <tc:section label="SwitchType='none'">
+    <p>If no switch type is activated with <code>switchType="none"</code>, you have full control over the tab group.
+      In this example the tabs are used as buttons to refresh the timestamps. The functionallity of
+    switching the tab comes explicitly by adding the id of the tab group to the ajax tag.</p>
+    <tc:tabGroup id="tabGroupSwitchTypeNone" switchType="none">
+      <tc:tab id="nt1" label="One">
+        <f:ajax execute="::tabGroupSwitchTypeNone" render="::tabGroupSwitchTypeNone ::outTimestamp1"/>
+        One
+      </tc:tab>
+      <tc:tab id="nt2" label="Two">
+        <f:ajax execute="::tabGroupSwitchTypeNone" render="::tabGroupSwitchTypeNone ::outTimestamp2"/>
+        Two
+      </tc:tab>
+      <tc:tab id="nt3" label="Three">
+        <f:ajax execute="::tabGroupSwitchTypeNone" render="::tabGroupSwitchTypeNone ::outTimestamp3"/>
+        Three
+      </tc:tab>
+    </tc:tabGroup>
+
+    <tc:box label="Area outsite of the tab group">
+      <tc:out id="outTimestamp1" label="Timestamp One" value="#{eventController.currentTimestamp}"/>
+      <tc:out id="outTimestamp2" label="Timestamp Two" value="#{eventController.currentTimestamp}"/>
+      <tc:out id="outTimestamp3" label="Timestamp Three" value="#{eventController.currentTimestamp}"/>
+    </tc:box>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/02-server/tab-server.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/02-server/tab-server.xhtml
new file mode 100644
index 0000000..e5761b7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/02-server/tab-server.xhtml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.tab} - #{demoBundle.tab_server} &lt;tc:tab>"/>
+  <p>Tabs can be created with one or more <code class="language-markup">&lt;tc:tab/></code> within a
+    <code class="language-markup">&lt;tc:tabGroup></code>.
+    Within a tab, content can be added like in a section or a panel.</p>
+  <p>Changing tabs is client sided by default.
+    To change them server sided, the <code>switchType</code> attribute must have the value "reloadPage".
+    All tabgroups on this page are server sided.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:tabGroup/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tabGroup.html"/>
+    |
+    <tc:link label="&lt;tc:tab/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tab.html"/>
+    |
+    <tc:link label="&lt;tc:tabChangeListener/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tabChangeListener.html"/></p>
+
+  <tc:section label="Basics">
+    <p>A simple tabgroup. The second tab is disabled.</p>
+    <tc:tabGroup id="tg1" switchType="reloadPage">
+      <tc:tab id="t11" label="One">
+        First tab.
+      </tc:tab>
+      <tc:tab id="t12" label="Two" disabled="true">
+        Second tab.
+      </tc:tab>
+      <tc:tab id="t13" label="Three">
+        Third tab.
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="Header">
+    <p>This example show the different headers if the <code>label</code> or the <code>image</code> is used.</p>
+    <tc:tabGroup id="tg2" switchType="reloadPage">
+      <tc:tab id="t21" label="Only label">
+        <p>Only a label is set.</p>
+        <pre><code class="language-markup">&lt;tc:tab label="Only label"/></code></pre>
+      </tc:tab>
+      <tc:tab id="t22" label="Label with image" image="#{request.contextPath}/image/feather-leaf.png">
+        <p>A label and an image are set.</p>
+        <pre><code
+                class="language-markup">&lt;tc:tab label="Label with image" image="\#{request.contextPath}/image/feather-leaf.png"></code></pre>
+      </tc:tab>
+      <tc:tab id="t23" image="#{request.contextPath}/image/feather-leaf.png">
+        <p>Only an image is set.</p>
+        <pre><code class="language-markup">&lt;tc:tab image="\#{request.contextPath}/image/feather-leaf.png"></code></pre>
+      </tc:tab>
+      <tc:tab id="t24">
+        <p>Neither a label or an image are set. In this case the header gets a label with the indexnumber of the tab in
+          the tabgroup.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="Open Folder Example">
+    <p>The image in the header depends on what tab is currently selected.</p>
+    <pre><code class="language-markup">&lt;tc:tabGroup selectedIndex="\#{tabController.index}"></code></pre>
+    <tc:tabGroup switchType="reloadPage" selectedIndex="#{tabController.index}">
+      <tc:tab label="One" image="#{tabController.tabOneImage}">
+        <p>First folder open.</p>
+      </tc:tab>
+      <tc:tab label="Two" image="#{tabController.tabTwoImage}">
+        <p>Second folder open.</p>
+      </tc:tab>
+      <tc:tab label="Three" image="#{tabController.tabThreeImage}">
+        <p>Third folder open.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section id="tabChangeListenerSection" label="TabChangeListener">
+    <p>The <code class="language-markup">&lt;tc:tabChangeListener/></code> tag is used to bind a
+      <code>TabChangeListener</code>. The <code>TabChangeListener</code> is an interface,
+      which is implemented in this example by <code>SimpleTabChangeListener</code>.</p>
+    <code class="language-markup">&lt;tc:tabChangeListener type="org.apache.myfaces.tobago.example
+      .demo.actionlistener.SimpleTabChangeListener"
+      binding="\#{tabController.tabChangeListener}"/></code>
+    <tc:tabGroup switchType="reloadPage">
+      <tc:tabChangeListener type="org.apache.myfaces.tobago.example.demo.actionlistener.SimpleTabChangeListener"
+                            binding="#{tabController.tabChangeListener}"/>
+      <tc:tab label="One">
+        <p>Changed to tab one.</p>
+      </tc:tab>
+      <tc:tab label="Two">
+        <p>Changed to tab two.</p>
+      </tc:tab>
+      <tc:tab label="Three">
+        <p>Changed to tab three.</p>
+      </tc:tab>
+    </tc:tabGroup>
+    <tc:out label="OldTabIndex" value="#{tabController.oldTabIndex}"/>
+    <tc:out label="NewTabIndex" value="#{tabController.newTabIndex}"/>
+    <tc:out label="ClientID" value="#{tabController.clientId}"/>
+    <tc:out label="TabChangedCount" value="#{tabController.count}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/tab.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/tab.xhtml
new file mode 100644
index 0000000..7301b3a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/070-tab/tab.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.tab}"/>
+  <p>A <code class="language-markup">&lt;tc:tabGroup/></code> can contain several
+    <code class="language-markup">&lt;tc:tab/></code> tags.
+    Switching between tabs can be done on the client or by server request.
+    For server requests there are two ways. Reload the whole page and reload only the tab (Ajax).
+    To set the switching type, use the <code>switchType</code> attribute. By default it's client sided.</p>
+
+  <tc:section label="#{demoBundle.tab_client}">
+    <pre><code class="language-markup">&lt;tc:tabGroup></code></pre>
+    <tc:tabGroup>
+      <tc:tab label="Tab One">
+        <p>Content of tab one.</p>
+      </tc:tab>
+      <tc:tab label="Tab Two">
+        <p>Content of tab two.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.tab_ajax}">
+    <pre><code class="language-markup">&lt;tabGroup switchType="reloadTab"></code></pre>
+    <tc:tabGroup switchType="reloadTab">
+      <tc:tab label="Tab One">
+        <p>Content of tab one.</p>
+      </tc:tab>
+      <tc:tab label="Tab Two">
+        <p>Content of tab two.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.tab_server}">
+    <pre><code class="language-markup">&lt;tabGroup switchType="reloadPage"></code></pre>
+    <tc:tabGroup switchType="reloadPage">
+      <tc:tab label="Tab One">
+        <p>Content of tab one.</p>
+      </tc:tab>
+      <tc:tab label="Tab Two">
+        <f:facet name="bar">
+          <tc:link image="fa-remove">
+            <tc:dataAttribute name="alert-text" value="Not implemented yet!"/>
+          </tc:link>
+        </f:facet>
+        <p>Content of tab two.</p>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/00-content/sheet-column-content.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/00-content/sheet-column-content.xhtml
new file mode 100644
index 0000000..90dba1a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/00-content/sheet-column-content.xhtml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet_column_content} &lt;tc:column>"/>
+  <p>This example, demonstrate the flexiblity of the <code class="language-markup">&lt;tc:column/></code> tag.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/></p>
+
+  <tc:section label="Example">
+    <p>The second column contain a tab group. Also a
+      <code class="language-markup"><tc:style/></code> tag is used to set the maximal height of the table.
+      As a result, a vertical scrollbar is shown.
+      The header is hidden by set <code>showHeader</code> to 'false'.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}"
+    var="solarobject" rows="4" showHeader="false">
+  &lt;tc:style maxHeight="500px"/>
+  ...
+  &lt;tc:column label="Orbit &amp; Period">
+    &lt;tc:tabGroup>
+      ...
+    &lt;/tc:tabGroup>
+  &lt;/tc:column>
+  ...</code></pre>
+    <tc:sheet id="s2" value="#{sheetController.solarList}" var="object" rows="4" showHeader="false">
+      <tc:style maxHeight="500px"/>
+      <tc:column label="Name">
+        <tc:out value="#{object.name}"/>
+      </tc:column>
+      <tc:column label="Orbit &amp; Period">
+        <tc:tabGroup>
+          <tc:tab label="Orbiting">
+            <tc:out value="#{object.orbit}"/>
+          </tc:tab>
+          <tc:tab label="Period (Days)">
+            <tc:out value="#{object.period}"/>
+          </tc:tab>
+        </tc:tabGroup>
+      </tc:column>
+      <tc:column label="Discovery">
+        <tc:out value="Discovered by #{object.discoverer} in the year #{object.discoverYear}."/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/sheet-sorting.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/sheet-sorting.test.js
new file mode 100644
index 0000000..ad0744c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/sheet-sorting.test.js
@@ -0,0 +1,1182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Basics: Name", function(assert) {
+  assert.expect(37);
+  var done = assert.async(4);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s1\\:columnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-left input");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+      done();
+
+      $colName.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Proteus", "1.12", "1989",
+            "Prospero", "-1962.95", "1999",
+            "Prometheus", "0.61", "1980",
+            "Praxidike", "625.3", "2000");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Proteus", "1.12", "1989",
+            "Prospero", "-1962.95", "1999",
+            "Prometheus", "0.61", "1980",
+            "Praxidike", "625.3", "2000");
+        done();
+
+        $colName.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Earth", "365.26", "",
+              "Elara", "259.65", "1905",
+              "Enceladus", "1.37", "1789",
+              "Epimetheus", "0.69", "1980");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Earth", "365.26", "",
+              "Elara", "259.65", "1905",
+              "Enceladus", "1.37", "1789",
+              "Epimetheus", "0.69", "1980");
+          done();
+        });
+      });
+    });
+  });
+});
+
+QUnit.test("Basics: Period", function(assert) {
+  assert.expect(37);
+  var done = assert.async(4);
+
+  var $colPeriod = jQueryFrame("#page\\:mainForm\\:s1\\:columnPeriod_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-left input");
+
+  if ($colPeriod.find(".fa-angle-up").length != 1) {
+    $colPeriod.click();
+  }
+
+  waitForAjax(function() {
+    $colPeriod = jQueryFrame($colPeriod.selector);
+    return $colPeriod.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colPeriod = jQueryFrame($colPeriod.selector);
+    assert.equal($colPeriod.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Galatea", "0.43", "1989",
+          "Cressida", "0.46", "1986",
+          "Desdemona", "0.47", "1986",
+          "Juliet", "0.49", "1986");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Galatea", "0.43", "1989",
+          "Cressida", "0.46", "1986",
+          "Desdemona", "0.47", "1986",
+          "Juliet", "0.49", "1986");
+      done();
+
+      $colPeriod.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Leda", "238.72", "1974",
+            "Venus", "224.7", "",
+            "Themisto", "130.02", "2000",
+            "Mercury", "87.97", "");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Leda", "238.72", "1974",
+            "Venus", "224.7", "",
+            "Themisto", "130.02", "2000",
+            "Mercury", "87.97", "");
+        done();
+
+        $colPeriod.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Galatea", "0.43", "1989",
+              "Cressida", "0.46", "1986",
+              "Desdemona", "0.47", "1986",
+              "Juliet", "0.49", "1986");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Galatea", "0.43", "1989",
+              "Cressida", "0.46", "1986",
+              "Desdemona", "0.47", "1986",
+              "Juliet", "0.49", "1986");
+          done();
+        });
+      });
+    });
+  });
+});
+
+QUnit.test("Basics: Year", function(assert) {
+  assert.expect(13);
+  var done = assert.async(4);
+
+  var $colYear = jQueryFrame("#page\\:mainForm\\:s1\\:columnDiscoverYear_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-left input");
+
+  if ($colYear.find(".fa-angle-up").length != 1) {
+    $colYear.click();
+  }
+
+  waitForAjax(function() {
+    $colYear = jQueryFrame($colYear.selector);
+    return $colYear.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colYear = jQueryFrame($colYear.selector);
+    assert.equal($colYear.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text() == "1789"
+          && $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+          && $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+          && $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text() == "1848";
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      assert.equal($rows.eq(0).find(".tobago-sheet-cell span").eq(2).text(), "1789", "row0col2");
+      assert.equal($rows.eq(1).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row1col2");
+      assert.equal($rows.eq(2).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row2col2");
+      assert.equal($rows.eq(3).find(".tobago-sheet-cell span").eq(2).text(), "1848", "row3col2");
+      done();
+
+      $colYear.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text() == "1989"
+            && $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text() == "1989"
+            && $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text() == "1989"
+            && $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text() == "1986";
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        assert.equal($rows.eq(0).find(".tobago-sheet-cell span").eq(2).text(), "1989", "row0col2");
+        assert.equal($rows.eq(1).find(".tobago-sheet-cell span").eq(2).text(), "1989", "row1col2");
+        assert.equal($rows.eq(2).find(".tobago-sheet-cell span").eq(2).text(), "1989", "row2col2");
+        assert.equal($rows.eq(3).find(".tobago-sheet-cell span").eq(2).text(), "1986", "row3col2");
+        done();
+
+        $colYear.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text() == "1789"
+              && $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+              && $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+              && $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text() == "1848";
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          assert.equal($rows.eq(0).find(".tobago-sheet-cell span").eq(2).text(), "1789", "row0col2");
+          assert.equal($rows.eq(1).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row1col2");
+          assert.equal($rows.eq(2).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row2col2");
+          assert.equal($rows.eq(3).find(".tobago-sheet-cell span").eq(2).text(), "1848", "row3col2");
+          done();
+        });
+      });
+    });
+  });
+});
+
+/**
+ * 1. goto line 8
+ * 2. goto line 9
+ */
+QUnit.test("Basics: left paging", function(assert) {
+  assert.expect(25);
+  var done = assert.async(3);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s1\\:columnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-left input");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("8").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Bianca", "0.43", "1986",
+          "Caliban", "-579.39", "1997",
+          "Callirrhoe", "758.8", "2000",
+          "Callisto", "16.69", "1610");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Bianca", "0.43", "1986",
+          "Caliban", "-579.39", "1997",
+          "Callirrhoe", "758.8", "2000",
+          "Callisto", "16.69", "1610");
+      done();
+
+      $leftPaging = jQueryFrame($leftPaging.selector);
+      $leftPaging.val("9").trigger("blur");
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Caliban", "-579.39", "1997",
+            "Callirrhoe", "758.8", "2000",
+            "Callisto", "16.69", "1610",
+            "Calypso", "1.89", "1980");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Caliban", "-579.39", "1997",
+            "Callirrhoe", "758.8", "2000",
+            "Callisto", "16.69", "1610",
+            "Calypso", "1.89", "1980");
+        done();
+      });
+    });
+  });
+});
+
+/**
+ * 1. goto page 7
+ * 2. goto page 16
+ * 3. goto page 13
+ */
+QUnit.test("Basics: center paging", function(assert) {
+  assert.expect(49);
+  var done = assert.async(5);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s1\\:columnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-left input");
+  var $centerPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-center li .page-link");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("1").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "1986U10", "0.64", "1999",
+          "Adrastea", "0.3", "1979",
+          "Amalthea", "0.5", "1892",
+          "Ananke", "-629.77", "1951");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "1986U10", "0.64", "1999",
+          "Adrastea", "0.3", "1979",
+          "Amalthea", "0.5", "1892",
+          "Ananke", "-629.77", "1951");
+      done();
+
+      $centerPaging = jQueryFrame($centerPaging.selector);
+      $centerPaging.eq(6).click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Epimetheus", "0.69", "1980",
+            "Erinome", "728.3", "2000",
+            "Europa", "3.55", "1610",
+            "Galatea", "0.43", "1989");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Epimetheus", "0.69", "1980",
+            "Erinome", "728.3", "2000",
+            "Europa", "3.55", "1610",
+            "Galatea", "0.43", "1989");
+        done();
+
+        $centerPaging = jQueryFrame($centerPaging.selector);
+        $centerPaging.eq(10).click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Phoebe", "-550.48", "1898",
+              "Pluto", "90800.0", "1930",
+              "Portia", "0.51", "1986",
+              "Praxidike", "625.3", "2000");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Phoebe", "-550.48", "1898",
+              "Pluto", "90800.0", "1930",
+              "Portia", "0.51", "1986",
+              "Praxidike", "625.3", "2000");
+          done();
+
+          $centerPaging = jQueryFrame($centerPaging.selector);
+          $centerPaging.eq(3).click();
+
+          waitForAjax(function() {
+            $rows = jQueryFrame($rows.selector);
+            return ajaxWaitingBodyTableCheck($rows,
+                "Neptune", "60190.0", "1846",
+                "Nereid", "360.13", "1949",
+                "Oberon", "13.46", "1787",
+                "Ophelia", "0.38", "1986");
+          }, function() {
+            $rows = jQueryFrame($rows.selector);
+            ajaxExecuteBodyTableCheck(assert, $rows,
+                "Neptune", "60190.0", "1846",
+                "Nereid", "360.13", "1949",
+                "Oberon", "13.46", "1787",
+                "Ophelia", "0.38", "1986");
+            done();
+          });
+        });
+      });
+    });
+  });
+});
+
+/**
+ * 1. goto first page
+ * 2. goto page 2 by pressing arrow-right
+ * 3. goto last page
+ * 4. goto page 21 by pressing arrow-left
+ * 5. goto page 14
+ */
+QUnit.test("Basics: right paging", function(assert) {
+  assert.expect(61);
+  var done = assert.async(6);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s1\\:columnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-left input");
+  var $rightPaging = jQueryFrame("#page\\:mainForm\\:s1 .tobago-sheet-paging-markup-right .page-link");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+      done();
+
+      var $rightPagingFirstPage = jQueryFrame($rightPaging.selector).eq(0);
+      $rightPagingFirstPage.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "1986U10", "0.64", "1999",
+            "Adrastea", "0.3", "1979",
+            "Amalthea", "0.5", "1892",
+            "Ananke", "-629.77", "1951");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "1986U10", "0.64", "1999",
+            "Adrastea", "0.3", "1979",
+            "Amalthea", "0.5", "1892",
+            "Ananke", "-629.77", "1951");
+        done();
+
+        var $rightPagingRight = jQueryFrame($rightPaging.selector).eq(3);
+        $rightPagingRight.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Ariel", "2.52", "1851",
+              "Atlas", "0.6", "1980",
+              "Belinda", "0.62", "1986",
+              "Bianca", "0.43", "1986");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Ariel", "2.52", "1851",
+              "Atlas", "0.6", "1980",
+              "Belinda", "0.62", "1986",
+              "Bianca", "0.43", "1986");
+          done();
+
+          var $rightPagingLastPage = jQueryFrame($rightPaging.selector).eq(4);
+          $rightPagingLastPage.click();
+
+          waitForAjax(function() {
+            $rows = jQueryFrame($rows.selector);
+            return ajaxWaitingBodyTableCheck($rows,
+                "Triton", "-5.88", "1846",
+                "Umbriel", "4.14", "1851",
+                "Uranus", "30685.0", "1781",
+                "Venus", "224.7", "");
+          }, function() {
+            $rows = jQueryFrame($rows.selector);
+            ajaxExecuteBodyTableCheck(assert, $rows,
+                "Triton", "-5.88", "1846",
+                "Umbriel", "4.14", "1851",
+                "Uranus", "30685.0", "1781",
+                "Venus", "224.7", "");
+            done();
+
+            var $rightPagingLeft = jQueryFrame($rightPaging.selector).eq(1);
+            $rightPagingLeft.click();
+
+            waitForAjax(function() {
+              $rows = jQueryFrame($rows.selector);
+              return ajaxWaitingBodyTableCheck($rows,
+                  "Thebe", "0.67", "1979",
+                  "Themisto", "130.02", "2000",
+                  "Titan", "15.95", "1655",
+                  "Titania", "8.71", "1787");
+            }, function() {
+              $rows = jQueryFrame($rows.selector);
+              ajaxExecuteBodyTableCheck(assert, $rows,
+                  "Thebe", "0.67", "1979",
+                  "Themisto", "130.02", "2000",
+                  "Titan", "15.95", "1655",
+                  "Titania", "8.71", "1787");
+              done();
+
+              var $rightPagingJumpToPage = jQueryFrame($rightPaging.selector).find("input");
+              $rightPagingJumpToPage.val("14").trigger("blur");
+
+              waitForAjax(function() {
+                $rows = jQueryFrame($rows.selector);
+                return ajaxWaitingBodyTableCheck($rows,
+                    "Neptune", "60190.0", "1846",
+                    "Nereid", "360.13", "1949",
+                    "Oberon", "13.46", "1787",
+                    "Ophelia", "0.38", "1986");
+              }, function() {
+                $rows = jQueryFrame($rows.selector);
+                ajaxExecuteBodyTableCheck(assert, $rows,
+                    "Neptune", "60190.0", "1846",
+                    "Nereid", "360.13", "1949",
+                    "Oberon", "13.46", "1787",
+                    "Ophelia", "0.38", "1986");
+                done();
+              });
+            });
+          });
+        });
+      });
+    });
+  });
+});
+
+QUnit.test("Custom Sorting: Name", function(assert) {
+  assert.expect(37);
+  var done = assert.async(4);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s2\\:customColumnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-left input");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+      done();
+
+      $colName.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Proteus", "1.12", "1989",
+            "Prospero", "-1962.95", "1999",
+            "Prometheus", "0.61", "1980",
+            "Praxidike", "625.3", "2000");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Proteus", "1.12", "1989",
+            "Prospero", "-1962.95", "1999",
+            "Prometheus", "0.61", "1980",
+            "Praxidike", "625.3", "2000");
+        done();
+
+        $colName.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Earth", "365.26", "",
+              "Elara", "259.65", "1905",
+              "Enceladus", "1.37", "1789",
+              "Epimetheus", "0.69", "1980");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Earth", "365.26", "",
+              "Elara", "259.65", "1905",
+              "Enceladus", "1.37", "1789",
+              "Epimetheus", "0.69", "1980");
+          done();
+        });
+      });
+    });
+  });
+});
+
+QUnit.test("Custom Sorting: Period", function(assert) {
+  assert.expect(37);
+  var done = assert.async(4);
+
+  var $colPeriod = jQueryFrame("#page\\:mainForm\\:s2\\:customColumnPeriod_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-left input");
+
+  if ($colPeriod.find(".fa-angle-up").length != 1) {
+    $colPeriod.click();
+  }
+
+  waitForAjax(function() {
+    $colPeriod = jQueryFrame($colPeriod.selector);
+    return $colPeriod.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colPeriod = jQueryFrame($colPeriod.selector);
+    assert.equal($colPeriod.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Belinda", "0.62", "1986",
+          "Pandora", "0.63", "1980",
+          "1986U10", "0.64", "1999",
+          "Thebe", "0.67", "1979");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Belinda", "0.62", "1986",
+          "Pandora", "0.63", "1980",
+          "1986U10", "0.64", "1999",
+          "Thebe", "0.67", "1979");
+      done();
+
+      $colPeriod.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Ananke", "-629.77", "1951",
+            "Praxidike", "625.3", "2000",
+            "Harpalyke", "623.3", "2000",
+            "Caliban", "-579.39", "1997");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Ananke", "-629.77", "1951",
+            "Praxidike", "625.3", "2000",
+            "Harpalyke", "623.3", "2000",
+            "Caliban", "-579.39", "1997");
+        done();
+
+        $colPeriod.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Belinda", "0.62", "1986",
+              "Pandora", "0.63", "1980",
+              "1986U10", "0.64", "1999",
+              "Thebe", "0.67", "1979");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Belinda", "0.62", "1986",
+              "Pandora", "0.63", "1980",
+              "1986U10", "0.64", "1999",
+              "Thebe", "0.67", "1979");
+          done();
+        });
+      });
+    });
+  });
+});
+
+QUnit.test("Custom Sorting: Year", function(assert) {
+  assert.expect(13);
+  var done = assert.async(4);
+
+  var $colYear = jQueryFrame("#page\\:mainForm\\:s2\\:customColumnYear_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-left input");
+
+  if ($colYear.find(".fa-angle-up").length != 1) {
+    $colYear.click();
+  }
+
+  waitForAjax(function() {
+    $colYear = jQueryFrame($colYear.selector);
+    return $colYear.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colYear = jQueryFrame($colYear.selector);
+    assert.equal($colYear.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text() == "1789"
+          && $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+          && $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+          && $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text() == "1848";
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      assert.equal($rows.eq(0).find(".tobago-sheet-cell span").eq(2).text(), "1789", "row0col2");
+      assert.equal($rows.eq(1).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row1col2");
+      assert.equal($rows.eq(2).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row2col2");
+      assert.equal($rows.eq(3).find(".tobago-sheet-cell span").eq(2).text(), "1848", "row3col2");
+      done();
+
+      $colYear.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text() == "1989"
+            && $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text() == "1989"
+            && $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text() == "1989"
+            && $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text() == "1986";
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        assert.equal($rows.eq(0).find(".tobago-sheet-cell span").eq(2).text(), "1989", "row0col2");
+        assert.equal($rows.eq(1).find(".tobago-sheet-cell span").eq(2).text(), "1989", "row1col2");
+        assert.equal($rows.eq(2).find(".tobago-sheet-cell span").eq(2).text(), "1989", "row2col2");
+        assert.equal($rows.eq(3).find(".tobago-sheet-cell span").eq(2).text(), "1986", "row3col2");
+        done();
+
+        $colYear.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text() == "1789"
+              && $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+              && $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text() == "1846"
+              && $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text() == "1848";
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          assert.equal($rows.eq(0).find(".tobago-sheet-cell span").eq(2).text(), "1789", "row0col2");
+          assert.equal($rows.eq(1).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row1col2");
+          assert.equal($rows.eq(2).find(".tobago-sheet-cell span").eq(2).text(), "1846", "row2col2");
+          assert.equal($rows.eq(3).find(".tobago-sheet-cell span").eq(2).text(), "1848", "row3col2");
+          done();
+        });
+      });
+    });
+  });
+});
+
+/**
+ * 1. goto line 8
+ * 2. goto line 9
+ */
+QUnit.test("Custom Sorting: left paging", function(assert) {
+  assert.expect(25);
+  var done = assert.async(3);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s2\\:customColumnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-left input");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("8").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Bianca", "0.43", "1986",
+          "Caliban", "-579.39", "1997",
+          "Callirrhoe", "758.8", "2000",
+          "Callisto", "16.69", "1610");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Bianca", "0.43", "1986",
+          "Caliban", "-579.39", "1997",
+          "Callirrhoe", "758.8", "2000",
+          "Callisto", "16.69", "1610");
+      done();
+
+      $leftPaging = jQueryFrame($leftPaging.selector);
+      $leftPaging.val("9").trigger("blur");
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Caliban", "-579.39", "1997",
+            "Callirrhoe", "758.8", "2000",
+            "Callisto", "16.69", "1610",
+            "Calypso", "1.89", "1980");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Caliban", "-579.39", "1997",
+            "Callirrhoe", "758.8", "2000",
+            "Callisto", "16.69", "1610",
+            "Calypso", "1.89", "1980");
+        done();
+      });
+    });
+  });
+});
+
+/**
+ * 1. goto page 7
+ * 2. goto page 16
+ * 3. goto page 13
+ */
+QUnit.test("Custom Sorting: center paging", function(assert) {
+  assert.expect(49);
+  var done = assert.async(5);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s2\\:customColumnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-left input");
+  var $centerPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-center li .page-link");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("1").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "1986U10", "0.64", "1999",
+          "Adrastea", "0.3", "1979",
+          "Amalthea", "0.5", "1892",
+          "Ananke", "-629.77", "1951");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "1986U10", "0.64", "1999",
+          "Adrastea", "0.3", "1979",
+          "Amalthea", "0.5", "1892",
+          "Ananke", "-629.77", "1951");
+      done();
+
+      $centerPaging = jQueryFrame($centerPaging.selector);
+      $centerPaging.eq(6).click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "Epimetheus", "0.69", "1980",
+            "Erinome", "728.3", "2000",
+            "Europa", "3.55", "1610",
+            "Galatea", "0.43", "1989");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "Epimetheus", "0.69", "1980",
+            "Erinome", "728.3", "2000",
+            "Europa", "3.55", "1610",
+            "Galatea", "0.43", "1989");
+        done();
+
+        $centerPaging = jQueryFrame($centerPaging.selector);
+        $centerPaging.eq(10).click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Phoebe", "-550.48", "1898",
+              "Pluto", "90800.0", "1930",
+              "Portia", "0.51", "1986",
+              "Praxidike", "625.3", "2000");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Phoebe", "-550.48", "1898",
+              "Pluto", "90800.0", "1930",
+              "Portia", "0.51", "1986",
+              "Praxidike", "625.3", "2000");
+          done();
+
+          $centerPaging = jQueryFrame($centerPaging.selector);
+          $centerPaging.eq(3).click();
+
+          waitForAjax(function() {
+            $rows = jQueryFrame($rows.selector);
+            return ajaxWaitingBodyTableCheck($rows,
+                "Neptune", "60190.0", "1846",
+                "Nereid", "360.13", "1949",
+                "Oberon", "13.46", "1787",
+                "Ophelia", "0.38", "1986");
+          }, function() {
+            $rows = jQueryFrame($rows.selector);
+            ajaxExecuteBodyTableCheck(assert, $rows,
+                "Neptune", "60190.0", "1846",
+                "Nereid", "360.13", "1949",
+                "Oberon", "13.46", "1787",
+                "Ophelia", "0.38", "1986");
+            done();
+          });
+        });
+      });
+    });
+  });
+});
+
+/**
+ * 1. goto first page
+ * 2. goto page 2 by pressing arrow-right
+ * 3. goto last page
+ * 4. goto page 21 by pressing arrow-left
+ * 5. goto page 14
+ */
+QUnit.test("Custom Sorting: right paging", function(assert) {
+  assert.expect(61);
+  var done = assert.async(6);
+
+  var $colName = jQueryFrame("#page\\:mainForm\\:s2\\:customColumnName_sorter");
+  var $rows = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-bodyTable tbody .tobago-sheet-row");
+  var $leftPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-left input");
+  var $rightPaging = jQueryFrame("#page\\:mainForm\\:s2 .tobago-sheet-paging-markup-right .page-link");
+
+  if ($colName.find(".fa-angle-up").length != 1) {
+    $colName.click();
+  }
+
+  waitForAjax(function() {
+    $colName = jQueryFrame($colName.selector);
+    return $colName.find(".fa-angle-up").length == 1;
+  }, function() {
+    $colName = jQueryFrame($colName.selector);
+    assert.equal($colName.find(".fa-angle-up").length, 1);
+    done();
+
+    $leftPaging = jQueryFrame($leftPaging.selector);
+    $leftPaging.val("22").trigger("blur");
+
+    waitForAjax(function() {
+      $rows = jQueryFrame($rows.selector);
+      return ajaxWaitingBodyTableCheck($rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+    }, function() {
+      $rows = jQueryFrame($rows.selector);
+      ajaxExecuteBodyTableCheck(assert, $rows,
+          "Earth", "365.26", "",
+          "Elara", "259.65", "1905",
+          "Enceladus", "1.37", "1789",
+          "Epimetheus", "0.69", "1980");
+      done();
+
+      var $rightPagingFirstPage = jQueryFrame($rightPaging.selector).eq(0);
+      $rightPagingFirstPage.click();
+
+      waitForAjax(function() {
+        $rows = jQueryFrame($rows.selector);
+        return ajaxWaitingBodyTableCheck($rows,
+            "1986U10", "0.64", "1999",
+            "Adrastea", "0.3", "1979",
+            "Amalthea", "0.5", "1892",
+            "Ananke", "-629.77", "1951");
+      }, function() {
+        $rows = jQueryFrame($rows.selector);
+        ajaxExecuteBodyTableCheck(assert, $rows,
+            "1986U10", "0.64", "1999",
+            "Adrastea", "0.3", "1979",
+            "Amalthea", "0.5", "1892",
+            "Ananke", "-629.77", "1951");
+        done();
+
+        var $rightPagingRight = jQueryFrame($rightPaging.selector).eq(3);
+        $rightPagingRight.click();
+
+        waitForAjax(function() {
+          $rows = jQueryFrame($rows.selector);
+          return ajaxWaitingBodyTableCheck($rows,
+              "Ariel", "2.52", "1851",
+              "Atlas", "0.6", "1980",
+              "Belinda", "0.62", "1986",
+              "Bianca", "0.43", "1986");
+        }, function() {
+          $rows = jQueryFrame($rows.selector);
+          ajaxExecuteBodyTableCheck(assert, $rows,
+              "Ariel", "2.52", "1851",
+              "Atlas", "0.6", "1980",
+              "Belinda", "0.62", "1986",
+              "Bianca", "0.43", "1986");
+          done();
+
+          var $rightPagingLastPage = jQueryFrame($rightPaging.selector).eq(4);
+          $rightPagingLastPage.click();
+
+          waitForAjax(function() {
+            $rows = jQueryFrame($rows.selector);
+            return ajaxWaitingBodyTableCheck($rows,
+                "Triton", "-5.88", "1846",
+                "Umbriel", "4.14", "1851",
+                "Uranus", "30685.0", "1781",
+                "Venus", "224.7", "");
+          }, function() {
+            $rows = jQueryFrame($rows.selector);
+            ajaxExecuteBodyTableCheck(assert, $rows,
+                "Triton", "-5.88", "1846",
+                "Umbriel", "4.14", "1851",
+                "Uranus", "30685.0", "1781",
+                "Venus", "224.7", "");
+            done();
+
+            var $rightPagingLeft = jQueryFrame($rightPaging.selector).eq(1);
+            $rightPagingLeft.click();
+
+            waitForAjax(function() {
+              $rows = jQueryFrame($rows.selector);
+              return ajaxWaitingBodyTableCheck($rows,
+                  "Thebe", "0.67", "1979",
+                  "Themisto", "130.02", "2000",
+                  "Titan", "15.95", "1655",
+                  "Titania", "8.71", "1787");
+            }, function() {
+              $rows = jQueryFrame($rows.selector);
+              ajaxExecuteBodyTableCheck(assert, $rows,
+                  "Thebe", "0.67", "1979",
+                  "Themisto", "130.02", "2000",
+                  "Titan", "15.95", "1655",
+                  "Titania", "8.71", "1787");
+              done();
+
+              var $rightPagingJumpToPage = jQueryFrame($rightPaging.selector).find("input");
+              $rightPagingJumpToPage.val("14").trigger("blur");
+
+              waitForAjax(function() {
+                $rows = jQueryFrame($rows.selector);
+                return ajaxWaitingBodyTableCheck($rows,
+                    "Neptune", "60190.0", "1846",
+                    "Nereid", "360.13", "1949",
+                    "Oberon", "13.46", "1787",
+                    "Ophelia", "0.38", "1986");
+              }, function() {
+                $rows = jQueryFrame($rows.selector);
+                ajaxExecuteBodyTableCheck(assert, $rows,
+                    "Neptune", "60190.0", "1846",
+                    "Nereid", "360.13", "1949",
+                    "Oberon", "13.46", "1787",
+                    "Ophelia", "0.38", "1986");
+                done();
+              });
+            });
+          });
+        });
+      });
+    });
+  });
+});
+
+function ajaxWaitingBodyTableCheck($rows, row0col0, row0col1, row0col2, row1col0, row1col1, row1col2,
+                                   row2col0, row2col1, row2col2, row3col0, row3col1, row3col2) {
+  var $row0Col0 = $rows.eq(0).find(".tobago-sheet-cell span").eq(0).text();
+  var $row0Col1 = $rows.eq(0).find(".tobago-sheet-cell span").eq(1).text();
+  var $row0Col2 = $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text();
+  var $row1Col0 = $rows.eq(1).find(".tobago-sheet-cell span").eq(0).text();
+  var $row1Col1 = $rows.eq(1).find(".tobago-sheet-cell span").eq(1).text();
+  var $row1Col2 = $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text();
+  var $row2Col0 = $rows.eq(2).find(".tobago-sheet-cell span").eq(0).text();
+  var $row2Col1 = $rows.eq(2).find(".tobago-sheet-cell span").eq(1).text();
+  var $row2Col2 = $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text();
+  var $row3Col0 = $rows.eq(3).find(".tobago-sheet-cell span").eq(0).text();
+  var $row3Col1 = $rows.eq(3).find(".tobago-sheet-cell span").eq(1).text();
+  var $row3Col2 = $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text();
+
+  return $row0Col0 == row0col0 && $row0Col1 == row0col1 && $row0Col2 == row0col2
+      && $row1Col0 == row1col0 && $row1Col1 == row1col1 && $row1Col2 == row1col2
+      && $row2Col0 == row2col0 && $row2Col1 == row2col1 && $row2Col2 == row2col2
+      && $row3Col0 == row3col0 && $row3Col1 == row3col1 && $row3Col2 == row3col2;
+}
+
+function ajaxExecuteBodyTableCheck(assert, $rows, row0col0, row0col1, row0col2, row1col0, row1col1, row1col2,
+                                   row2col0, row2col1, row2col2, row3col0, row3col1, row3col2) {
+  var $row0Col0 = $rows.eq(0).find(".tobago-sheet-cell span").eq(0).text();
+  var $row0Col1 = $rows.eq(0).find(".tobago-sheet-cell span").eq(1).text();
+  var $row0Col2 = $rows.eq(0).find(".tobago-sheet-cell span").eq(2).text();
+  var $row1Col0 = $rows.eq(1).find(".tobago-sheet-cell span").eq(0).text();
+  var $row1Col1 = $rows.eq(1).find(".tobago-sheet-cell span").eq(1).text();
+  var $row1Col2 = $rows.eq(1).find(".tobago-sheet-cell span").eq(2).text();
+  var $row2Col0 = $rows.eq(2).find(".tobago-sheet-cell span").eq(0).text();
+  var $row2Col1 = $rows.eq(2).find(".tobago-sheet-cell span").eq(1).text();
+  var $row2Col2 = $rows.eq(2).find(".tobago-sheet-cell span").eq(2).text();
+  var $row3Col0 = $rows.eq(3).find(".tobago-sheet-cell span").eq(0).text();
+  var $row3Col1 = $rows.eq(3).find(".tobago-sheet-cell span").eq(1).text();
+  var $row3Col2 = $rows.eq(3).find(".tobago-sheet-cell span").eq(2).text();
+
+  assert.equal($row0Col0, row0col0, "row0col0");
+  assert.equal($row0Col1, row0col1, "row0col1");
+  assert.equal($row0Col2, row0col2, "row0col2");
+  assert.equal($row1Col0, row1col0, "row1col0");
+  assert.equal($row1Col1, row1col1, "row1col1");
+  assert.equal($row1Col2, row1col2, "row1col2");
+  assert.equal($row2Col0, row2col0, "row2col0");
+  assert.equal($row2Col1, row2col1, "row2col1");
+  assert.equal($row2Col2, row2col2, "row2col2");
+  assert.equal($row3Col0, row3col0, "row3col0");
+  assert.equal($row3Col1, row3col1, "row3col1");
+  assert.equal($row3Col2, row3col2, "row3col2");
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/sheet-sorting.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/sheet-sorting.xhtml
new file mode 100644
index 0000000..84d6a8a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/10-sort/sheet-sorting.xhtml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet_sorting} &lt;tc:sheet>"/>
+  <p>Sorting can be enable via the <code>sortable</code> attribute in the
+    <code class="language-markup">&lt;tc:column/></code>.
+    A custom sorting implementation can be set in the <code>sortActionListener</code> attribute in the
+    <code class="language-markup">&lt;tc:sheet/></code>.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/></p>
+
+  <tc:section label="Basics">
+    <p>In this example, the <code>sortable</code> attribute is 'true' for all columns.
+      Notice, that there are negative periods.</p>
+    <pre><code class="language-markup">&lt;tc:column label="Name" sortable="true"></code></pre>
+    <tc:sheet id="s1" value="#{sheetSortingController.solarList}" var="object" rows="4" markup="small">
+      <tc:column id="columnName" label="Name" sortable="true">
+        <tc:out value="#{object.name}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column id="columnPeriod" label="Period (Days)" sortable="true">
+        <tc:out value="#{object.period}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column id="columnDistance" label="Distance" sortable="true" rendered="false">
+        <tc:out value="#{object.distance}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column id="columnDiscoverYear" label="Discovery Year" sortable="true">
+        <tc:out value="#{object.discoverYear}" labelLayout="skip"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+
+  <tc:section label="Custom Sorting">
+    <p>All columns in this sheet can be sorted. A custom sorting implementation is set.
+      Now, the sign for period numbers is ignored by sorting.</p>
+
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}"
+    var="solarobject" rows="4"
+    sortActionListener="\#{sheetController.sheetSorter}">
+      &lt;tc:column id="namecol" label="Name" sortable="true">
+      ...
+    </code></pre>
+
+    <tc:sheet id="s2" value="#{sheetSortingController.solarList}" var="object" rows="4"
+              sortActionListener="#{sheetSortingController.sheetSorter}" markup="small">
+      <tc:column id="customColumnName" label="Name" sortable="true">
+        <tc:out value="#{object.name}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column id="customColumnPeriod" label="Period (Days)" sortable="true">
+        <tc:out value="#{object.period}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column id="customColumnDistance" label="Period (Days)" sortable="true" rendered="false">
+        <tc:out value="#{object.period}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column id="customColumnYear" label="Discovery Year" sortable="true">
+        <tc:out value="#{object.discoverYear}" labelLayout="skip"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/20-selector/sheet-column-selector.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/20-selector/sheet-column-selector.xhtml
new file mode 100644
index 0000000..59ec554
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/20-selector/sheet-column-selector.xhtml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet_column_selector} &lt;tc:columnSelector>"/>
+  <p>To insert a selectable column, use the <code class="language-markup">&lt;tc:columnSelector/></code> tag.
+    With the <code>selectable</code> in the <code class="language-markup">&lt;tc:sheet/></code> tag, you can
+    adjust, whether the column should show checkboxes (default) or radio button 'singleOrNone'.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:columnSelector/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/columnSelector.html"/></p>
+
+  <tc:section label="Column Selector">
+    <p>The first column in this sheet contain radio buttons.
+      After clicking the submit button, the number of the selected row is displayed in the outputfield.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}"
+    var="solarobject" selectable="singleOrNone" rows="2"
+    state="\#{sheetController.sheetState}">
+    &lt;tc:columnSelector/>
+    &lt;tc:column label="Name">
+      &lt;tc:out value="\#{solarobject.name}"/>
+    &lt;/tc:column>
+    ...</code></pre>
+    <tc:sheet id="s4" value="#{sheetController.solarList}" var="object" rows="2"
+              selectable="singleOrNone" state="#{sheetController.sheetState}">
+      <tc:columnSelector/>
+      <tc:column label="Name">
+        <tc:in value="#{object.name}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:out value="#{object.orbit}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:out value="#{object.period}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{object.discoverer}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:out value="#{object.discoverYear}" labelLayout="skip"/>
+      </tc:column>
+    </tc:sheet>
+
+    <tc:button id="b1" label="Submit"/>
+    <tc:out id="o1" label="Row Number" value="#{sheetController.selectedRowNumber}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/sheet-event.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/sheet-event.test.js
new file mode 100644
index 0000000..874c9fd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/sheet-event.test.js
@@ -0,0 +1,191 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("On click with ajax", function(assert) {
+  assert.expect(6);
+  var done = assert.async(4);
+
+  $oneClickAjax = jQueryFrame("#page\\:mainForm\\:changeExample\\:\\:0");
+  $venus = jQueryFrame("#page\\:mainForm\\:s1\\:2\\:sample0");
+  $jupiter = jQueryFrame("#page\\:mainForm\\:s1\\:5\\:sample0");
+  $saturn = jQueryFrame("#page\\:mainForm\\:s1\\:6\\:sample0");
+  $namefield = jQueryFrame("#page\\:mainForm\\:name\\:\\:field");
+
+  $oneClickAjax.click();
+
+  waitForAjax(function() {
+    $venus = jQueryFrame($venus.selector);
+    $jupiter = jQueryFrame($jupiter.selector);
+    $saturn = jQueryFrame($saturn.selector);
+    return $venus.length == 1 && $jupiter.length == 1 && $saturn.length == 1;
+  }, function() {
+    $venus = jQueryFrame($venus.selector);
+    $jupiter = jQueryFrame($jupiter.selector);
+    $saturn = jQueryFrame($saturn.selector);
+    assert.equal($venus.length, 1);
+    assert.equal($jupiter.length, 1);
+    assert.equal($saturn.length, 1);
+    done();
+
+    $venus.click();
+
+    waitForAjax(function() {
+      $namefield = jQueryFrame($namefield.selector);
+      return $namefield.val() == "Venus";
+    }, function() {
+      $namefield = jQueryFrame($namefield.selector);
+      assert.equal($namefield.val(), "Venus");
+      done();
+
+      $jupiter.click();
+
+      waitForAjax(function() {
+        $namefield = jQueryFrame($namefield.selector);
+        return $namefield.val() == "Jupiter";
+      }, function() {
+        $namefield = jQueryFrame($namefield.selector);
+        assert.equal($namefield.val(), "Jupiter");
+        done();
+
+        $saturn.click();
+
+        waitForAjax(function() {
+          $namefield = jQueryFrame($namefield.selector);
+          return $namefield.val() == "Saturn";
+        }, function() {
+          $namefield = jQueryFrame($namefield.selector);
+          assert.equal($namefield.val(), "Saturn");
+          done();
+        });
+      });
+    });
+  });
+});
+
+QUnit.test("On click with full request", function(assert) {
+  assert.expect(6);
+  var done = assert.async(4);
+  var step = 1;
+
+  $oneClickFullRequest = jQueryFrame("#page\\:mainForm\\:changeExample\\:\\:1");
+  $venus = jQueryFrame("#page\\:mainForm\\:s1\\:2\\:sample1");
+  $jupiter = jQueryFrame("#page\\:mainForm\\:s1\\:5\\:sample1");
+  $saturn = jQueryFrame("#page\\:mainForm\\:s1\\:6\\:sample1");
+  $namefield = jQueryFrame("#page\\:mainForm\\:name\\:\\:field");
+
+  $oneClickFullRequest.click();
+
+  waitForAjax(function() {
+    $venus = jQueryFrame($venus.selector);
+    $jupiter = jQueryFrame($jupiter.selector);
+    $saturn = jQueryFrame($saturn.selector);
+    return $venus.length == 1 && $jupiter.length == 1 && $saturn.length == 1;
+  }, function() {
+    if (step == 1) {
+      $venus = jQueryFrame($venus.selector);
+      $jupiter = jQueryFrame($jupiter.selector);
+      $saturn = jQueryFrame($saturn.selector);
+      assert.equal($venus.length, 1);
+      assert.equal($jupiter.length, 1);
+      assert.equal($saturn.length, 1);
+
+      $venus.click();
+    }
+
+    done();
+    step++;
+  });
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 2) {
+      $namefield = jQueryFrame($namefield.selector);
+      assert.equal($namefield.val(), "Venus");
+
+      $jupiter = jQueryFrame($jupiter.selector);
+      $jupiter.click();
+    } else if (step == 3) {
+      $namefield = jQueryFrame($namefield.selector);
+      assert.equal($namefield.val(), "Jupiter");
+
+      $saturn = jQueryFrame($saturn.selector);
+      $saturn.click();
+    } else if (step == 4) {
+      $namefield = jQueryFrame($namefield.selector);
+      assert.equal($namefield.val(), "Saturn");
+    }
+
+    step++;
+    done();
+  });
+});
+
+QUnit.test("On double click with full request", function(assert) {
+  assert.expect(6);
+  var done = assert.async(4);
+  var step = 1;
+
+  $doubleClickFullRequest = jQueryFrame("#page\\:mainForm\\:changeExample\\:\\:2");
+  $venus = jQueryFrame("#page\\:mainForm\\:s1\\:2\\:sample2");
+  $jupiter = jQueryFrame("#page\\:mainForm\\:s1\\:5\\:sample2");
+  $saturn = jQueryFrame("#page\\:mainForm\\:s1\\:6\\:sample2");
+  $namefield = jQueryFrame("#page\\:mainForm\\:name\\:\\:field");
+
+  $doubleClickFullRequest.click();
+
+  waitForAjax(function() {
+    $venus = jQueryFrame($venus.selector);
+    $jupiter = jQueryFrame($jupiter.selector);
+    $saturn = jQueryFrame($saturn.selector);
+    return $venus.length == 1 && $jupiter.length == 1 && $saturn.length == 1;
+  }, function() {
+    if (step == 1) {
+      $venus = jQueryFrame($venus.selector);
+      $jupiter = jQueryFrame($jupiter.selector);
+      $saturn = jQueryFrame($saturn.selector);
+      assert.equal($venus.length, 1);
+      assert.equal($jupiter.length, 1);
+      assert.equal($saturn.length, 1);
+
+      $venus.dblclick();
+    }
+
+    done();
+    step++;
+  });
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 2) {
+      $namefield = jQueryFrame($namefield.selector);
+      assert.equal($namefield.val(), "Venus");
+
+      $jupiter = jQueryFrame($jupiter.selector);
+      $jupiter.dblclick();
+    } else if (step == 3) {
+      $namefield = jQueryFrame($namefield.selector);
+      assert.equal($namefield.val(), "Jupiter");
+
+      $saturn = jQueryFrame($saturn.selector);
+      $saturn.dblclick();
+    } else if (step == 4) {
+      $namefield = jQueryFrame($namefield.selector);
+      assert.equal($namefield.val(), "Saturn");
+    }
+
+    step++;
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/sheet-event.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/sheet-event.xhtml
new file mode 100644
index 0000000..5587012
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/30-event/sheet-event.xhtml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.sheet_event} &lt;tc:row>"/>
+  <p>A <code class="language-markup">&lt;tc:sheet/></code> can contain a
+    <code class="language-markup">&lt;tc:columnEvent/></code> tag, which knows two types of events.
+    The event type can be set by the <code>event</code> attribute. Possible values are 'click' and 'dblclick'.
+  </p>
+
+  <tc:section label="Example">
+    Here are different examples:
+    <tc:selectOneRadio id="changeExample" value="#{sheetController.columnEventSample}">
+      <tc:selectItem itemValue="0" itemLabel="on click with AJAX"/>
+      <tc:selectItem itemValue="1" itemLabel="on click with full request"/>
+      <tc:selectItem itemValue="2" itemLabel="on double click with full request"/>
+      <tc:selectItem itemValue="3" itemLabel="open popup on click with AJAX"/>
+      <f:ajax render="example"/>
+    </tc:selectOneRadio>
+    <p>Select an object from the SolarObjects list.</p>
+    <tc:segmentLayout id="example" medium="5;7">
+      <tc:box label="Solar Objects">
+        <tc:sheet id="s1" value="#{sheetController.solarList}" var="object" columns="*" markup="small">
+          <tc:style maxHeight="486px"/>
+          <tc:column label="#{demoBundle.solarArrayName}">
+            <tc:out value="#{object.name}" id="t_name" labelLayout="skip"/>
+          </tc:column>
+          <tc:row id="sample0" rendered="#{sheetController.columnEventSample == 0}">
+            <f:ajax render=":::detail" listener="#{sheetController.selectSolarObject}" id="columnEventAjax"/>
+          </tc:row>
+          <tc:row id="sample1" rendered="#{sheetController.columnEventSample == 1}">
+            <tc:event actionListener="#{sheetController.selectSolarObject}" immediate="true" id="columnEventClick"
+                      event="click">
+              <tc:resetInputActionListener/>
+            </tc:event>
+          </tc:row>
+          <tc:row id="sample2" rendered="#{sheetController.columnEventSample == 2}">
+            <tc:event actionListener="#{sheetController.selectSolarObject}" immediate="true" id="columnEventDblClick"
+                      event="dblclick">
+              <tc:resetInputActionListener/>
+            </tc:event>
+          </tc:row>
+
+          <tc:row id="sample3" rendered="#{sheetController.columnEventSample == 3}">
+            <f:ajax execute=":::popup" render=":::popup" listener="#{sheetController.selectSolarObject}" id="columnEventPopup"/>
+            <tc:event omit="true">
+              <tc:operation name="show" for=":::popup"/>
+            </tc:event>
+          </tc:row>
+
+        </tc:sheet>
+      </tc:box>
+
+      <tc:box id="detail" label="Details" rendered="#{sheetController.columnEventSample le 2}">
+        <tc:panel rendered="#{sheetController.selectedSolarObject != null}">
+          <tc:in id="name" label="Name" value="#{sheetController.selectedSolarObject.name}" required="true"/>
+          <tc:in label="Number" value="#{sheetController.selectedSolarObject.number}"/>
+          <tc:in label="Orbit" value="#{sheetController.selectedSolarObject.orbit}"/>
+          <tc:in label="Distance" value="#{sheetController.selectedSolarObject.distance}"/>
+          <tc:in label="Period" value="#{sheetController.selectedSolarObject.period}"/>
+          <tc:in label="Obliquity" value="#{sheetController.selectedSolarObject.incl}"/>
+          <tc:in label="Eccentricity" value="#{sheetController.selectedSolarObject.eccen}"/>
+          <tc:in label="Discoverer" value="#{sheetController.selectedSolarObject.discoverer}"/>
+          <tc:in label="Discover Year" value="#{sheetController.selectedSolarObject.discoverYear}"/>
+        </tc:panel>
+
+        <tc:panel rendered="#{sheetController.selectedSolarObject == null}">
+          <tc:out value="Please select a solar object on the left side to show its details."/>
+        </tc:panel>
+      </tc:box>
+    </tc:segmentLayout>
+
+    <tc:panel id="reloadable">
+
+      <tc:popup id="popup">
+        <tc:box label="Details">
+          <tc:in label="Name" value="#{sheetController.selectedSolarObject.name}" required="true"/>
+          <tc:in label="Number" value="#{sheetController.selectedSolarObject.number}"/>
+          <tc:in label="Orbit" value="#{sheetController.selectedSolarObject.orbit}"/>
+          <tc:in label="Distance" value="#{sheetController.selectedSolarObject.distance}"/>
+          <tc:in label="Period" value="#{sheetController.selectedSolarObject.period}"/>
+          <tc:in label="Obliquity" value="#{sheetController.selectedSolarObject.incl}"/>
+          <tc:in label="Eccentricity" value="#{sheetController.selectedSolarObject.eccen}"/>
+          <tc:in label="Discoverer" value="#{sheetController.selectedSolarObject.discoverer}"/>
+          <tc:in label="Discover Year" value="#{sheetController.selectedSolarObject.discoverYear}"/>
+          <tc:buttons>
+            <tc:button id="submit" label="Submit" action="#{popupController.closePopup1}">
+              <f:ajax execute="popup" render=":::example"/>
+              <tc:operation name="hide" for="popup"/>
+            </tc:button>
+            <tc:button id="cancel" label="Cancel" omit="true">
+              <tc:operation name="hide" for="popup"/>
+            </tc:button>
+          </tc:buttons>
+        </tc:box>
+      </tc:popup>
+
+    </tc:panel>
+
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/35-markup/sheet-markup.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/35-markup/sheet-markup.xhtml
new file mode 100644
index 0000000..9e83da8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/35-markup/sheet-markup.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.sheet_markup}"/>
+  <p>This example, demonstrate the different markups defined for sheet.
+    These markups reflecting the styles from bootstrap.
+    <tc:selectOneRadio value="#{sheetController.automaticLayout}">
+      <tc:event/>
+      <tc:selectItem itemLabel="Automatic table layout" itemValue="true"/>
+      <tc:selectItem itemLabel="Managed table layout" itemValue="false"/>
+    </tc:selectOneRadio>
+
+    <tc:selectManyShuttle value="#{sheetController.markup}">
+      <tc:event/>
+      <tc:selectItem itemLabel="Inverse" itemValue="inverse"/>
+      <tc:selectItem itemLabel="Striped" itemValue="striped"/>
+      <tc:selectItem itemLabel="Bordered" itemValue="bordered"/>
+      <tc:selectItem itemLabel="Hover" itemValue="hover"/>
+      <tc:selectItem itemLabel="Small" itemValue="small"/>
+    </tc:selectManyShuttle>
+  </p>
+
+  <tc:section label="Markup">
+    <pre><code class="language-markup">&lt;tc:sheet markup="inverse hover" ...></code></pre>
+    <tc:sheet markup="#{sheetController.markup}" value="#{sheetController.solarList}" var="object" rows="4"
+              columns="#{sheetController.automaticLayout ? null : '*;*;*;*;*'}">
+      <tc:column label="Name">
+        <tc:out value="#{object.name}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:out value="#{object.orbit}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:out value="#{object.period}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{object.discoverer}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:out value="#{object.discoverYear}" labelLayout="skip"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/50-filter/sheet-filter.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/50-filter/sheet-filter.xhtml
new file mode 100644
index 0000000..af2f0ac
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/50-filter/sheet-filter.xhtml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <ui:param name="title" value="#{demoBundle.sheet_filter} &lt;tc:sheet/>"/>
+  <p>Filtering is not a explicit feature of the sheet. It is done in the controller.</p>
+  <p>To add filtering components to the header of a sheet, use
+    <code class="language-markup">&lt;f:facet name="header"></code>.</p>
+  <p><b>Warning:</b> Paging currently doesn't work with filters!</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/></p>
+
+  <tc:section label="#{demoBundle.sheet_filter}">
+    <p>Add a search string to the inputfield or change the value of the dropdown boxes to filter the sheet.
+      If an inputfield lost focus the filtering will be executed.</p>
+    <tc:sheet id="sheet" value="#{sheetFilterController.filteredSolarList}" var="object" rows="15">
+      <f:facet name="header">
+        <tc:form id="headerForm">
+          <tc:panel>
+            <tc:out value="Name"/>
+            <tc:in value="#{sheetFilterController.name}">
+              <tc:suggest totalCount="10" query="#{sheetFilterController.nameSuggestionQuery}">
+                <tc:selectItems value="#{sheetFilterController.suggestionSolarList}" var="name" itemValue="#{name}"/>
+              </tc:suggest>
+              <!-- XXX using blur instead of change for event, because of TOBAGO-1689 -->
+              <f:ajax event="blur" execute=":::sheet" render=":::sheet" listener="#{sheetFilterController.filter}"/>
+            </tc:in>
+          </tc:panel>
+          <tc:panel>
+            <tc:out value="Orbit"/>
+            <tc:in value="#{sheetFilterController.orbit}">
+              <f:ajax execute=":::sheet" render=":::sheet" listener="#{sheetFilterController.filter}"/>
+            </tc:in>
+          </tc:panel>
+          <tc:panel>
+            <tc:out value="Distance [1000 km]"/>
+            <tc:selectOneChoice value="#{sheetFilterController.distance}"
+                                converter="#{sheetFilterController.distanceRangeConverter}">
+              <tc:selectItems value="#{sheetFilterController.distanceItems}"/>
+              <f:ajax execute=":::sheet" render=":::sheet" listener="#{sheetFilterController.filter}"/>
+            </tc:selectOneChoice>
+          </tc:panel>
+          <tc:out value="Period"/>
+          <tc:panel>
+            <tc:out value="Discoverer"/>
+            <tc:in value="#{sheetFilterController.discoverer}">
+              <f:ajax execute=":::sheet" render=":::sheet" listener="#{sheetFilterController.filter}"/>
+            </tc:in>
+          </tc:panel>
+          <tc:panel>
+            <tc:out value="Year"/>
+            <tc:flexLayout columns="1*;1*">
+              <tc:selectOneChoice value="#{sheetFilterController.minYear}">
+                <tc:style width="70px"/>
+                <tc:selectItems value="#{sheetFilterController.minYearItems}"/>
+                <f:ajax execute=":::sheet" render=":::sheet" listener="#{sheetFilterController.filter}"/>
+              </tc:selectOneChoice>
+              <tc:selectOneChoice value="#{sheetFilterController.maxYear}">
+                <tc:style width="70px"/>
+                <tc:selectItems value="#{sheetFilterController.maxYearItems}"/>
+                <f:ajax execute=":::sheet" render=":::sheet" listener="#{sheetFilterController.filter}"/>
+              </tc:selectOneChoice>
+            </tc:flexLayout>
+          </tc:panel>
+        </tc:form>
+      </f:facet>
+      <tc:column>
+        #{object.name}
+      </tc:column>
+      <tc:column>
+        #{object.orbit}
+      </tc:column>
+      <tc:column>
+        #{object.distance}
+      </tc:column>
+      <tc:column>
+        #{object.period}
+      </tc:column>
+      <tc:column>
+        #{object.discoverer}
+      </tc:column>
+      <tc:column>
+        #{object.discoverYear}
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/55-staticheader/sheet-static-header.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/55-staticheader/sheet-static-header.xhtml
new file mode 100644
index 0000000..86822a4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/55-staticheader/sheet-static-header.xhtml
@@ -0,0 +1,118 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet_static_header}"/>
+  <p>There are several ways to display the header.
+    For simple column headers, use the attribute <code>label</code> of
+    <code class="language-markup">&lt;tc:column></code>.
+    For more complex header which span over columns and/or rows please go to the
+    <tc:link label="#{demoBundle.sheet_multi_header}"
+             link="/faces/content/20-component/080-sheet/60-multiheader/sheet-multi-header.xhtml"/> section.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/></p>
+
+  <tc:section label="Basics">
+    <p>A sheet with six rows. The name of the columns is set by the <code>label</code> attribute.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}" var="object" rows="6">
+  &lt;tc:column label="Name">
+    &lt;tc:out value="\#{object.name}"/>
+  ...</code></pre>
+    <tc:sheet id="simpleSheet" value="#{sheetController.solarList}" var="object" rows="6">
+      <tc:column label="Name">
+        <tc:out value="#{object.name}"/>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:out value="#{object.orbit}"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:out value="#{object.period}"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{object.discoverer}"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:out value="#{object.discoverYear}"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+
+  <tc:section label="Scrolling Header">
+    <p>A sheet with ten rows and a maximal height of 500px. The header is scrollable.</p>
+    <p>To get a scrolling header, you have to set a maximal height
+      and the width of all columns must be calculated automatically.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}" var="object" rows="10">
+  &lt;tc:style maxHeight="500px"/>
+  ...</code></pre>
+    <tc:sheet id="scrollHeaderSheet" value="#{sheetController.solarList}" var="object" rows="10">
+      <tc:style maxHeight="500px"/>
+      <tc:column label="Name">
+        <tc:out value="#{object.name}"/>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:out value="#{object.orbit}"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:out value="#{object.period}"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{object.discoverer}"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:out value="#{object.discoverYear}"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+
+  <tc:section label="Header always visible">
+    <p>A sheet with ten rows and a maximal height of 500px. The header is static.</p>
+    <p>To get a static header, you have to set a maximal height and the
+      <code>columns</code> attribute must be used to set the width of the columns manually.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}" var="object" rows="10"
+      columns="3*;80px;20%;2*;1*">
+  &lt;tc:style maxHeight="500px"/>
+  ...</code></pre>
+    <tc:sheet id="alwaysVisibleHeaderSheet" value="#{sheetController.solarList}" var="object" rows="10"
+              columns="3*;80px;20%;2*;1*">
+      <tc:style maxHeight="500px"/>
+      <tc:column label="Name">
+        <tc:out value="#{object.name}"/>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:out value="#{object.orbit}"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:out value="#{object.period}"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{object.discoverer}"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:out value="#{object.discoverYear}"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/60-multiheader/sheet-multi-header.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/60-multiheader/sheet-multi-header.xhtml
new file mode 100644
index 0000000..0f0359d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/60-multiheader/sheet-multi-header.xhtml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.sheet}"/>
+  <p>For more complex headers, which can span over columns and/or rows use a
+    <code class="language-markup">&lt;f:facet name="header"></code>in the sheet.
+    The facet could be filled with <code class="language-markup">&lt;tc:out/></code> tags
+    to set the names of the header.
+    Such an outputfield tag may also contain
+    <code class="language-markup">&lt;tc:span column="..."/></code>
+    or
+    <code class="language-markup">&lt;tc:span row="..."/></code>
+    to set a span over columns or rows.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/>
+    |
+    <tc:link label="&lt;tc:span/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/gridLayoutConstraint.html"/></p>
+
+  <tc:section label="Multi-Header">
+    <p>For multi-header sheets, you should consider to use <code>markup="bordered"</code> for better appearance.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}" var="luminary" rows="11"
+    columns="3*;2*;30px;2*;2*;2*;2*;2*;2*" markup="bordered">
+  &lt;f:facet name="header">
+    &lt;tc:out value="Name">
+      &lt;tc:span row="3"/>
+    &lt;/tc:out>
+    &lt;tc:out value="Information">
+      &lt;tc:span column="2"/>
+    ...</code></pre>
+    <tc:sheet value="#{sheetController.solarList}" var="luminary" rows="11"
+              columns="3*;2*;30px;2*;2*;2*;2*;2*;2*" markup="bordered">
+      <f:facet name="header">
+        <tc:panel>
+          <tc:out value="Name">
+            <tc:span row="3"/>
+          </tc:out>
+          <tc:out value="Information">
+            <tc:span column="2"/>
+          </tc:out>
+          <tc:out value="Data">
+            <tc:span column="4"/>
+          </tc:out>
+          <tc:out value="Discovery">
+            <tc:span column="2"/>
+          </tc:out>
+
+          <tc:out value="Orbit">
+            <tc:span column="3"/>
+          </tc:out>
+          <tc:out value="Orb">
+            <tc:span column="3"/>
+          </tc:out>
+          <tc:out value="Name">
+            <tc:span row="2"/>
+          </tc:out>
+          <tc:out value="Year">
+            <tc:span row="2"/>
+          </tc:out>
+
+          <tc:out value="of"/>
+          <tc:out value="#"/>
+          <tc:out value="Distance [1000 km]"/>
+          <tc:out value="Period [days]"/>
+          <tc:out value="Inclination [°]"/>
+          <tc:out value="Eccentricity"/>
+        </tc:panel>
+      </f:facet>
+
+      <tc:column align="center">
+        #{luminary.name}
+      </tc:column>
+      <tc:column sortable="true">
+        #{luminary.orbit}
+      </tc:column>
+      <tc:column align="center">
+        #{luminary.number}
+      </tc:column>
+      <tc:column align="right" sortable="true">
+        #{luminary.distance}
+      </tc:column>
+      <tc:column align="right" sortable="true">
+        #{luminary.period}
+      </tc:column>
+      <tc:column align="right" sortable="true">
+        #{luminary.incl}
+      </tc:column>
+      <tc:column align="right" sortable="true">
+        #{luminary.eccen}
+      </tc:column>
+      <tc:column sortable="true">
+        #{luminary.discoverer}
+      </tc:column>
+      <tc:column align="center" sortable="true">
+        #{luminary.discoverYear}
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/70-tree/sheet-tree.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/70-tree/sheet-tree.xhtml
new file mode 100644
index 0000000..d269068
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/70-tree/sheet-tree.xhtml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet_tree} &lt;tc:columnNode/>"/>
+  <p>A tree can be added into a sheet. To do so, there are two steps which must be done.
+    First, the <code>value</code> attribute of the sheet must refer to a method, which return a tree instead of a list.
+    Second, to display the tree, use the <code class="language-markup">&lt;tc:columnNode/></code> tag.</p>
+
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:columnNode/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/columnNode.html"/></p>
+
+  <tc:section label="Column Tree">
+    <p>There is a tree in the first column. You can expand and collapse the items.
+      The <code class="language-markup">&lt;tc:columnNode/></code> tag can contain several tags for a tree.
+      In this example, it's a <code class="language-markup">&lt;tc:treeIndent/></code> to intent the
+      single entries of the tree.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetTreeController.solarTree}"
+    var="solarObject" showRoot="true" showRootJunction="true">
+  &lt;tc:columnNode label="Name">
+    &lt;tc:treeIndent/>
+    &lt;tc:out value="\#{solarObject.userObject.name}"/>
+    ...</code></pre>
+    <tc:sheet value="#{sheetTreeController.solarTree}" var="solarObject" showRoot="true" showRootJunction="true">
+      <tc:columnNode label="Name">
+        <tc:treeIndent/>
+        <tc:out value="#{solarObject.userObject.name}"/>
+      </tc:columnNode>
+      <tc:column label="Central Body">
+        <tc:out value="#{solarObject.userObject.orbit}"/>
+      </tc:column>
+      <tc:column label="Distance" sortable="true">
+        <tc:out value="#{solarObject.userObject.distance}"/>
+      </tc:column>
+      <tc:column label="Period" sortable="true">
+        <tc:out value="#{solarObject.userObject.period}"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{solarObject.userObject.discoverer}"/>
+      </tc:column>
+      <tc:column label="Year" sortable="true">
+        <tc:out value="#{solarObject.userObject.discoverYear}"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/80-editable/sheet-editable.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/80-editable/sheet-editable.xhtml
new file mode 100644
index 0000000..31f2a5c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/80-editable/sheet-editable.xhtml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.sheet_editable} &lt;tc:sheet>"/>
+  <p>Not only a sheet can be used to display data, it may also contain inputfields to edit the data.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/></p>
+
+  <tc:section label="Editable Sheet" id="basics">
+    <p>In this sheet you can edit the data of solar objects. Press the 'Submit' button to see the results in the
+      'Result' section.</p>
+    <tc:sheet id="editSheet" value="#{sheetController.solarList}" var="object" rows="5">
+      <tc:column label="Name">
+        <tc:in id="nameCol" value="#{object.name}" labelLayout="skip">
+          <f:ajax execute="nameCol" render="resultSheet"/>
+        </tc:in>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:in value="#{object.orbit}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:in value="#{object.period}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:in value="#{object.discoverer}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:date value="#{object.discoverYear}" converter="#{sheetController.yearConverter}" labelLayout="skip"/>
+      </tc:column>
+    </tc:sheet>
+    <tc:button label="Submit">
+      <f:ajax execute="editSheet" render="resultSheet"/>
+    </tc:button>
+  </tc:section>
+
+  <tc:section label="Result">
+    <p>The sheet in this section is for verifying the submitted data.</p>
+    <tc:sheet id="resultSheet" var="object" value="#{sheetController.solarList}">
+      <tc:column label="Name">
+        <tc:out value="#{object.name}"/>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:out value="#{object.orbit}"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:out value="#{object.period}"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{object.discoverer}"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:out value="#{object.discoverYear}"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/sheet.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/sheet.xhtml
new file mode 100644
index 0000000..d91c186
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/sheet.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet} &lt;tc:sheet>"/>
+  <p>A <code class="language-markup">&lt;tc:sheet/></code> tag can contain any number of
+    <code class="language-markup">&lt;tc:column/></code> tags.
+    The <code class="language-markup">&lt;tc:column/></code> tag is a container, which may contain
+    outputfields, labels, progress bars or even tab groups.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/></p>
+
+  <tc:section label="Basics">
+    <p>Two attributes should be recognized in a sheet.
+      The data of the sheet is set in the <code>value</code> attribute.
+      The variablename of a single entry is set by the <code>var</code> attribute, which can be used in the
+      <code class="language-markup">&lt;tc:column/></code> tags.
+      In this example, also the <code>rows</code> attribute is set. So only four rows are shown at a time.</p>
+    <p>In most cases, you should set <code class="language-markup">labelLayout="skip"</code> for
+      components which have usually a label.
+      Otherwise those components have a negative affect on the proportion of the sheet.<br/>
+      For components with a label the attribute <code class="language-css">margin-bottom</code> is set.
+      The margin is add to the height of a row.</p>
+    <pre><code class="language-markup">&lt;tc:sheet value="\#{sheetController.solarList}"
+    var="solarobject" rows="4">
+  &lt;tc:column label="Name">
+    &lt;tc:out value="\#{solarobject.name}" labelLayout="skip"/>
+      ...</code></pre>
+    <tc:sheet id="s1" value="#{sheetController.solarList}" var="object" rows="4">
+      <tc:style maxHeight="500px"/>
+      <tc:column label="Name">
+        <tc:out value="#{object.name}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Orbit">
+        <tc:out value="#{object.orbit}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Period (Days)">
+        <tc:out value="#{object.period}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Discoverer">
+        <tc:out value="#{object.discoverer}" labelLayout="skip"/>
+      </tc:column>
+      <tc:column label="Year">
+        <tc:out value="#{object.discoverYear}" labelLayout="skip"/>
+      </tc:column>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/x-sheet-nested.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/x-sheet-nested.xhtml
new file mode 100644
index 0000000..23d6871
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/080-sheet/x-sheet-nested.xhtml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet}"/>
+
+    <tc:sheet value="#{demo.solarList}" id="sheet"
+              columns="*;2*" var="luminary">
+      <tc:column label="#{demoBundle.solarArrayName}" id="name" sortable="true" markup="#{luminary.markup}">
+        <tc:out value="#{luminary.name}" id="t_name"/>
+      </tc:column>
+      <tc:column label="Chemical Composition" id="cc" sortable="false" resizable="false"
+                 tip="Chemical Composition of the Crust">
+
+          <tc:sheet value="#{luminary.chemicalComposition}" id="nested"
+                    columns="*;*" var="element">
+              <tc:column label="Element" id="element" sortable="false" resizable="false">
+                  <tc:out value="#{element.name}"/>
+              </tc:column>
+              <tc:column label="Ratio" id="ratio" sortable="false" resizable="false">
+                  <tc:out value="#{element.ratio}"/>
+              </tc:column>
+          </tc:sheet>
+
+      </tc:column>
+    </tc:sheet>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/00-command/tree-command-types.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/00-command/tree-command-types.xhtml
new file mode 100644
index 0000000..6ee337e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/00-command/tree-command-types.xhtml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.tree_command_types} &lt;tc:treeCommand>"/>
+  <p>The <code class="language-markup">&lt;tc:treeCommand/></code> tag can be added to a
+    <code class="language-markup">&lt;tc:treeNode/></code> tag.
+    The command can be used to execute an action or a link.</p>
+  <p><tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+              link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeCommand.html"/></p>
+
+  <tc:section label="Example">
+    <p>In this example, the nodes with children are displayed as
+      <code class="language-markup">&lt;tc:treeLabel/></code>. The leafs are
+      <code class="language-markup">&lt;tc:treeCommand/></code>.
+      Like the parent nodes suggest,
+      the entries in 'Actions' run an action with the <code>action</code> attribute.
+      And the entries in 'Links' are links to an external website using the <code>link</code> attribute.</p>
+    <tc:tree value="#{treeCommandTypesController.sample}" var="node">
+      <tc:treeNode>
+        <tc:treeIndent showJunctions="false"/>
+        <tc:treeLabel value="#{node.name}" rendered="#{node.childCount > 0}"/>
+        <tc:treeCommand label="#{node.name}" rendered="#{node.childCount == 0}"
+                        action="#{treeCommandTypesController.increaseActionCount(node.action)}" link="#{node.url}"/>
+      </tc:treeNode>
+    </tc:tree>
+
+    <tc:out label="Action 1 Count" value="#{treeCommandTypesController.actionOneCount}"/>
+    <tc:out label="Action 2 Count" value="#{treeCommandTypesController.actionTwoCount}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/tree-select.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/tree-select.test.js
new file mode 100644
index 0000000..579db02
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/tree-select.test.js
@@ -0,0 +1,320 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("single: select Music, select Mathematics", function(assert) {
+  assert.expect(4);
+  var done = assert.async(4);
+  var $music = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:3\\:select");
+  var $mathematics = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:9\\:select");
+  var $output = jQueryFrame("#page\\:mainForm\\:selectedNodesOutput span");
+  var $selectableNone = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:0");
+  var $selectableSingle = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:1");
+
+  $selectableNone.prop("checked", true).trigger("change");
+
+  waitForAjax(function() {
+    return jQueryFrame(".tobago-treeSelect input").length == 0;
+  }, function() {
+    assert.equal(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+    $selectableSingle = jQueryFrame($selectableSingle.selector);
+    $selectableSingle.prop("checked", true).trigger("change");
+
+    waitForAjax(function() {
+      return jQueryFrame(".tobago-treeSelect input").length > 0;
+    }, function() {
+      assert.notEqual(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+      $music = jQueryFrame($music.selector);
+      $music.prop("checked", true).trigger("change");
+
+      waitForAjax(function() {
+        $output = jQueryFrame($output.selector);
+        return $output.text() == "Music"
+      }, function() {
+        $output = jQueryFrame($output.selector);
+        assert.equal($output.text(), "Music");
+
+        $mathematics = jQueryFrame($mathematics.selector);
+        $mathematics.prop("checked", true).trigger("change");
+
+        waitForAjax(function() {
+          $output = jQueryFrame($output.selector);
+          return $output.text() == "Mathematics"
+        }, function() {
+          $output = jQueryFrame($output.selector);
+          assert.equal($output.text(), "Mathematics");
+          done();
+        });
+        done();
+      });
+      done();
+    });
+    done();
+  });
+});
+
+QUnit.test("singleLeafOnly: select Classic, select Mathematics", function(assert) {
+  assert.expect(4);
+  var done = assert.async(4);
+  var $classic = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:4\\:select");
+  var $mathematics = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:9\\:select");
+  var $output = jQueryFrame("#page\\:mainForm\\:selectedNodesOutput span");
+  var $selectableNone = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:0");
+  var $selectableSingleLeafOnly = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:2");
+
+  $selectableNone.prop("checked", true).trigger("change");
+
+  waitForAjax(function() {
+    return jQueryFrame(".tobago-treeSelect input").length == 0;
+  }, function() {
+    assert.equal(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+    $selectableSingleLeafOnly = jQueryFrame($selectableSingleLeafOnly.selector);
+    $selectableSingleLeafOnly.prop("checked", true).trigger("change");
+
+    waitForAjax(function() {
+      return jQueryFrame(".tobago-treeSelect input").length > 0;
+    }, function() {
+      assert.notEqual(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+      $classic = jQueryFrame($classic.selector);
+      $classic.prop("checked", true).trigger("change");
+
+      waitForAjax(function() {
+        $output = jQueryFrame($output.selector);
+        return $output.text() == "Classic"
+      }, function() {
+        $output = jQueryFrame($output.selector);
+        assert.equal($output.text(), "Classic");
+
+        $mathematics = jQueryFrame($mathematics.selector);
+        $mathematics.prop("checked", true).trigger("change");
+
+        waitForAjax(function() {
+          $output = jQueryFrame($output.selector);
+          return $output.text() == "Mathematics"
+        }, function() {
+          $output = jQueryFrame($output.selector);
+          assert.equal($output.text(), "Mathematics");
+          done();
+        });
+        done();
+      });
+      done();
+    });
+    done();
+  });
+});
+
+QUnit.test("multi: select Music, select Mathematics, deselect Music", function(assert) {
+  assert.expect(4);
+  var done = assert.async(4);
+  var $music = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:3\\:select");
+  var $mathematics = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:9\\:select");
+  var $output = jQueryFrame("#page\\:mainForm\\:selectedNodesOutput span");
+  var $selectableNone = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:0");
+  var $selectableMulti = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:3");
+
+  $selectableNone.prop("checked", true).trigger("change");
+
+  waitForAjax(function() {
+    return jQueryFrame(".tobago-treeSelect input").length == 0;
+  }, function() {
+    assert.equal(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+    $selectableMulti = jQueryFrame($selectableMulti.selector);
+    $selectableMulti.prop("checked", true).trigger("change");
+
+    waitForAjax(function() {
+      return jQueryFrame(".tobago-treeSelect input").length > 0;
+    }, function() {
+      assert.notEqual(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+      $music = jQueryFrame($music.selector);
+      $music.prop("checked", true).trigger("change");
+
+      waitForAjax(function() {
+        $output = jQueryFrame($output.selector);
+        return $output.text() == "Music"
+      }, function() {
+        $output = jQueryFrame($output.selector);
+        assert.equal($output.text(), "Music");
+
+        $mathematics = jQueryFrame($mathematics.selector);
+        $mathematics.prop("checked", true).trigger("change");
+
+        waitForAjax(function() {
+          $output = jQueryFrame($output.selector);
+          return $output.text() == "Music, Mathematics"
+        }, function() {
+          $output = jQueryFrame($output.selector);
+          assert.equal($output.text(), "Music, Mathematics");
+
+          $music = jQueryFrame($music.selector);
+          $music.prop("checked", false).trigger("change");
+
+          waitForAjax(function() {
+            $output = jQueryFrame($output.selector);
+            return $output.text() == "Mathematics"
+          }, function() {
+            $output = jQueryFrame($output.selector);
+            assert.equal($output.text(), "Mathematics");
+            done();
+          });
+          done();
+        });
+        done();
+      });
+      done();
+    });
+    done();
+  });
+});
+
+QUnit.test("multiLeafOnly: select Classic, select Mathematics, deselect Classic", function(assert) {
+  assert.expect(4);
+  var done = assert.async(4);
+  var $classic = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:4\\:select");
+  var $mathematics = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:9\\:select");
+  var $output = jQueryFrame("#page\\:mainForm\\:selectedNodesOutput span");
+  var $selectableNone = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:0");
+  var $selectableMultiLeafOnly = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:4");
+
+  $selectableNone.prop("checked", true).trigger("change");
+
+  waitForAjax(function() {
+    return jQueryFrame(".tobago-treeSelect input").length == 0;
+  }, function() {
+    assert.equal(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+    $selectableMultiLeafOnly = jQueryFrame($selectableMultiLeafOnly.selector);
+    $selectableMultiLeafOnly.prop("checked", true).trigger("change");
+
+    waitForAjax(function() {
+      return jQueryFrame(".tobago-treeSelect input").length > 0;
+    }, function() {
+      assert.notEqual(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+      $classic = jQueryFrame($classic.selector);
+      $classic.prop("checked", true).trigger("change");
+
+      waitForAjax(function() {
+        $output = jQueryFrame($output.selector);
+        return $output.text() == "Classic"
+      }, function() {
+        $output = jQueryFrame($output.selector);
+        assert.equal($output.text(), "Classic");
+
+        $mathematics = jQueryFrame($mathematics.selector);
+        $mathematics.prop("checked", true).trigger("change");
+
+        waitForAjax(function() {
+          $output = jQueryFrame($output.selector);
+          return $output.text() == "Classic, Mathematics"
+        }, function() {
+          $output = jQueryFrame($output.selector);
+          assert.equal($output.text(), "Classic, Mathematics");
+
+          $classic = jQueryFrame($classic.selector);
+          $classic.prop("checked", false).trigger("change");
+
+          waitForAjax(function() {
+            $output = jQueryFrame($output.selector);
+            return $output.text() == "Mathematics"
+          }, function() {
+            $output = jQueryFrame($output.selector);
+            assert.equal($output.text(), "Mathematics");
+            done();
+          });
+          done();
+        });
+        done();
+      });
+      done();
+    });
+    done();
+  });
+});
+
+QUnit.test("multiCascade: select Music, select Mathematics, deselect Classic", function(assert) {
+  assert.expect(4);
+  var done = assert.async(4);
+  var $music = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:3\\:select");
+  var $classic = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:4\\:select");
+  var $pop = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:5\\:select");
+  var $world = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:6\\:select");
+  var $mathematics = jQueryFrame("#page\\:mainForm\\:categoriesTree\\:9\\:select");
+  var $output = jQueryFrame("#page\\:mainForm\\:selectedNodesOutput span");
+  var $selectableNone = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:0");
+  var $selectableMultiCascade = jQueryFrame("#page\\:mainForm\\:selectable\\:\\:5");
+
+  $selectableNone.prop("checked", true).trigger("change");
+
+  waitForAjax(function() {
+    return jQueryFrame(".tobago-treeSelect input").length == 0;
+  }, function() {
+    assert.equal(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+    $selectableMultiCascade = jQueryFrame($selectableMultiCascade.selector);
+    $selectableMultiCascade.prop("checked", true).trigger("change");
+
+    waitForAjax(function() {
+      return jQueryFrame(".tobago-treeSelect input").length > 0;
+    }, function() {
+      assert.notEqual(jQueryFrame(".tobago-treeSelect input").length, 0);
+
+      $music = jQueryFrame($music.selector);
+      $music.prop("checked", true).trigger("change");
+
+      waitForAjax(function() {
+        $output = jQueryFrame($output.selector);
+        return $output.text() == "Music, Classic, Pop, World"
+      }, function() {
+        $output = jQueryFrame($output.selector);
+        assert.equal($output.text(), "Music, Classic, Pop, World");
+
+        $mathematics = jQueryFrame($mathematics.selector);
+        $mathematics.prop("checked", true).trigger("change");
+
+        waitForAjax(function() {
+          $output = jQueryFrame($output.selector);
+          return $output.text() == "Music, Classic, Pop, World, Mathematics"
+        }, function() {
+          $output = jQueryFrame($output.selector);
+          assert.equal($output.text(), "Music, Classic, Pop, World, Mathematics");
+
+          $classic = jQueryFrame($classic.selector);
+          $classic.prop("checked", false).trigger("change");
+
+          waitForAjax(function() {
+            $output = jQueryFrame($output.selector);
+            return $output.text() == "Music, Pop, World, Mathematics"
+          }, function() {
+            $output = jQueryFrame($output.selector);
+            assert.equal($output.text(), "Music, Pop, World, Mathematics");
+            done();
+          });
+          done();
+        });
+        done();
+      });
+      done();
+    });
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/tree-select.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/tree-select.xhtml
new file mode 100644
index 0000000..ea0f527
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/01-select/tree-select.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.tree_select} &lt;treeSelect>"/>
+  <p>The <code class="language-markup">&lt;tc:treeSelect/></code> tag can be used instead of
+    <code class="language-markup">&lt;treeLabel/></code> to add radio buttons or checkboxes in front of the nodes.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:tree/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tree.html"/>
+    |
+    <tc:link label="&lt;tc:treeSelect/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeSelect.html"/></p>
+
+  <tc:section label="Example">
+    <p>The <code class="language-markup">&lt;tc:tree/></code> tag must use the <code>selectable</code> attribute.
+      The value of the attribute in this example can be changed by the radio buttons in the contentbox on the right.</p>
+    <tc:panel id="examplePanel">
+      <tc:flexLayout columns="*;auto">
+        <tc:tree id="categoriesTree" value="#{treeSelectController.sample}" var="node" showRoot="true"
+                 selectable="#{treeSelectController.selectable}">
+          <tc:treeNode>
+            <tc:treeIndent/>
+            <tc:treeSelect id="select" label="#{node.userObject.name}" value="#{node.userObject.selected}">
+              <f:ajax render=":::selectedNodesOutput"/>
+            </tc:treeSelect>
+          </tc:treeNode>
+        </tc:tree>
+        <tc:panel>
+          <tc:box label="selectable">
+            <tc:selectOneRadio id="selectable" value="#{treeSelectController.selectable}">
+              <f:ajax render="examplePanel selectedNodesOutput"/>
+              <tc:selectItem itemLabel="none" itemValue="none"/>
+              <tc:selectItem itemLabel="single" itemValue="single"/>
+              <tc:selectItem itemLabel="singleLeafOnly" itemValue="singleLeafOnly"/>
+              <tc:selectItem itemLabel="multi" itemValue="multi"/>
+              <tc:selectItem itemLabel="multiLeafOnly" itemValue="multiLeafOnly"/>
+              <tc:selectItem itemLabel="multiCascade" itemValue="multiCascade"/>
+            </tc:selectOneRadio>
+          </tc:box>
+        </tc:panel>
+      </tc:flexLayout>
+    </tc:panel>
+    <tc:out id="selectedNodesOutput" label="Selected Nodes" value="#{treeSelectController.selectedNodes}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/02-editor/tree-editor.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/02-editor/tree-editor.xhtml
new file mode 100644
index 0000000..0456b32
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/02-editor/tree-editor.xhtml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.tree_editor}"/>
+  <p>This is an example, to show how to write an editor for a tree.
+  Some commands are using popups and AJAX.</p>
+
+  <tc:buttons>
+    <tc:button label="New" omit="true" image="fa-file-o">
+      <tc:operation name="show" for="createPopup"/>
+    </tc:button>
+    <tc:button label="Delete" image="fa-trash-o" action="#{treeEditorController.delete}"/>
+    <tc:button label="Rename" omit="true" image="fa-edit">
+      <tc:operation name="show" for="renamePopup"/>
+    </tc:button>
+    <tc:button label="Cut" action="#{treeEditorController.cut}" image="fa-cut"/>
+    <tc:button label="Copy" action="#{treeEditorController.copy}" image="fa-copy"/>
+    <tc:button label="Paste" action="#{treeEditorController.paste}" image="fa-paste"/>
+    <tc:button label="Up" action="#{treeEditorController.moveUp}" image="fa-level-up"/>
+    <tc:button label="Down" action="#{treeEditorController.moveDown}" image="fa-level-down"/>
+    <tc:button label="Reset" action="#{treeEditorController.reset}" image="fa-undo"/>
+  </tc:buttons>
+
+  <tc:popup id="createPopup" collapsedMode="hidden">
+    <tc:box label="New">
+      <tc:in label="New Name" id="newName" value="#{treeEditorController.name}"/>
+      <tc:button label="OK" action="#{treeEditorController.create}">
+        <f:ajax render=":::tree" execute=":::tree newName"/>
+        <tc:operation name="hide" for="createPopup"/>
+      </tc:button>
+      <tc:button label="Cancel" omit="true">
+        <tc:operation name="hide" for="createPopup"/>
+      </tc:button>
+    </tc:box>
+  </tc:popup>
+
+  <tc:popup id="renamePopup" collapsedMode="hidden">
+    <tc:box label="Rename">
+      <tc:in label="New Name" id="renameName" value="#{treeEditorController.name}"/>
+      <tc:button label="OK" action="#{treeEditorController.rename}">
+        <f:ajax render=":::tree" execute=":::tree renameName"/>
+        <tc:operation name="hide" for="renamePopup"/>
+      </tc:button>
+      <tc:button label="Cancel" omit="true">
+        <tc:operation name="hide" for="renamePopup"/>
+      </tc:button>
+    </tc:box>
+  </tc:popup>
+
+  <tc:tree value="#{treeEditorController.categoryTree}" var="node" id="tree"
+           showRoot="true" showRootJunction="true" selectable="single">
+    <tc:treeNode>
+      <tc:treeIndent showJunctions="true"/>
+      <tc:treeSelect label="#{node.userObject.name}" value="#{node.userObject.selected}"/>
+    </tc:treeNode>
+  </tc:tree>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/03-menu/tree-menu.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/03-menu/tree-menu.xhtml
new file mode 100644
index 0000000..98fdd2e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/03-menu/tree-menu.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.tree_menu} &lt;tc:treeMenu>"/>
+  <p>The <code class="language-markup">&lt;tc:treeMenu/></code> tag can be used for menus
+    like the one on the left side of this site.
+    The nodes have to be <code class="language-markup">&lt;tc:treeCommand/></code> tags,
+    otherwise <code class="language-markup">&lt;tc:treeMenu/></code> behaves the same way as
+    <code class="language-markup">&lt;tc:tree/></code>.
+    <code class="language-markup">&lt;tc:treeMenu/></code> set indents automatically for
+    <code class="language-markup">&lt;tc:treeCommand/></code>.
+    So the <code class="language-markup">&lt;tc:treeIndent/></code> tag is not needed.</p>
+  <tc:link label="Tag Library Documentation:" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeMenu.html"/>
+
+  <tc:section label="Example">
+    <p>In this example, a click on a node has no effect.</p>
+    <pre><code class="language-markup">&lt;tc:treeMenu value="\#{treeController.sample}" ...></code></pre>
+    <tc:treeMenu value="#{treeController.sample}" var="node">
+      <tc:treeNode>
+        <tc:treeCommand label="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:treeMenu>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/04-listbox/tree-listbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/04-listbox/tree-listbox.xhtml
new file mode 100644
index 0000000..0f22085
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/04-listbox/tree-listbox.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.tree_listbox} &lt;tc:treeListbox>"/>
+  <p>The <code class="language-markup">&lt;tc:treeListbox/></code> can be used to replace a classic
+    <code class="language-markup">&lt;tc:tree/></code>. It displays the tree as a number of lists.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeListbox.html"/>
+
+  <tc:section label="Example">
+    <pre><code class="language-markup">&lt;tc:treeListbox value="\#{treeController.sample}" ...></code></pre>
+    <tc:treeListbox value="#{treeController.sample}" var="node">
+      <tc:treeNode>
+        <tc:treeIndent/>
+        <tc:treeLabel value="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:treeListbox>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/tree.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/tree.xhtml
new file mode 100644
index 0000000..cff886c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/090-tree/tree.xhtml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.tree} &lt;tc:tree>"/>
+  <p>A classic tree can created with the <code class="language-markup">&lt;tc:tree/></code> tag.
+    Tobago knows two more presentations of a tree. As a <tc:link label="menu" link="03-menu/tree-menu.xhtml"/>
+    and as a <tc:link label="list" link="04-listbox/tree-listbox.xhtml"/>.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:tree/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/tree.html"/>
+    |
+    <tc:link label="&lt;tc:treeNode/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeNode.html"/>
+    |
+    <tc:link label="&lt;tc:treeIndent/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeIndent.html"/>
+    |
+    <tc:link label="&lt;tc:treeLabel/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeLabel.html"/>
+    |
+    <tc:link label="&lt;tc:treeIcon/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/treeIcon.html"/></p>
+
+  <tc:section label="Basics">
+    <p>The tree tag has two attributes, <code>value</code> and <code>var</code>. The attribute <code>value</code>
+      contain a DefaultMutableTreeNode, which represent the tree.
+      The <code>var</code> attribute is the name of the variable, to get specific content.</p>
+    <pre><code class="language-markup">&lt;tc:tree value="#{treeController.sample}" var="node"></code></pre>
+    <p>In every tree, a <code class="language-markup">&lt;tc:treeNode/></code> has to be added.
+      A <code class="language-markup">&lt;tc:treeNode/></code> can contain several tags to describe the node.
+      In this example, two tags are used.<br/>
+      The <code class="language-markup">&lt;tc:treeIndent/></code> tag, which add an indent besides a node
+      and <code class="language-markup">&lt;tc:treeLabel value="\#{node.userObject.name}"/></code>, which contain the
+      String for the label. Notice that 'node' is the value of the <code>var</code> attribute from the tree tag.</p>
+    <tc:tree value="#{treeController.sample}" var="node">
+      <tc:treeNode>
+        <tc:treeIndent/>
+        <tc:treeLabel value="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:tree>
+  </tc:section>
+
+  <tc:section label="Icon">
+    <p>An icon can be added to a node with
+      <code class="language-markup">&lt;tc:treeIcon value="image/feather.png"/></code>.
+      In this case, the targeted image is 'feather.png'. It is displayed for closed nodes.
+      For opened nodes, an image with a '-open'-suffix is used, here it's 'feather-open.png'.
+      For the leafs of the tree, an image with a '-leaf'-suffix is used. Therefor 'feather-leaf.png' is the displayed
+      image.</p>
+    <tc:tree value="#{treeController.sample}" var="node">
+      <tc:treeNode>
+        <tc:treeIndent/>
+        <tc:treeIcon value="#{request.contextPath}/image/feather.png" />
+        <tc:treeIcon value="fa-file-o"
+                     closed="fa-folder-o" open="fa-folder-open-o" />
+        <tc:treeLabel value="#{node.userObject.name}" />
+      </tc:treeNode>
+    </tc:tree>
+  </tc:section>
+
+  <tc:section label="Additional Attributes">
+    <p>In this example, some boolean attributes can be activated and deactivated in the right boxes for
+      <code class="language-markup">&lt;tc:tree/></code> and
+      <code class="language-markup">&lt;tc:treeIndent/></code>.</p>
+    <tc:panel id="p1">
+      <tc:flexLayout columns="*;auto">
+        <tc:tree value="#{treeController.sample}" var="node" showRoot="#{treeController.treeShowRoot}"
+                 showRootJunction="#{treeController.treeShowRootJunction}">
+          <tc:treeNode>
+            <tc:treeIndent rendered="#{treeController.treeIndentRendered}"
+                           showJunctions="#{treeController.treeIndentShowJunction}"/>
+            <tc:treeLabel value="#{node.userObject.name}"/>
+          </tc:treeNode>
+        </tc:tree>
+        <tc:panel>
+          <tc:box label="&lt;tc:tree/>">
+            <tc:selectBooleanCheckbox label="showRoot" value="#{treeController.treeShowRoot}">
+              <f:ajax render="p1"/>
+            </tc:selectBooleanCheckbox>
+            <tc:selectBooleanCheckbox label="showRootJunction" value="#{treeController.treeShowRootJunction}">
+              <f:ajax render="p1"/>
+            </tc:selectBooleanCheckbox>
+          </tc:box>
+          <tc:box label="&lt;tc:treeIndent/>">
+            <tc:selectBooleanCheckbox label="rendered" value="#{treeController.treeIndentRendered}">
+              <f:ajax render="p1"/>
+            </tc:selectBooleanCheckbox>
+            <tc:selectBooleanCheckbox label="showJunction" value="#{treeController.treeIndentShowJunction}">
+              <f:ajax render="p1"/>
+            </tc:selectBooleanCheckbox>
+          </tc:box>
+        </tc:panel>
+      </tc:flexLayout>
+    </tc:panel>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/100-upload/upload.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/100-upload/upload.xhtml
new file mode 100644
index 0000000..0d76f62
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/100-upload/upload.xhtml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.upload} &lt;tc:file/&gt;"/>
+  <p>The <code class="language-markup">&lt;tc:file/></code> create a textfield with a choose directory button on the
+    right.</p>
+  <p>To load up files to the server for JSF 2.0 and 2.1 you will need to add a multipart-config entry to the
+    FacesServlet in the <code>web.xml</code> file. Since JSF 2.2 this is not required.</p>
+  <p>Here you can configure some more general information.</p>
+    <pre><code class="language-markup">&lt;multipart-config>
+  &lt;max-file-size>20848820&lt;/max-file-size>
+  &lt;max-request-size>418018841&lt;/max-request-size>
+  &lt;location>/tmp&lt;/location>
+  &lt;file-size-threshold>1048576&lt;/file-size-threshold>
+&lt;/multipart-config></code></pre>
+  <p>If using Servlet API 3.1 you may call <code>part.getSubmittedFileName()</code>, for 3.0 you may use the Utility
+    <code>org.apache.myfaces.tobago.internal.util.PartUtils.getSubmittedFileName(part)</code>
+    to access to filename of the upload.</p>
+  <tc:link label="Tag Library Documentation" image="image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/file.html"/>
+
+  <tc:section id="s1" label="Basics">
+    <pre><code class="language-markup">&lt;tc:file label="Upload" value="\#{uploadController.file1}"/></code></pre>
+    <tc:file label="Upload" value="#{uploadController.fileBasic}"/>
+    <tc:file label="Read Only" readonly="true" value="#{uploadController.fileBasic}"/>
+    <tc:file label="Disabled" disabled="true" value="#{uploadController.fileBasic}"/>
+    <tc:button label="Submit" action="#{uploadController.uploadBasic}"/>
+  </tc:section>
+
+  <tc:section id="s2" label="Content type">
+    <p>You can filter files using the <code class="language-markup">&lt;tc:validateFileItem/></code> tag within
+      the <code class="language-markup">&lt;tc:file/></code>.
+      In the following example only images and PDF files are excepted.</p>
+    <tc:file label="Upload image" value="#{uploadController.fileContentType}">
+      <tc:validateFileItem contentType="image/*,application/pdf"/>
+    </tc:file>
+    <tc:button label="Submit" action="#{uploadController.uploadContentType}"/>
+  </tc:section>
+
+  <tc:section id="upload-multi" label="Multiple files">
+    <p>
+      You can upload multiple files in one selection and request.
+      Use the <code class="language-markup">multiple="true"</code> attribute.
+    </p>
+    <tc:file label="Multiple" value="#{uploadController.fileMulti}" multiple="true"/>
+    <tc:button label="Submit" action="#{uploadController.uploadMulti}"/>
+  </tc:section>
+
+  <tc:section id="s3" label="Ajax">
+
+    <p>Ajax can be activated by adding <code class="language-markup">&lt;f:ajax/></code>
+      to the <code class="language-markup">&lt;tc:file/></code> tag.</p>
+    <p>The Ajax feature of file upload currently works with JSF 2.2 only!</p>
+
+    <tc:file label="Ajax" value="#{uploadController.fileAjax}">
+      <f:ajax listener="#{uploadController.uploadAjax}" render="s3 :page:messages"/>
+    </tc:file>
+
+    <tc:section id="s4" label="Uploaded Files">
+      <tc:sheet value="#{uploadController.uploadItems}" var="item" columns="*;*;*">
+        <tc:column label="Name">
+          <tc:out value="#{item.name}"/>
+        </tc:column>
+        <tc:column label="Type">
+          <tc:out value="#{item.type}"/>
+        </tc:column>
+        <tc:column label="Size">
+          <tc:out value="#{item.size}"/>
+        </tc:column>
+      </tc:sheet>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/00-tinymce/tinymce.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/00-tinymce/tinymce.js
new file mode 100644
index 0000000..a8d5b9a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/00-tinymce/tinymce.js
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function ($) {
+
+  $.widget("demo.htmlEditor", {
+
+    _create: function () {
+
+      if (typeof tinymce == "undefined") {
+        console.error("No TinyMCE installation found!");
+        return;
+      }
+      tinymce.init({
+        selector: Tobago.Utils.escapeClientId(this.element.attr("id")),
+        init_instance_callback: function (editor) {
+          var textarea = jQuery(Tobago.Utils.escapeClientId(editor.id));
+          var editorContainer = jQuery(editor.editorContainer);
+
+          editorContainer.css("height", textarea.css("height"));
+          editorContainer.css("width", textarea.css("width"));
+          editorContainer.css("left", textarea.css("left"));
+          editorContainer.css("top", textarea.css("top"));
+          editorContainer.css("position", textarea.css("position"));
+
+          var text = jQuery(editor.contentAreaContainer);
+
+          // set estimated height
+          text.outerHeight(text.outerHeight - 107);
+
+          // compute the real height a bit later, (didn't found an event to listen, so using setTimeout)
+          setTimeout(function () {
+            var heightDelta = 2; // extra pixel...
+            editorContainer.find(".mce-toolbar, .mce-statusbar").each(function () {
+              heightDelta += jQuery(this).outerHeight();
+            });
+            text.outerHeight(text.outerHeight() - heightDelta);
+          }, 50);
+        },
+        setup: function(ed) {
+          ed.on('init', function(args) {
+            // TinyMCE v4
+            if (jQuery("#" + args.target.id.replace(/:/g, "\\:")).attr('readonly') == "readonly") {
+              console.debug("RO!");
+              tinymce.get(args.target.id).setMode('readonly');
+            }
+          });
+        }
+      });
+    },
+
+    _destroy: function () {
+      // tbd: instance.destroy()
+    }
+
+  });
+
+}(jQuery));
+
+Tobago.registerListener(function () {
+  jQuery("[data-html-editor]").htmlEditor();
+}, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/00-tinymce/tinymce.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/00-tinymce/tinymce.xhtml
new file mode 100644
index 0000000..0e7120f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/00-tinymce/tinymce.xhtml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.tinymce}"/>
+  <tc:script
+          file="#{request.contextPath}/content/20-component/110-wysiwyg/00-tinymce/tinymce/js/tinymce/tinymce.min.js"/>
+  <tc:script file="#{request.contextPath}/content/20-component/110-wysiwyg/00-tinymce/tinymce.js"/>
+
+  <tc:section label="Installation">
+    <p>Download <tc:link link="http://www.tinymce.com/" target="_blank" label="TinyMCE"/>
+      and unpack the ZIP file directly beside this XHTML-file.</p>
+  </tc:section>
+
+  <tc:section label="Editor">
+    <p>This facelet contains two <code class="language-markup">&lt;tc:script/></code> tags,
+      one for the TinyMCE and the other for the integration in this application.
+      The <code class="language-markup">&lt;tc:textarea/></code> contain
+      <code class="language-markup">&lt;tc:dataAttribute name="html-editor" value=""/></code>,
+      to mark this textarea to be used as rich text editor. The rest does the script: tinymce.js</p>
+
+    <tc:box id="sourceCodeBox" label="tinymce.js" collapsed="true" collapsedMode="hidden">
+      <f:facet name="bar">
+        <tc:buttons>
+          <tc:button label="show" omit="true">
+            <tc:operation name="show" for="sourceCodeBox"/>
+          </tc:button>
+          <tc:button label="hide" omit="true">
+            <tc:operation name="hide" for="sourceCodeBox"/>
+          </tc:button>
+        </tc:buttons>
+      </f:facet>
+      <pre><code class="language-javascript"><tc:out value="#{tinyMceController.source}"/></code></pre>
+    </tc:box>
+
+    <tc:out markup="strong" rendered="#{not tinyMceController.editorAvailable}"
+            value="The TinyMCE is not installed! Using the fallback textarea."/>
+
+    <tc:textarea value="#{tinyMceController.text}">
+      <tc:style width="400px" height="300px"/>
+      <tc:dataAttribute name="html-editor" value=""/>
+    </tc:textarea>
+    <tc:button label="Submit"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/01-ckeditor/ckeditor.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/01-ckeditor/ckeditor.xhtml
new file mode 100644
index 0000000..7ad7372
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/01-ckeditor/ckeditor.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.ckeditor}"/>
+  <tc:script file="content/20-component/110-wysiwyg/01-ckeditor/ckeditor/ckeditor.js"/>
+  <tc:script file="content/20-component/110-wysiwyg/01-ckeditor/demo-ckeditor.js"/>
+
+  <tc:section label="Installation">
+    <p>Download <tc:link link="http://ckeditor.com/" target="_blank" label="CKEditor"/>
+      and unpack the ZIP file directly beside this XHTML-file.
+      Then restart this application (this is needed, because the resource manager needs to scan the content).</p>
+  </tc:section>
+
+  <tc:section label="Editor">
+    <p>This facelet contains two <code class="language-markup">&lt;tc:script/></code> tags,
+      one for the CKEditor and the other for the integration in this application.
+      The <code class="language-markup">&lt;tc:textarea/></code> contain
+      <code class="language-markup">&lt;tc:dataAttribute name="html-editor" value=""/></code>,
+      to mark this textarea to be used as rich text editor. The rest does the script: demo-ckeditor.js</p>
+
+    <tc:button label="show/hide" action="#{ckeditorController.switchCollapsed}"/>
+    <tc:box label="demo-ckeditor.js" collapsed="#{ckeditorController.collapsed}">
+      <pre><code class="language-javascript"><tc:out value="#{ckeditorController.source}"/></code></pre>
+    </tc:box>
+
+    <tc:out markup="strong" rendered="#{not ckeditorController.editorAvailable}"
+            value="The CKEditor is not installed! Using the fallback textarea."/>
+
+    <tc:out markup="strong" rendered="#{ckeditorController.contentSecurityPolicyMode == 'ON'}"
+            value="CSP is ON! CKEditor is not compatible with CSP!"/>
+
+    <tc:textarea value="#{ckeditorController.text}">
+      <tc:style width="400px" height="300px"/>
+      <tc:dataAttribute name="html-editor" value=""/>
+    </tc:textarea>
+    <tc:button label="Submit"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/01-ckeditor/demo-ckeditor.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/01-ckeditor/demo-ckeditor.js
new file mode 100644
index 0000000..451ed1c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/01-ckeditor/demo-ckeditor.js
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* global initialzing script for CSS */
+CKEDITOR.on("instanceLoaded", function(event) {
+  var textarea = jQuery(Tobago.Utils.escapeClientId(event.editor.name));
+  var editor = textarea.next();
+  editor.css("height", textarea.css("height"));
+  editor.css("width", textarea.css("width"));
+  editor.css("left", textarea.css("left"));
+  editor.css("top", textarea.css("top"));
+  editor.css("position", textarea.css("position"));
+  var child = editor.children(".cke_inner");
+  child.css("height", "100%");
+  var top = child.children(".cke_top");
+  var bottom = child.children(".cke_bottom");
+  var content = child.children(".cke_contents");
+  content.css("height", child.innerHeight() - top.outerHeight() - bottom.outerHeight());
+});
+
+(function ($) {
+
+  $.widget("demo.htmlEditor", {
+
+    _create: function () {
+
+      var id = this.element.attr("id");
+      CKEDITOR.replace(id);
+    },
+
+    _destroy: function () {
+      // tbd: instance.destory()
+    }
+
+  });
+
+}(jQuery));
+
+Tobago.registerListener(function() {
+  jQuery("[data-html-editor]").htmlEditor();
+}, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/wysiwyg-editor.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/wysiwyg-editor.xhtml
new file mode 100644
index 0000000..bb627dd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/110-wysiwyg/wysiwyg-editor.xhtml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.wysiwyg_editor}"/>
+  <tc:section label="A WYSIWYG HTML Editor">
+    <p>
+      You can embed HTML editor in Tobago easily,
+      but there is no HTML editor component in Tobago.
+      The reason is, there a many web-based editors in the web available, with different
+      licences, different features (and different bugs).
+    </p>
+    <p>
+      So Tobago should not implement it's own HTML editor.
+      But Tobago may embed an existing editor. Such an editor needs to comply with these requirements:
+    </p>
+    <ul>
+      <li>License must be compatible with the Apache 2.0 license.</li>
+      <li>Should be easy to integrate.</li>
+      <li>Should have many features.</li>
+      <li>Should have few bugs.</li>
+      <li>Must be compatible to CSP (Content Security Policy).</li>
+    </ul>
+    <p>
+      Unfortunately we didn't found the <em>perfect</em> editor.
+    </p>
+    <p>
+      But that doesn't matter. You can choice you favorite editor and integrate it in your application.
+      In this application there are two editors embedded as an example.
+    </p>
+    <ul>
+      <li><tc:link label="TinyMCE" link="https://www.tinymce.com/" target="_blank"/></li>
+      Is using LGPL license.
+      <li><tc:link label="CKEditor" link="http://ckeditor.com/" target="_blank"/></li>
+      Doesn't work with CSP activated.
+      There is an issue #8584 in the
+      <tc:link link="https://dev.ckeditor.com/ticket/8584" target="_blank" label="issue tracker"/>
+      of the project.
+    </ul>
+  </tc:section>
+  <tc:section label="About Security">
+    <p>
+      The application should be protected against invalid or malicious HTML content.
+      If the application uses an HTML editor in the browser, an attacker is able to modify the clean code
+      and submit malicious code.
+      That must be checked on server side!
+    </p>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/component.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/component.xhtml
new file mode 100644
index 0000000..0b1efcd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/20-component/component.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.component}"/>
+  <p>The different components of Tobago are shown in this section.
+    There are some classic components like inputfields, outputfields or radiobuttons
+    and some more advanced like a popup dialog, a tabgroup or a sheet.</p>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/content-validation.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/content-validation.test.js
new file mode 100644
index 0000000..b3c1160
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/content-validation.test.js
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Required: Submit without content.", function (assert) {
+  assert.expect(2);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $textarea = jQueryFrame("#page\\:mainForm\\:required\\:textarea\\:\\:field");
+  var textareaValue = $textarea.val();
+  var $submit = jQueryFrame("#page\\:mainForm\\:required\\:submit");
+
+  $textarea.val("");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    assert.equal($textarea.val(), textareaValue);
+    done();
+  });
+});
+
+QUnit.test("Required: Submit with content.", function (assert) {
+  assert.expect(2);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $textarea = jQueryFrame("#page\\:mainForm\\:required\\:textarea\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:required\\:submit");
+
+  $textarea.val("some content");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    $textarea = jQueryFrame($textarea.selector);
+    assert.equal($messages.length, 0);
+    assert.equal($textarea.val(), "some content");
+    done();
+  });
+});
+
+QUnit.test("Validate Length: Submit single character.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:validateLength\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:validateLength\\:submit");
+
+  $in.val("a");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Validate Length: Submit two character.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:validateLength\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:validateLength\\:submit");
+
+  $in.val("ab");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 0);
+    done();
+  });
+});
+
+QUnit.test("Validate Range: Submit no number.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:validateRange\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:validateRange\\:submit");
+
+  $in.val("no number");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Validate Range: Submit number '2' which is out of range.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:validateRange\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:validateRange\\:submit");
+
+  $in.val("2");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Validate Range: Submit number '78' which is out of range.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:validateRange\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:validateRange\\:submit");
+
+  $in.val("78");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Validate Range: Submit number '64' which is within the range.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:validateRange\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:validateRange\\:submit");
+
+  $in.val("64");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 0);
+    done();
+  });
+});
+
+QUnit.test("Regex Validation: Submit 'T' which violates the pattern.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:regexValidation\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:regexValidation\\:submit");
+
+  $in.val("T");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Regex Validation: Submit '3' which violates the pattern.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:regexValidation\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:regexValidation\\:submit");
+
+  $in.val("3");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Regex Validation: Submit 'T3' which is accepted.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:regexValidation\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:regexValidation\\:submit");
+
+  $in.val("T3");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 0);
+    done();
+  });
+});
+
+QUnit.test("Custom Validator: Submit rejected string.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:customValidator\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:customValidator\\:submit");
+
+  $in.val("java");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Custom Validator: Submit accepted string.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:customValidator\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:customValidator\\:submit");
+
+  $in.val("tobago");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 0);
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/content-validation.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/content-validation.xhtml
new file mode 100644
index 0000000..5c76e29
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/00/content-validation.xhtml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.validation}"/>
+  <p>There are several ways to validate the content of a component. In general input components have the option
+    for validation. In the following sections, the different kinds von validation are explained.</p>
+
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:sheet/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/sheet.html"/>
+    |
+    <tc:link label="&lt;tc:column/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/column.html"/></p>
+
+  <tc:section label="Required">
+    <p>A simple way of validation is the <code>required</code> attribute in some input components.
+      The text area must not empty if the submit button is pressed. Otherwise a error message is displayed.</p>
+    <pre><code class="language-markup">&lt;tc:textarea label="Text Area" required="true"/></code></pre>
+    <tc:form id="required">
+      <tc:textarea id="textarea" label="Text Area" required="true"/>
+      <tc:button id="submit" label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Validate Length">
+    <p>The length of a value can be validated by the <code class="language-markup">&lt;f:validateLength/></code> tag.
+      Length means the number of characters.
+      In this example, the given string must have at least two characters and maximal four characters.</p>
+    <p>Please note, an empty string will not be validated.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Input">
+  &lt;f:validateLength minimum="2" maximum="4"/>
+&lt;/tc:in></code></pre>
+    <tc:form id="validateLength">
+      <tc:in id="in" label="Text">
+        <f:validateLength minimum="2" maximum="4"/>
+      </tc:in>
+      <tc:button id="submit" label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Validate Range">
+    <p>The range of a number can be validated via <code class="language-markup">&lt;f:validateLongRange/></code>
+      or - for floating point numbers - <code class="language-markup">&lt;f:validateDoubleRange/></code>.
+      In the following inputfield numbers from 3 to 77 can be added.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Number" markup="number">
+  &lt;f:validateLongRange minimum="3" maximum="77"/>
+&lt;/tc:in></code></pre>
+    <tc:form id="validateRange">
+      <tc:in id="in" label="Number" markup="number">
+        <f:validateLongRange minimum="3" maximum="77"/>
+      </tc:in>
+      <tc:button id="submit" label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Regex Validation">
+    <p>A value can be validated against a regex patter via the
+      <code class="language-markup">&lt;f:validateRegex/></code> tag.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Letter &amp; Number" >
+  &lt;f:validateRegex pattern="[A-Za-z][0-9]"/>
+&lt;/tc:in></code></pre>
+    <tc:form id="regexValidation">
+      <p>The value in the field must be a word character combined with a number. For example 'T3'.</p>
+      <tc:in id="in" label="Letter &amp; Number">
+        <f:validateRegex pattern="[A-Za-z][0-9]"/>
+      </tc:in>
+      <tc:button id="submit" label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Custom Validator">
+    <p>It's also possible to add custom validators using the <code>validator</code> attribute of an input component.
+      In this case, only the string 'Tobago' (uppercase/lowercase ignored) is accepted.</p>
+    <tc:form id="customValidator">
+      <tc:in id="in" label="Text" validator="#{validationController.customValidator}"/>
+      <tc:button id="submit" label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Two Field Validation">
+    <p>A validator check the password against the confirmation field.
+      To get access to the confirmation field from the validator a binding with the <code>binding</code> attribute
+      and the <code class="language-markup">&lt;f:attribute/></code> tag is created.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Password" value="qwe" validator="\#{validationController.passwordValidator}">
+  &lt;f:attribute name="confirmationField" value="\#{confirmBinding}"/>
+&lt;/tc:in>
+&lt;tc:in label="Confirmation" value="asdf" binding="\#{confirmBinding}"/></code></pre>
+    <tc:form>
+      <tc:in label="Password" required="true" validator="#{validationController.passwordValidator}">
+        <f:attribute name="confirmationField" value="#{confirmBinding}"/>
+      </tc:in>
+      <tc:in label="Confirmation" required="true" binding="#{confirmBinding}"/>
+      <tc:button label="Submit"/>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/validation-jsr303.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/validation-jsr303.test.js
new file mode 100644
index 0000000..8964148
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/validation-jsr303.test.js
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Required: Submit without content.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:required\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:required\\:submit");
+
+  $in.val("");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Required: Submit with content.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:required\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:required\\:submit");
+
+  $in.val("some content");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 0);
+    done();
+  });
+});
+
+QUnit.test("Length: Submit single character.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:length\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:length\\:submit");
+
+  $in.val("a");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Length: Submit three characters.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:length\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:length\\:submit");
+
+  $in.val("abc");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 0);
+    done();
+  });
+});
+
+QUnit.test("Length: Submit five characters.", function (assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $in = jQueryFrame("#page\\:mainForm\\:length\\:in\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:length\\:submit");
+
+  $in.val("abcde");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/validation-jsr303.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/validation-jsr303.xhtml
new file mode 100644
index 0000000..10ca3fb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/01/validation-jsr303.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.validation_jsr303}"/>
+  <p>Tobago has JSR 303 Validation support.
+    With it, you can describe the validation in an annotation in the controller.</p>
+
+  <tc:section label="Required">
+    <p>In this example, the input cannot be empty - in other words, it's required.
+      The value in the controller is annotated with <code class="language-java">@NotNull</code>.</p>
+    <pre><code class="language-markup">&lt;tc:in label="Input" value="\#{validationJsr303Controller.required}"/></code></pre>
+    <pre><code class="language-java">@NotNull
+private String required;</code></pre>
+    <tc:form id="required">
+      <tc:in id="in" label="Input (required)" value="#{validationJsr303Controller.required}"/>
+      <tc:button id="submit" label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Length">
+    <p>The length of the given string must be between 2 and 4 characters.</p>
+    <pre><code
+            class="language-markup">&lt;tc:in label="Input" value="\#{validationJsr303Controller.length}"/></code></pre>
+    <pre><code class="language-java">@Size(min = 2, max = 4, message = "Length must be between 2 and 4")
+private String length;</code></pre>
+    <tc:form id="length">
+      <tc:in id="in" label="2 to 4 Character" value="#{validationJsr303Controller.length}"/>
+      <tc:button id="submit" label="Submit"/>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/02/severity.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/02/severity.xhtml
new file mode 100644
index 0000000..34a3dea
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/02/severity.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.severity}"/>
+
+  The validator of each field creates a FacesMessage with the given severity.
+
+  <tc:in label="Fatal" value="something" validator="#{severityController.addFatal}"/>
+  <tc:in label="Error" value="something" validator="#{severityController.addError}"/>
+  <tc:in label="Warn" value="something" validator="#{severityController.addWarn}"/>
+  <tc:in label="Info" value="something" validator="#{severityController.addInfo}"/>
+
+  <tc:button label="Submit" defaultCommand="true"/>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/validation.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/validation.xhtml
new file mode 100644
index 0000000..0b4a83c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/06-validation/validation.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.validation}"/>
+  <p>Content validation of inputfields can be made directly in the facelet
+    with the <code>required</code> attribute and several validation tags.</p>
+  <p>Validation can also be described in the controller via annotations.</p>
+  <p>In the context of validation, you may report errors to the user.
+    The <code class="language-markup">&lt;tc:messages/></code> tag provide different severity levels.
+    Have a look at
+    <tc:link label="#{demoBundle.messages}"
+             link="/faces/content/20-component/020-output/30-messages/messages.xhtml"/>.</p>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/07-conversion/conversion.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/07-conversion/conversion.xhtml
new file mode 100644
index 0000000..fa4a109
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/07-conversion/conversion.xhtml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.conversion}"/>
+  <p>To convert numbers put a <code class="language-markup">&lt;f:convertNumber/></code> tag in an component.</p>
+  <tc:section label="Example">
+    <p>The following examples show the basic functions of the number converter.
+      The given number is in every example:</p>
+    <tc:label value="#{conversionController.amount}"/>
+
+    <tc:section label="Default">
+      <p>By default, grouping is activated and only three digits after the point are shown.
+        Also the value of <code>type</code> is 'number'.</p>
+      <pre><code class="language-markup">&lt;tc:out label="Number"
+    markup="number" value="\#{conversionController.amount}">
+  &lt;f:convertNumber/>
+&lt;/tc:out></code></pre>
+      <tc:out id="o1" label="Number" markup="number" value="#{conversionController.amount}">
+        <f:convertNumber/>
+      </tc:out>
+    </tc:section>
+
+    <tc:section label="Grouping">
+      <p>Grouping is deactivated.</p>
+      <pre><code class="language-markup">&lt;f:convertNumber groupingUsed="false"/></code></pre>
+      <tc:out id="o2" label="Number" markup="number" value="#{conversionController.amount}">
+        <f:convertNumber groupingUsed="false"/>
+      </tc:out>
+    </tc:section>
+
+    <tc:section label="Integer only">
+      <p>Only integer values are shown.</p>
+      <pre><code class="language-markup">&lt;f:convertNumber integerOnly="true"/></code></pre>
+      <tc:out id="o3" label="Number" markup="number" value="#{conversionController.amount}">
+        <f:convertNumber integerOnly="true"/>
+      </tc:out>
+    </tc:section>
+
+    <tc:section label="Minimal Digits">
+      <p>There are at minimum 10 integer digits and 5 digits after the point shown.
+        The given amount is not high enough in both ways. </p>
+      <pre><code class="language-markup">&lt;f:convertNumber minIntegerDigits="10" minFractionDigits="5"/></code></pre>
+      <tc:out id="o4" label="Number" markup="number" value="#{conversionController.amount}">
+        <f:convertNumber minIntegerDigits="10" minFractionDigits="5"/>
+      </tc:out>
+    </tc:section>
+
+    <tc:section label="Maximal Digits">
+      <p>There are maximal 6 integer digits and 2 digits after the point shown.
+        Notice, that the second digit after the point is rounded up.</p>
+      <pre><code class="language-markup">&lt;f:convertNumber maxIntegerDigits="6" maxFractionDigits="2"/></code></pre>
+      <tc:out id="o5" label="Number" markup="number" value="#{conversionController.amount}">
+        <f:convertNumber maxIntegerDigits="6" maxFractionDigits="2"/>
+      </tc:out>
+    </tc:section>
+
+    <tc:section label="Type">
+      <p>The <code>type</code> attribute can have the value 'number' (default), 'currency' and 'percent'.
+        If the type is set to 'currency', a code or a symbol must be set. Have a look at the following examples.</p>
+
+      <tc:section label="Currency Code">
+        <p>The currency code is set to 'EUR'. Also the type must set to 'currency', otherwise the
+          <code>currencyCode</code> attribute has no effect.</p>
+        <pre><code class="language-markup">&lt;f:convertNumber type="currency" currencyCode="EUR"/></code></pre>
+        <tc:out id="i6" label="Number" markup="number" value="#{conversionController.amount}">
+          <f:convertNumber type="currency" currencyCode="EUR"/>
+        </tc:out>
+      </tc:section>
+
+      <tc:section label="Currency Symbol">
+        <p>The currency symbol is set to '€'. Also the type must set to 'currency', otherwise the
+          <code>currencyCode</code> attribute has no effect.</p>
+        <pre><code class="language-markup">&lt;f:convertNumber type="currency" currencySymbol="€"/></code></pre>
+        <tc:out id="i7" label="Number" markup="number" value="#{conversionController.amount}">
+          <f:convertNumber type="currency" currencySymbol="€"/>
+        </tc:out>
+      </tc:section>
+
+      <tc:section label="Percent">
+        <p>The type is set to 'percent'.</p>
+        <pre><code class="language-markup">&lt;f:convertNumber type="percent"/></code></pre>
+        <tc:out id="i8" label="Number" markup="number" value="#{conversionController.amount}">
+          <f:convertNumber type="percent"/>
+        </tc:out>
+      </tc:section>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/form-required.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/form-required.test.js
new file mode 100644
index 0000000..787278a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/form-required.test.js
@@ -0,0 +1,221 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit inner form 1 without violations", function (assert) {
+  assert.expect(3);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm1\\:in\\:\\:field");
+  var $form1SubmitButton = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm1\\:submit");
+
+  $form1InputField.val("Alice");
+  $form1SubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm1\\:in\\:\\:field");
+    var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm1\\:out span");
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+
+    assert.equal($form1InputField.val(), "Alice");
+    assert.equal($form1OutputField.text(), "Alice");
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
+
+QUnit.test("submit inner form 2, violate required field", function (assert) {
+  assert.expect(4);
+  var done = assert.async();
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+  var $form2SubmitButton = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:submit");
+
+  var form2OutputFieldValue = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span").text();
+
+  $form2InputField.val("");
+  assert.equal($form2InputField.val(), "");
+  $form2SubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span");
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+
+    assert.equal($form2InputField.val(), "");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit inner form 2 without violations", function (assert) {
+  assert.expect(4);
+  var done = assert.async();
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+  var $form2SubmitButton = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:submit");
+
+  $form2InputField.val("Bob");
+  assert.equal($form2InputField.val(), "Bob");
+  $form2SubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span");
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+
+    assert.equal($form2InputField.val(), "Bob");
+    assert.equal($form2OutputField.text(), "Bob");
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form, violate both required fields", function (assert) {
+  assert.expect(5);
+  var done = assert.async();
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormSubmitButton = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  var form2OutputFieldValue = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span").text();
+  var outerFormOutputFieldValue = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span").text();
+
+  $form2InputField.val("");
+  $outerFormInputField.val("");
+  $outerFormSubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span");
+    $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+    var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+
+    assert.equal($form2InputField.val(), "");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    assert.equal($alert.length, "2");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form, violate required field in form 2", function (assert) {
+  assert.expect(5);
+  var done = assert.async();
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormSubmitButton = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  var form2OutputFieldValue = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span").text();
+  var outerFormOutputFieldValue = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span").text();
+
+  $form2InputField.val("");
+  $outerFormInputField.val("Charlie");
+  $outerFormSubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span");
+    $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+    var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+
+    assert.equal($form2InputField.val(), "");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "Charlie");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form, violate required field in outer form", function (assert) {
+  assert.expect(5);
+  var done = assert.async();
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormSubmitButton = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  var form2OutputFieldValue = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span").text();
+  var outerFormOutputFieldValue = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span").text();
+
+  $form2InputField.val("Dave");
+  $outerFormInputField.val("");
+  $outerFormSubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span");
+    $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+    var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+
+    assert.equal($form2InputField.val(), "Dave");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form without violations", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm1\\:in\\:\\:field");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormSubmitButton = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  $form1InputField.val("Eve");
+  $form2InputField.val("Frank");
+  $outerFormInputField.val("Grace");
+  $outerFormSubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm1\\:in\\:\\:field");
+    var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm1\\:out span");
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:innerForm2\\:out span");
+    $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+    var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+
+    assert.equal($form1InputField.val(), "Eve");
+    assert.equal($form1OutputField.text(), "Eve");
+    assert.equal($form2InputField.val(), "Frank");
+    assert.equal($form2OutputField.text(), "Frank");
+    assert.equal($outerFormInputField.val(), "Grace");
+    assert.equal($outerFormOutputField.text(), "Grace");
+
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/form-required.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/form-required.xhtml
new file mode 100644
index 0000000..4b4a478
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/10-required/form-required.xhtml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.form_required} &lt;tc:form>"/>
+  <p>If the validation of a form is activated and the actual value of this form is only stored temporarily,
+    the validation is deactivated until the value is definitely stored into the model.</p>
+  <p>For example, if only the value in 'Inner Form 1' is set, the validation of the other forms are turned off.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/form.html"/>
+
+  <tc:section label="Example">
+    <p>Every form in this example is surrounded by a content box.
+      The submit buttons in the inner forms only put the inner value into the model.
+      The submit button in the outer form put all values into the model.
+      The validation for the inner value 2 and for the outer value is activated, both fields are required.</p>
+
+    <pre><code class="language-markup">&lt;tc:box label="Outer Form">
+  &lt;tc:form>
+    &lt;tc:box label="Inner Form 1">
+      &lt;tc:form>
+        &lt;tc:in label="Inner Value 1"/>
+        &lt;tc:out label="Inner Value 1 in Model"/>
+        &lt;tc:button label="Submit"/>
+      &lt;/tc:form>
+    &lt;/tc:box>
+    &lt;tc:box label="Inner Form 2">
+      ...
+    &lt;/tc:box>
+    &lt;tc:separator/>
+    &lt;tc:in label="Outer Value" required="true"/>
+    &lt;tc:out label="Outer Value in Model"/>
+    &lt;tc:button label="Submit"/>
+  &lt;/tc:form>
+&lt;/tc:box></code></pre>
+
+    <tc:box label="Outer Form">
+      <tc:form id="outerForm">
+        <tc:box label="Inner Form 1">
+          <tc:form id="innerForm1">
+            <tc:in id="in" label="Inner Value 1" value="#{formRequiredController.innerValue1}"/>
+            <tc:out id="out" label="Value in Model" value="#{formRequiredController.innerValue1}"/>
+            <tc:button id="submit" label="Submit"/>
+          </tc:form>
+        </tc:box>
+        <tc:box label="Inner Form 2">
+          <tc:form id="innerForm2">
+            <tc:in id="in" label="Inner Value 2" required="true"
+                   value="#{formRequiredController.innerValue2}"/>
+            <tc:out id="out" label="Value in Model" value="#{formRequiredController.innerValue2}"/>
+            <tc:button id="submit" label="Submit"/>
+          </tc:form>
+        </tc:box>
+        <tc:separator/>
+        <tc:in id="in" label="Outer Value" required="true" value="#{formRequiredController.outerValue}"/>
+        <tc:out id="out" label="Value in Model" value="#{formRequiredController.outerValue}"/>
+        <tc:button id="submit" label="Submit"/>
+      </tc:form>
+    </tc:box>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/form-ajax.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/form-ajax.test.js
new file mode 100644
index 0000000..98cd724
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/form-ajax.test.js
@@ -0,0 +1,546 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit inner form 1 without violations", function (assert) {
+  assert.expect(3);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:submit");
+
+  $form1InputField.val("Alice");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    return $form1InputField.val() == "Alice" && $form1OutputField.text() == "Alice";
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+
+    assert.equal($form1InputField.val(), "Alice");
+    assert.equal($form1OutputField.text(), "Alice");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
+
+QUnit.test("submit inner form 2, violate required field", function (assert) {
+  assert.expect(3);
+  var done = assert.async();
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:submit");
+
+  var form2OutputFieldValue = $form2OutputField.text();
+
+  $form2InputField.val("");
+  $button.click();
+
+  waitForAjax(function () {
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    return $form2InputField.val() == "" && $form2OutputField.text() == form2OutputFieldValue;
+  }, function () {
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+
+    assert.equal($form2InputField.val(), "");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit inner form 2 without violations", function (assert) {
+  assert.expect(3);
+  var done = assert.async();
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:submit");
+
+  $form2InputField.val("Bob");
+  $button.click();
+
+  waitForAjax(function () {
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    return $form2InputField.val() == "Bob" && $form2OutputField.text() == "Bob";
+  }, function () {
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+
+    assert.equal($form2InputField.val(), "Bob");
+    assert.equal($form2OutputField.text(), "Bob");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form, violate both required fields", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  var form1OutputFieldValue = $form1OutputField.text();
+  var form2OutputFieldValue = $form2OutputField.text();
+  var outerFormOutputFieldValue = $outerFormOutputField.text();
+
+  $form1InputField.val("Charlie");
+  $form2InputField.val("");
+  $outerFormInputField.val("");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Charlie"
+        && $form1OutputField.text() == form1OutputFieldValue
+        && $form2InputField.val() == ""
+        && $form2OutputField.text() == form2OutputFieldValue
+        && $outerFormInputField.val() == ""
+        && $outerFormOutputField.text() == outerFormOutputFieldValue;
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Charlie");
+    assert.equal($form1OutputField.text(), form1OutputFieldValue);
+    assert.equal($form2InputField.val(), "");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "2");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form, violate required field in form 2", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  var form1OutputFieldValue = $form1OutputField.text();
+  var form2OutputFieldValue = $form2OutputField.text();
+  var outerFormOutputFieldValue = $outerFormOutputField.text();
+
+  $form1InputField.val("Dave");
+  $form2InputField.val("");
+  $outerFormInputField.val("Eve");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Dave"
+        && $form1OutputField.text() == form1OutputFieldValue
+        && $form2InputField.val() == ""
+        && $form2OutputField.text() == form2OutputFieldValue
+        && $outerFormInputField.val() == "Eve"
+        && $outerFormOutputField.text() == outerFormOutputFieldValue;
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Dave");
+    assert.equal($form1OutputField.text(), form1OutputFieldValue);
+    assert.equal($form2InputField.val(), "");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "Eve");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form, violate required field in outer form", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  var form1OutputFieldValue = $form1OutputField.text();
+  var form2OutputFieldValue = $form2OutputField.text();
+  var outerFormOutputFieldValue = $outerFormOutputField.text();
+
+  $form1InputField.val("Frank");
+  $form2InputField.val("Grace");
+  $outerFormInputField.val("");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Frank"
+        && $form1OutputField.text() == form1OutputFieldValue
+        && $form2InputField.val() == "Grace"
+        && $form2OutputField.text() == form2OutputFieldValue
+        && $outerFormInputField.val() == ""
+        && $outerFormOutputField.text() == outerFormOutputFieldValue;
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Frank");
+    assert.equal($form1OutputField.text(), form1OutputFieldValue);
+    assert.equal($form2InputField.val(), "Grace");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer form without violations", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submit");
+
+  $form1InputField.val("Hank");
+  $form2InputField.val("Irene");
+  $outerFormInputField.val("John");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Hank"
+        && $form1OutputField.text() == "Hank"
+        && $form2InputField.val() == "Irene"
+        && $form2OutputField.text() == "Irene"
+        && $outerFormInputField.val() == "John"
+        && $outerFormOutputField.text() == "John";
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Hank");
+    assert.equal($form1OutputField.text(), "Hank");
+    assert.equal($form2InputField.val(), "Irene");
+    assert.equal($form2OutputField.text(), "Irene");
+    assert.equal($outerFormInputField.val(), "John");
+    assert.equal($outerFormOutputField.text(), "John");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
+
+QUnit.test("submit inner forms, violate required field in form 2", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submitInnerForms");
+
+  var form1OutputFieldValue = $form1OutputField.text();
+  var form2OutputFieldValue = $form2OutputField.text();
+  var outerFormOutputFieldValue = $outerFormOutputField.text();
+
+  $form1InputField.val("Kate");
+  $form2InputField.val("");
+  $outerFormInputField.val("Leonard");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Kate"
+    && $form1OutputField.text() == form1OutputFieldValue
+    && $form2InputField.val() == ""
+    && $form2OutputField.text() == form2OutputFieldValue
+    && $outerFormInputField.val() == "Leonard"
+    && $outerFormOutputField.text(), outerFormOutputFieldValue;
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Kate");
+    assert.equal($form1OutputField.text(), form1OutputFieldValue);
+    assert.equal($form2InputField.val(), "");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "Leonard");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit inner forms without violations", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submitInnerForms");
+
+  var outerFormOutputFieldValue = $outerFormOutputField.text();
+
+  $form1InputField.val("Mike");
+  $form2InputField.val("Neil");
+  $outerFormInputField.val("");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Mike"
+        && $form1OutputField.text() == "Mike"
+        && $form2InputField.val() == "Neil"
+        && $form2OutputField.text() == "Neil"
+        && $outerFormInputField.val() == ""
+        && $outerFormOutputField.text() == outerFormOutputFieldValue;
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Mike");
+    assert.equal($form1OutputField.text(), "Mike");
+    assert.equal($form2InputField.val(), "Neil");
+    assert.equal($form2OutputField.text(), "Neil");
+    assert.equal($outerFormInputField.val(), "");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer value, violate required field", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submitOuterValue");
+
+  var form1OutputFieldValue = $form1OutputField.text();
+  var form2OutputFieldValue = $form2OutputField.text();
+  var outerFormOutputFieldValue = $outerFormOutputField.text();
+
+  $form1InputField.val("Oscar");
+  $form2InputField.val("Penny");
+  $outerFormInputField.val("");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Oscar"
+        && $form1OutputField.text() == form1OutputFieldValue
+        && $form2InputField.val() == "Penny"
+        && $form2OutputField.text() == form2OutputFieldValue
+        && $outerFormInputField.val() == ""
+        && $outerFormOutputField.text() == outerFormOutputFieldValue;
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Oscar");
+    assert.equal($form1OutputField.text(), form1OutputFieldValue);
+    assert.equal($form2InputField.val(), "Penny");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "");
+    assert.equal($outerFormOutputField.text(), outerFormOutputFieldValue);
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "1");
+
+    done();
+  });
+});
+
+QUnit.test("submit outer value without violations", function (assert) {
+  assert.expect(7);
+  var done = assert.async();
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:in\\:\\:field");
+  var $form1OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form1\\:out span");
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:in\\:\\:field");
+  var $form2OutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:form2\\:out span");
+  var $outerFormInputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:in\\:\\:field");
+  var $outerFormOutputField = jQueryFrame("#page\\:mainForm\\:outerForm\\:out span");
+
+  var $button = jQueryFrame("#page\\:mainForm\\:outerForm\\:submitOuterValue");
+
+  var form1OutputFieldValue = $form1OutputField.text();
+  var form2OutputFieldValue = $form2OutputField.text();
+
+  $form1InputField.val("Quin");
+  $form2InputField.val("Sue");
+  $outerFormInputField.val("Ted");
+  $button.click();
+
+  waitForAjax(function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+    return $form1InputField.val() == "Quin"
+        && $form1OutputField.text() == form1OutputFieldValue
+        && $form2InputField.val() == "Sue"
+        && $form2OutputField.text() == form2OutputFieldValue
+        && $outerFormInputField.val() == "Ted"
+        && $outerFormOutputField.text() == "Ted";
+  }, function () {
+    $form1InputField = jQueryFrame($form1InputField.selector);
+    $form1OutputField = jQueryFrame($form1OutputField.selector);
+    $form2InputField = jQueryFrame($form2InputField.selector);
+    $form2OutputField = jQueryFrame($form2OutputField.selector);
+    $outerFormInputField = jQueryFrame($outerFormInputField.selector);
+    $outerFormOutputField = jQueryFrame($outerFormOutputField.selector);
+
+    assert.equal($form1InputField.val(), "Quin");
+    assert.equal($form1OutputField.text(), form1OutputFieldValue);
+    assert.equal($form2InputField.val(), "Sue");
+    assert.equal($form2OutputField.text(), form2OutputFieldValue);
+    assert.equal($outerFormInputField.val(), "Ted");
+    assert.equal($outerFormOutputField.text(), "Ted");
+
+    var $alert = jQueryFrame("#page\\:messages .alert-danger label");
+    assert.equal($alert.length, "0");
+
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/form-ajax.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/form-ajax.xhtml
new file mode 100644
index 0000000..0b42037
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/20-ajax/form-ajax.xhtml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.form_ajax} &lt;tc:form>"/>
+  <p>The <code class="language-markup">&lt;f:ajax execute="..." render="..."/></code> tag ignore the
+    <code class="language-markup">&lt;tc:form></code> tag.
+    The form is only used as a naming container.</p>
+
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/form.html"/>
+
+  <tc:section label="Example">
+    <p>The structure of this example is similar to the
+      <tc:link label="#{demoBundle.form_required}" link="../10-required/form-required.xhtml"/> example.
+      Every form in this example is surrounded by a content box.
+      The submit buttons in the inner forms only put the inner value into the model.
+      The submit button in the outer form put all values into the model.
+      The validation for the inner value 2 and for the outer value is activated, both fields are required.</p>
+    <p>There are also two more submit buttons in the outer form.
+      The 'Inner Forms' button submit both values in the inner forms.
+      The 'Outer Value' button only submit the outer value.
+      Please notice, that all buttons use the
+      <code class="language-markup">&lt;f:ajax execute="..." render="..."/></code> tag.</p>
+    <p>Also note, that the <code class="language-markup">&lt;tc:message/></code> tag has to be rerendered
+      to show error messages.</p>
+
+    <pre><code class="language-markup">&lt;tc:box label="Outer Form">
+  &lt;tc:form>
+    &lt;tc:box label="Inner Form 1">
+      &lt;tc:form>
+        &lt;tc:in label="Inner Value 1"/>
+        &lt;tc:out label="Inner Value 1 in Model"/>
+        &lt;tc:button label="Submit">
+          &lt;f:ajax execute="in" render="out :page:messages"/>
+        &lt;/tc:button>
+      &lt;/tc:form>
+    &lt;/tc:box>
+    &lt;tc:box label="Inner Form 2">
+      ...
+    &lt;/tc:box>
+    &lt;tc:separator/>
+    &lt;tc:in label="Outer Value" required="true"/>
+    &lt;tc:out label="Outer Value in Model"/>
+    &lt;tc:button label="Submit">
+      &lt;f:ajax execute="::form1:in ::form2:in in"
+              render="::form1:out ::form2:out out :page:messages"/>
+    &lt;/tc:button>
+    ...
+  &lt;/tc:form>
+&lt;/tc:box></code></pre>
+
+    <tc:box label="Outer Form">
+      <tc:form id="outerForm">
+        <tc:box label="Inner Form 1">
+          <tc:form id="form1">
+            <tc:in id="in" label="Inner Value 1" value="#{formAjaxController.innerValue1}"/>
+            <tc:out id="out" label="Inner Value 1 in Model" value="#{formAjaxController.innerValue1}"/>
+            <tc:button id="submit" label="Submit">
+              <f:ajax execute="in" render="out :page:messages"/>
+            </tc:button>
+          </tc:form>
+        </tc:box>
+        <tc:box label="Inner Form 2">
+          <tc:form id="form2">
+            <tc:in id="in" label="Inner Value 2" required="true"
+                   value="#{formAjaxController.innerValue2}"/>
+            <tc:out id="out" label="Inner Value 2 in Model" value="#{formAjaxController.innerValue2}"/>
+            <tc:button id="submit" label="Submit">
+              <f:ajax execute="in" render="out :page:messages"/>
+            </tc:button>
+          </tc:form>
+        </tc:box>
+        <tc:separator/>
+        <tc:in id="in" label="Outer Value" required="true" value="#{formAjaxController.outerValue}"/>
+        <tc:out id="out" label="Outer Value in Model" value="#{formAjaxController.outerValue}"/>
+        <tc:button id="submit" label="Submit">
+          <f:ajax execute="::form1:in ::form2:in in"
+                  render="::form1:out ::form2:out out :page:messages"/>
+        </tc:button>
+
+        <tc:separator/>
+        Submit only:
+        <tc:buttons>
+          <tc:button id="submitInnerForms" label="Inner Forms">
+            <f:ajax execute="::form1:in ::form2:in"
+                    render="::form1:out ::form2:out :page:messages"/>
+          </tc:button>
+          <tc:button id="submitOuterValue" label="Outer Value">
+            <f:ajax execute="in" render="out :page:messages"/>
+          </tc:button>
+        </tc:buttons>
+      </tc:form>
+    </tc:box>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/form.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/form.test.js
new file mode 100644
index 0000000..d960679
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/form.test.js
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("submit form 1", function (assert) {
+  assert.expect(4);
+  var done = assert.async();
+
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:form1\\:in\\:\\:field");
+  var $form1SubmitButton = jQueryFrame("#page\\:mainForm\\:form1\\:submit");
+
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:form2\\:in\\:\\:field");
+  var $form2OutputFieldValue = jQueryFrame("#page\\:mainForm\\:form2\\:out span").text();
+
+  $form1InputField.val("Oliver");
+  $form2InputField.val("Peter");
+
+  $form1SubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form1InputField = jQueryFrame("#page\\:mainForm\\:form1\\:in\\:\\:field");
+    var $form1OutputField = jQueryFrame("#page\\:mainForm\\:form1\\:out span");
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:form2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:form2\\:out span");
+
+    assert.equal($form1InputField.val(), "Oliver");
+    assert.equal($form1OutputField.text(), "Oliver");
+    assert.equal($form2InputField.val(), "Peter");
+    assert.equal($form2OutputField.text(), $form2OutputFieldValue);
+
+    done();
+  });
+});
+
+QUnit.test("submit form 2", function (assert) {
+  assert.expect(4);
+  var done = assert.async();
+
+  var $form1InputField = jQueryFrame("#page\\:mainForm\\:form1\\:in\\:\\:field");
+  var $form1OutputFieldValue = jQueryFrame("#page\\:mainForm\\:form1\\:out span").text();
+
+  var $form2InputField = jQueryFrame("#page\\:mainForm\\:form2\\:in\\:\\:field");
+  var $form2SubmitButton = jQueryFrame("#page\\:mainForm\\:form2\\:submit");
+
+  $form1InputField.val("Oliver");
+  $form2InputField.val("Peter");
+
+  $form2SubmitButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $form1InputField = jQueryFrame("#page\\:mainForm\\:form1\\:in\\:\\:field");
+    var $form1OutputField = jQueryFrame("#page\\:mainForm\\:form1\\:out span");
+    $form2InputField = jQueryFrame("#page\\:mainForm\\:form2\\:in\\:\\:field");
+    var $form2OutputField = jQueryFrame("#page\\:mainForm\\:form2\\:out span");
+
+    assert.equal($form1InputField.val(), "Oliver");
+    assert.equal($form1OutputField.text(), $form1OutputFieldValue);
+    assert.equal($form2InputField.val(), "Peter");
+    assert.equal($form2OutputField.text(), "Peter");
+
+    done();
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/form.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/form.xhtml
new file mode 100644
index 0000000..d4d9d3c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/08-form/form.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.form} &lt;tc:form>"/>
+  <p>Tobago supports nested forms and can treat each form separately.
+    Values can be stored separately into the model, while already filled input elements keep their values (temporarily).
+    Forms are added by the <code class="language-markup">&lt;tc:form/></code> tag.</p>
+  <p>Forms are also relevant for
+    <tc:link label="#{demoBundle.default_command}"
+             link="/faces/content/20-component/040-command/00-default/default-command.xhtml"/>.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/form.html"/>
+
+  <tc:section label="Example">
+    <p>This small example contain two separate forms, each surrounded by a content box.
+      The submit button only update the model in the current form.</p>
+    <pre><code class="language-markup">&lt;tc:box label="Form 1">
+  &lt;tc:form>
+    &lt;tc:in label="Value 1" value="\#{formController.value1}"/>
+    &lt;tc:out label="Value 1 in Model" value="\#{formController.value1}"/>
+    &lt;tc:button label="Submit"/>
+  &lt;/tc:form>
+&lt;/tc:box>
+&lt;tc:box label="Form 2">
+  ...
+&lt;/tc:box></code></pre>
+    <tc:box label="Form 1">
+      <tc:form id="form1">
+        <tc:in id="in" label="Value 1" value="#{formController.value1}"/>
+        <tc:out id="out" label="Value 1 in Model" value="#{formController.value1}"/>
+        <tc:button id="submit" label="Submit"/>
+      </tc:form>
+    </tc:box>
+    <tc:box label="Form 2">
+      <tc:form id="form2">
+        <tc:in id="in" label="Value 2" value="#{formController.value2}"/>
+        <tc:out id="out" label="Value 2 in Model" value="#{formController.value2}"/>
+        <tc:button id="submit" label="Submit"/>
+      </tc:form>
+    </tc:box>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/10-theme/theme.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/10-theme/theme.xhtml
new file mode 100644
index 0000000..570c084
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/10-theme/theme.xhtml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.theme}"/>
+  <p>Tobago supports a big variety of displaying controls, so called designs or themes.</p>
+
+  <tc:section label="Change Theme">
+    <p>Choosing of themes can be application wide, user or group specific.
+      Images and other resources can be theme dependant as well as the application pages can be designed seperatly
+      for each supported theme.</p>
+    <tc:selectOneChoice label="Theme" value="#{themeController.theme}">
+      <f:selectItems value="#{themeController.themeItems}"/>
+    </tc:selectOneChoice>
+    <tc:button label="Submit" action="#{themeController.submit}"/>
+
+    <tc:separator/>
+    <tc:figure>
+      <f:facet name="label">
+        <!-- todo: theme dependent text -->
+        <tc:out id="o1" value="#{demoBundle.theme_photo} (TODO: theme dependent text)"/>
+      </f:facet>
+      <tc:image value="/image/#{tobagoContext.theme.name}/theme-photo.jpg"/>
+    </tc:figure>
+  </tc:section>
+
+  <tc:section label="Configuration">
+    <p>In Tobago it's easy to give an application a well designed look. You can use prepared themes like 'speyside' or
+      'scarborough', just to name two. The only thing you have to do is configure them in the 'tobago-config.xml'.</p>
+
+    <pre><code class="language-markup">...
+&lt;tobago-config>
+  &lt;theme-config>
+    &lt;default-theme>speyside&lt;/default-theme>
+  &lt;/theme-config>
+  &lt;resource-dir>tobago&lt;/resource-dir>
+&lt;/tobago-config>
+...</code></pre>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/12-browser/browser.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/12-browser/browser.xhtml
new file mode 100644
index 0000000..b88c2fc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/12-browser/browser.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.browser}"/>
+  <tc:out escape="false" value="#{demoBundle.browser_text}"/>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/14-locale/locale.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/14-locale/locale.xhtml
new file mode 100644
index 0000000..4f31434
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/14-locale/locale.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.locale} - #{demoBundle.locale_title}"/>
+  <tc:gridLayout rows="80px;auto;auto;auto">
+
+    <tc:out escape="false" value="#{demoBundle.locale_text}"/>
+
+    <tc:selectOneChoice value="#{clientConfigController2.locale}"
+                        label="#{demoBundle.locale}">
+      <f:selectItems value="#{clientConfigController2.localeItems}"/>
+    </tc:selectOneChoice>
+
+    <tc:gridLayout columns="100px;*;100px">
+
+      <tc:image value="image/country.png" width="100px" height="100px"/>
+
+      <tc:panel/>
+
+      <tc:panel>
+        <tc:gridLayout rows="*;auto "/>
+
+        <tc:panel/>
+        <tc:button action="#{clientConfigController2.submit}" label="#{demoBundle.locale_submit}"/>
+      </tc:panel>
+    </tc:gridLayout>
+  </tc:gridLayout>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/10-flow/flow-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/10-flow/flow-layout.xhtml
new file mode 100644
index 0000000..e93582b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/10-flow/flow-layout.xhtml
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.flow_layout} &lt;tc:flowLayout>"/>
+  <p>The flow layout can be used with the <code>&lt;tc:flowLayout/></code> tag.
+    By default, the content is displayed in a flow layout.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/flowLayout.html"/>
+
+  <tc:section label="Basics">
+    <p>The buttons are displayed successively at the same line.
+      Components which doesn't fit in the current line are moved to the next one.
+      Components like an outputfield or a checkbox are displayed in a separate line.</p>
+    <tc:flowLayout>
+      <tc:out id="o1" label="Output" value="Outputvalue"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:selectBooleanCheckbox label="Checkbox"/>
+    </tc:flowLayout>
+  </tc:section>
+
+  <tc:section label="Align: left (default)">
+    <pre><code class="language-markup">&lt;tc:flowLayout textAlign="left"></code></pre>
+    <tc:flowLayout textAlign="left">
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:out id="o2" value="Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text
+      Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text "/>
+    </tc:flowLayout>
+  </tc:section>
+
+  <tc:section label="Align: right">
+    <pre><code class="language-markup">&lt;tc:flowLayout textAlign="right"></code></pre>
+    <tc:flowLayout textAlign="right">
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:out id="o3" value="Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text
+      Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text "/>
+    </tc:flowLayout>
+  </tc:section>
+
+  <tc:section label="Align: center">
+    <pre><code class="language-markup">&lt;tc:flowLayout textAlign="center"></code></pre>
+    <tc:flowLayout textAlign="center">
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:out id="o4" value="Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text
+      Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text "/>
+    </tc:flowLayout>
+  </tc:section>
+
+  <tc:section label="Align: justify">
+    <pre><code class="language-markup">&lt;tc:flowLayout textAlign="justify"></code></pre>
+    <tc:flowLayout textAlign="justify">
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:out id="o5" value="Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text
+      Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text Some Text "/>
+    </tc:flowLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/20-flex/flex-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/20-flex/flex-layout.xhtml
new file mode 100644
index 0000000..d2da150
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/20-flex/flex-layout.xhtml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.flex_layout}  &lt;tc:flexLayout>"/>
+  <p>The flex layout can be used with the <code>&lt;tc:flexLayout/></code> tag.
+    The two most important attributes are <code>columns</code> and <code>rows</code>.
+    If both attributes are set, only <code>rows</code> has an effect.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/flexLayout.html"/>
+
+  <tc:section label="Basics">
+    <p>If no attributes set, the behavior of the flex layout is like a flow layout.</p>
+    <tc:flexLayout>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+    </tc:flexLayout>
+  </tc:section>
+
+  <tc:section label="Columns">
+    <p>In this example, the <code>columns</code> attribute is set to '200px;auto;1*;2*;1*'.
+      This means:</p>
+    <ul>
+      <li>Column 1: Width is always at 200px.</li>
+      <li>Column 2: Width is always the width of the button.</li>
+      <li>The left space is filled with the remaining buttons.
+        The fourth button is twice the size than button three and five.
+      </li>
+    </ul>
+    <tc:flexLayout columns="200px;auto;1*;2*;1*">
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+    </tc:flexLayout>
+  </tc:section>
+
+  <tc:section label="Rows">
+    <p>The <code>rows</code> attribute is set to '100px;auto;1*;2*;1*'. Also, the height of the flex layout is '400px'.
+      This means:</p>
+    <ul>
+      <li>Row 1: Height is always at 100px.</li>
+      <li>Row 2: Height is always the height of the button.</li>
+      <li>The left space is filled with the remaining buttons.
+        The fourth button is twice the size than button three and five.
+      </li>
+    </ul>
+    <tc:flexLayout rows="100px;auto;1*;2*;1*">
+      <tc:style height="400px"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+    </tc:flexLayout>
+  </tc:section>
+
+  <tc:section label="Cascade">
+    <p>You can also put a flex layout within a flex layout. In this case the second row is another flex layout.</p>
+    <tc:flexLayout rows="100px;auto;80px;1*">
+      <tc:style height="400px"/>
+      <tc:button label="Button"/>
+      <tc:flexLayout columns="200px;auto;1*;2*;1*">
+        <tc:button label="Button"/>
+        <tc:button label="Button"/>
+        <tc:button label="Button"/>
+        <tc:button label="Button"/>
+        <tc:button label="Button"/>
+      </tc:flexLayout>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+    </tc:flexLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/30-segment/segment-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/30-segment/segment-layout.xhtml
new file mode 100644
index 0000000..eb73057
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/30-segment/segment-layout.xhtml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.segment_layout}  &lt;tc:segmentLayout>"/>
+  <p>The segment layout is basicly a grid with 12 columns.
+    The number and the proportion of the columns can be set with
+    <code>large</code>, <code>medium</code>, <code>small</code> or <code>extraSmall</code>.
+    Every attribute has a different css class, but the usage is the same.
+    The value is a semicolon separated list of integers, which sum has to be '12'.
+    A value of n will use n columns from the grid.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/segmentLayout.html"/>
+
+  <tc:section label="Basics">
+    <p>This example show a segment layout with four columns and a segment layout with three columns.
+      The numbers are displayed via the <code class="language-markup">&lt;tc:label/></code> tag.
+      The space is set via the <code class="language-markup">&lt;tc:hidden/></code> tag.</p>
+    <tc:section label="4 Columns">
+      <pre><code class="language-markup">&lt;tc:segmentLayout medium="1;6;2;3"></code></pre>
+      <tc:segmentLayout medium="1;6;2;3">
+        <tc:in value="1"/>
+        <tc:in value="2"/>
+        <tc:in value="3"/>
+        <tc:in value="4"/>
+        <tc:hidden/>
+        <tc:in value="5"/>
+      </tc:segmentLayout>
+    </tc:section>
+    <tc:section label="3 Columns">
+      <pre><code class="language-markup">&lt;tc:segmentLayout medium="2;4;6"></code></pre>
+      <tc:segmentLayout medium="2;4;6">
+        <tc:in value="1"/>
+        <tc:in value="2"/>
+        <tc:in value="3"/>
+        <tc:in value="4"/>
+        <tc:hidden/>
+        <tc:in value="5"/>
+      </tc:segmentLayout>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Screen Size">
+    <p>For the different kinds of screen sizes, the segment layout has four attributes:
+      <code>large</code>, <code>medium</code>, <code>small</code> and <code>extraSmall</code>.
+      The first two ones should be used for desktops. The last two should be used for tablets and phones.
+      Notice, that only the screen size matters. So a small browser window on a big screen also reacts with
+      <code>small</code> and <code>extraSmall</code>.</p>
+    <p>In the following example, all attributes are used. If you are on a desktop you can see the different
+      behavior by changing the size of the browser window.</p>
+    <pre><code class="language-markup">&lt;tc:segmentLayout large="2;2;2;2;2;2"
+  medium="3;3;3;3" small="4;4;4" extraSmall="6;6">
+    ...</code></pre>
+
+    <tc:segmentLayout large="2;2;2;2;2;2" medium="3;3;3;3" small="4;4;4" extraSmall="6;6">
+      <tc:in value="1"/>
+      <tc:in value="2"/>
+      <tc:in value="3"/>
+      <tc:in value="4"/>
+      <tc:in value="5"/>
+      <tc:in value="6"/>
+      <tc:in value="7"/>
+      <tc:in value="8"/>
+      <tc:in value="9"/>
+      <tc:in value="10"/>
+      <tc:in value="11"/>
+      <tc:in value="12"/>
+    </tc:segmentLayout>
+
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/40-labeled/labeled-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/40-labeled/labeled-layout.xhtml
new file mode 100644
index 0000000..e89d5d3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/40-labeled/labeled-layout.xhtml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.labeled_layout}"/>
+  <p>For many components, a <code>label</code> attribute is available, which place a label in front
+    of the according component.
+    With the <code>labelLayout</code> you can adjust this label.
+    The following examples use an inputfield to show, how this works.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:in/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/in.html"/>
+    |
+    <tc:link label="&lt;tc:flowLayout/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/flowLayout.html"/>
+    |
+    <tc:link label="&lt;tc:flexLayout/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/flexLayout.html"/>
+    |
+    <tc:link label="&lt;tc:segmentLayout/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/segmentLayout.html"/></p>
+
+  <tc:section label="Basics">
+    <tc:section label="Default value">
+      <p>If the <code>labelLayout</code> is not set, the value is 'flexLeft' by default.</p>
+      <pre><code class="language-markup">&lt;tc:in label="Input"/></code></pre>
+      <tc:in label="Input"/>
+    </tc:section>
+    <tc:section label="No label">
+      <p>The value 'none' has the same effect as just not set the <code>label</code> attribute.</p>
+      <pre><code class="language-markup">&lt;tc:in label="Input" labelLayout="none"/></code></pre>
+      <tc:in label="Input" labelLayout="none"/>
+    </tc:section>
+    <tc:section label="Label on top">
+      <p>The <code>labelLayout</code> is set to 'top'.</p>
+      <pre><code class="language-markup">&lt;tc:in label="Input" labelLayout="top"/></code></pre>
+      <tc:in label="Input" labelLayout="top"/>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.flow_layout}">
+    <pre><code class="language-markup">&lt;tc:in label="Input" labelLayout="flowLeft"/>
+&lt;tc:in label="Input" labelLayout="flowRight"/></code></pre>
+    <tc:in label="Input" labelLayout="flowLeft"/>
+    <tc:in label="Input" labelLayout="flowRight"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.flex_layout}">
+    <pre><code class="language-markup">&lt;tc:in label="Input" labelLayout="flexLeft"/>
+&lt;tc:in label="Input" labelLayout="flexRight"/></code></pre>
+    <tc:in label="Input" labelLayout="flexLeft"/>
+    <tc:in label="Input" labelLayout="flexRight"/>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.segment_layout}">
+    <p>The segment layout is divided in two columns. The right one is three times bigger.
+      The 'segmentLeft' and 'segmentRight' put the label in the left or in the right column.</p>
+    <pre><code class="language-markup">&lt;tc:segmentLayout medium="3;9">
+  &lt;tc:in label="Input" labelLayout="segmentLeft"/>
+  &lt;tc:in label="Input" labelLayout="segmentRight"/>
+&lt;/tc:segmentLayout></code></pre>
+    <tc:segmentLayout medium="3;9">
+      <tc:in label="Input" labelLayout="segmentLeft"/>
+      <tc:in label="Input" labelLayout="segmentRight"/>
+    </tc:segmentLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/50-grid/grid-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/50-grid/grid-layout.xhtml
new file mode 100644
index 0000000..1303857
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/50-grid/grid-layout.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.grid_layout} (deprecated)"/>
+  <p>The GridLayout is deprecated. Take a look at
+    <tc:link label="#{demoBundle.grid_layout}"
+             link="/faces/content/35-deprecated/70-grid-layout/grid-layout.xhtml"/>
+    in the #{demoBundle.deprecated} section.
+  </p>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/layout.xhtml
new file mode 100644
index 0000000..5081e5c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/16-layout/layout.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.layout}"/>
+  <p>Tobago provide several layout options.</p>
+
+  <tc:section label="#{demoBundle.flow_layout}">
+    <tc:flowLayout>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+    </tc:flowLayout>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.flex_layout}">
+    <tc:flexLayout columns="200px;auto;1*;3*;1*">
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+    </tc:flexLayout>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.segment_layout}">
+    <tc:segmentLayout medium="4;4;4">
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+      <tc:button label="Button"/>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.labeled_layout}">
+    <p>For many components, a <code>label</code> attribute is available, which place a label in front
+      of the according component.</p>
+    <tc:in label="Input"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/20-format/format.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/20-format/format.xhtml
new file mode 100644
index 0000000..544d3b0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/20-format/format.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:fn="http://java.sun.com/jsp/jstl/functions">
+  <ui:param name="title" value="#{demoBundle.format}"/>
+  <p>Use the EL functions from <code>tc:format1</code> to <code>tc:format9</code>
+    to replace up to 9 variables in a given internationalized text.
+    This work like in <tc:link label="java.text.MessageFormat"
+                               link="https://docs.oracle.com/javase/6/docs/api/java/text/MessageFormat.html"/>.</p>
+
+  <tc:section label="Format 1">
+    <p>The message format is: "#{demoBundle.format1}"</p>
+    <pre><code class="language-markup">&lt;tc:out value="\#{tc:format1(demoBundle.format1, 695700)}"/></code></pre>
+    <tc:out id="o1" value="#{tc:format1(demoBundle.format1, 695700)}"/>
+  </tc:section>
+
+  <tc:section label="Format 3">
+    <p>The message format is: "#{demoBundle.format3}"</p>
+    <pre><code
+            class="language-markup">&lt;tc:out value="\#{tc:format3(demoBundle.format3, 5800, 15700000, 5000000)}"/></code></pre>
+    <tc:out id="o2" value="#{tc:format3(demoBundle.format3, 5800, 15700000, 5000000)}"/>
+  </tc:section>
+
+  <tc:section label="Format 9">
+    <p>The message format is: "#{demoBundle.format9}"</p>
+    <pre><code
+            class="language-markup">&lt;tc:out value="\#{tc:format9(demoBundle.format9, 0, 1, 2, 3, 4, 5, 6, 7, 8)}"/></code></pre>
+    <tc:out id="o3" value="#{tc:format9(demoBundle.format9, 0, 1, 2, 3, 4, 5, 6, 7, 8)}"/>
+  </tc:section>
+
+  <tc:section label="UpperCase">
+    <p>You may also use the <code>fn:</code> function library for string manipulation.</p>
+    <pre><code class="language-markup">&lt;tc:out value="\#{fn:toUpperCase('uppercase')}"/></code></pre>
+    <tc:out id="o4" value="#{fn:toUpperCase('uppercase')}"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/21-error/error.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/21-error/error.xhtml
new file mode 100644
index 0000000..5e4fb68
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/21-error/error.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+
+  <ui:param name="title" value="Sample Error Scenarios (Todo: is to be optimized) "/>
+
+  <tc:gridLayout rows="35px;35px;35px;35px" columns="100px;*">
+
+    <tc:flowLayout>
+      <tc:span column="2"/>
+      <tc:out
+          value="When using MyFaces or Facelets you have to turn off the exception mechanism of them to use this demo. See in the MyFaces Wiki: "/>
+      <tc:link link="http://wiki.apache.org/myfaces/Handling_Server_Errors" label="Handling Server Errors"/>
+    </tc:flowLayout>
+
+    <tc:button action="#{bestPracticeController.throwException}" label="Application"/>
+    <tc:out
+        value="An exception is thrown in the application. The servlet container forwards to a page defined in the web.xml."/>
+
+    <tc:button action="error-404" label="Not Found"/>
+    <tc:out
+        value="The navigation handler refers to a non existing page. The error code 404 in the web.xml is affected."/>
+
+    <tc:button action="syntax" label="Syntax Error"/>
+    <tc:out value="The navigation handler refers to a page with a syntax error."/>
+
+  </tc:gridLayout>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/21-error/x-error-in-syntax.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/21-error/x-error-in-syntax.xhtml
new file mode 100644
index 0000000..d9f6fb0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/21-error/x-error-in-syntax.xhtml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  this page is syntactically incorrect!
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/23-transition/transition.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/23-transition/transition.xhtml
new file mode 100644
index 0000000..77f15fc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/23-transition/transition.xhtml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <ui:param name="title" value="#{demoBundle.transition}"/>
+  <p>For command components like a link or a button, the <code>transition</code> attribute is available.
+    It shows a loading animation if the site don't respond in a certain amount of time.
+    By default, the value is 'true'.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:link/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/link.html"/>
+    |
+    <tc:link label="&lt;tc:button/>" image="#{request.contextPath}/image/feather-leaf.png" link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/button.html"/></p>
+
+  <tc:section label="Basics">
+    <p>By following one of the links, the site waits five seconds.
+      After that, you will be redirected to another page.</p>
+    <pre><code class="language-markup">&lt;tc:link label="link with transition ON"
+action="\#{transitionController.sleep5sAndRedirect}"/>
+&lt;tc:link label="link with transition OFF" transition="false"
+action="\#{transitionController.sleep5sAndRedirect}"/></code></pre>
+
+    <tc:link label="link with transition ON" action="#{transitionController.sleep5sAndRedirect}"/>
+    <br/>
+    <tc:link label="link with transition OFF" transition="false" action="#{transitionController.sleep5sAndRedirect}"/>
+  </tc:section>
+
+  <tc:section label="Popup">
+    <p>In this example, a popup dialog is shown five seconds after pressing one of the buttons.</p>
+    <tc:popup id="popup">
+      <tc:box label="Info">
+        <p>Button pressed</p>
+        <tc:button label="Close" omit="true">
+          <tc:operation name="hide" for="popup"/>
+        </tc:button>
+      </tc:box>
+    </tc:popup>
+    <tc:button label="Open Popup (transition ON)" action="#{transitionController.sleep5s}">
+      <tc:operation name="show" for="popup"/>
+    </tc:button>
+    <tc:button label="Open Popup (transition OFF)" action="#{transitionController.sleep5s}" transition="false">
+      <tc:operation name="show" for="popup"/>
+    </tc:button>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/23-transition/x-transition-after-sleep.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/23-transition/x-transition-after-sleep.xhtml
new file mode 100644
index 0000000..288d912
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/23-transition/x-transition-after-sleep.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Transition after sleep"/>
+
+  <tc:button label="Back" action="/content/30-concept/23-transition/transition.xhtml"/>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/non-faces-response.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/non-faces-response.xhtml
new file mode 100644
index 0000000..bdd5337
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/non-faces-response.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Non Faces Response (e. g. a download link)"/>
+
+  <tc:segmentLayout large="10;2">
+
+    <tc:out value="A faces request to a non-faces-response. Inside of the Browser."/>
+    <tc:button action="#{bestPracticeController.viewFile(false, true)}" label="View PDF"/>
+
+    <tc:out value="A faces request to a non-faces-response. Outside of the Browser."/>
+    <tc:button action="#{bestPracticeController.viewFile(true, true)}" label="View PDF" transition="false"/>
+
+    <tc:out value="A faces request to a non-faces-response. Inside of the Browser."/>
+    <tc:button action="#{bestPracticeController.viewFile(false, false)}" label="View TXT"/>
+
+    <tc:out value="A faces request to a non-faces-response. Outside of the Browser."/>
+    <tc:button action="#{bestPracticeController.viewFile(true, false)}" label="View TXT" transition="false"/>
+  </tc:segmentLayout>
+
+  Problems:
+  <ul>
+    <li>
+      Is seems there are problems with the first example in Firefox, if it is configured to
+      NOT view PDF inside the browser.
+    </li>
+  </ul>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/x-sample.pdf b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/x-sample.pdf
new file mode 100644
index 0000000..fabc97b
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/x-sample.pdf differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/x-sample.txt b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/x-sample.txt
new file mode 100644
index 0000000..fcbf7bb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/24-non-faces-response/x-sample.txt
@@ -0,0 +1 @@
+Sample TXT
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/25-facelets-as-resources/facelets-as-resources.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/25-facelets-as-resources/facelets-as-resources.xhtml
new file mode 100644
index 0000000..9671077
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/25-facelets-as-resources/facelets-as-resources.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Loading Facelets from JARs"/>
+  <tc:panel>
+    <tc:out value="#{demoBundle.faceletsAsResources_text}"/>
+
+    <tc:box label="This content is included from a JAR.">
+
+      <ui:include src="/data/edit-solar.xhtml"/>
+
+    </tc:box>
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/50-partial/partial.css b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/50-partial/partial.css
new file mode 100644
index 0000000..aba023d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/50-partial/partial.css
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.tobago-out-markup-demoSeconds {
+  font-size: 96px;
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/50-partial/partial.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/50-partial/partial.xhtml
new file mode 100644
index 0000000..26b7f56
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/50-partial/partial.xhtml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <ui:param name="title" value="Partial Update (AJAX)"/>
+  <tc:gridLayout id="parent" rows="20px;200px;*;auto">
+
+    <tc:out value="Demonstration and test of partial reload"/>
+
+    <tc:style file="content/50-partial/partial.css"/>
+
+    <tc:gridLayout columns="1*;1*">
+      <tc:box label="Left panel" id="left">
+        <tc:gridLayout rows="auto;*">
+          <tc:label value="Current seconds on server: "/>
+          <tc:out value="#{partialReloadController.currentDate}" markup="demoSeconds">
+            <f:convertDateTime pattern="ss:SSS"/>
+          </tc:out>
+        </tc:gridLayout>
+      </tc:box>
+      <tc:box label="Right panel" id="right">
+        <tc:gridLayout rows="auto;*">
+          <tc:label value="Current seconds on server: "/>
+          <tc:out value="#{partialReloadController.currentDate}" markup="demoSeconds">
+            <f:convertDateTime pattern="ss:SSS"/>
+          </tc:out>
+        </tc:gridLayout>
+      </tc:box>
+    </tc:gridLayout>
+
+    <tc:flowLayout>
+      <ul>
+        <li>Click on 'Reload Left' button to reload the left panel."</li>
+        <li>Click on 'Reload Right' button to reload the right panel."</li>
+        <li>Or select a option from the selectOneChoise control:"
+          <ul>
+            <li>Select 'Reload parent' to reload both panels parent container"</li>
+            <li>Select 'Reload both' to reload both panels in one request"</li>
+            <li>Select 'Goto prev' to navigate to previous page"</li>
+            <li>Select 'Goto next' to navigate to next page"</li>
+          </ul>
+        </li>
+      </ul>
+    </tc:flowLayout>
+
+    <tc:gridLayout columns="*;205px;*">
+
+      <tc:panel/>
+
+      <tc:gridLayout columns="*;*" rows="auto;auto;auto;auto;auto;auto;auto;auto">
+
+        <tc:button label="Reload left" tip="Reload left side box"
+                   action="#{partialReloadController.reload}">
+          <f:ajax render="left :page:header:headerInfo"/>
+        </tc:button>
+
+        <tc:button label="Reload right" tip="Reload right side box"
+                   action="#{partialReloadController.reload}">
+          <f:ajax render="right :page:header:headerInfo"/>
+        </tc:button>
+
+        <tc:button label="Reload both" tip="Reload both boxes"
+                   action="#{partialReloadController.reload}">
+          <f:ajax render="left right :page:header:headerInfo"/>
+          <tc:span column="2"/>
+        </tc:button>
+
+        <tc:button label="Reload full panel"
+                   tip="Reload the full area inside the outer box"
+                   action="#{partialReloadController.reload}">
+          <f:ajax render="parent :page:header:headerInfo"/>
+          <tc:span column="2"/>
+        </tc:button>
+
+        <tc:button label="Reload both (wait 3 s)"
+                   tip="Reload both boxes, but the server has a delay of 3 seconds"
+                   action="#{partialReloadController.waitAndReload3}">
+          <f:ajax render="left right :page:header:headerInfo"/>
+          <tc:span column="2"/>
+        </tc:button>
+
+        <tc:button label="Reload both (wait 7 s, timeout)"
+                   tip="Reload both boxes, but the server has a delay of 7 seconds, this is more than the default timeout for AJAX"
+                   action="#{partialReloadController.waitAndReload7}">
+          <f:ajax render="left right :page:header:headerInfo"/>
+          <tc:span column="2"/>
+        </tc:button>
+
+        <tc:panel id="navTest">
+          <tc:span column="2"/>
+
+          <tc:selectOneChoice fieldId="navSelect" value="#{partialReloadController.navigateActionValue}"
+                              label="On Change">
+            <f:ajax execute="navTest"
+                    render="navTest :page:header:headerInfo"
+                    listener="#{partialReloadController.navigateAction}"/>
+            <f:selectItem itemLabel="Select action" itemValue=""/>
+            <f:selectItem itemLabel="Reload left" itemValue="left"/>
+            <f:selectItem itemLabel="Reload right" itemValue="right"/>
+            <f:selectItem itemLabel="Reload both" itemValue="both"/>
+            <f:selectItem itemLabel="Reload parent" itemValue="parent"/>
+            <f:selectItem itemLabel="Goto prev" itemValue="prev"/>
+            <f:selectItem itemLabel="Goto next" itemValue="next"/>
+          </tc:selectOneChoice>
+
+        </tc:panel>
+
+        <tc:button label="Error left" tip="Reload left side box, but an exception occures"
+                   action="#{partialReloadController.error}">
+          <f:ajax render="left :page:header:headerInfo"/>
+        </tc:button>
+
+        <tc:button label="Error right" tip="Reload right side box, but an exception occures"
+                   action="#{partialReloadController.error}">
+          <f:ajax render="right :page:header:headerInfo"/>
+        </tc:button>
+
+      </tc:gridLayout>
+
+      <tc:panel/>
+
+    </tc:gridLayout>
+  </tc:gridLayout>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/for-each.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/for-each.test.js
new file mode 100644
index 0000000..224868a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/for-each.test.js
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Add a river and reset.", function (assert) {
+  assert.expect(6);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $name = jQueryFrame("#page\\:mainForm\\:add\\:inName\\:\\:field");
+  var $length = jQueryFrame("#page\\:mainForm\\:add\\:inLength\\:\\:field");
+  var $discharge = jQueryFrame("#page\\:mainForm\\:add\\:inDischarge\\:\\:field");
+  var $add = jQueryFrame("#page\\:mainForm\\:add\\:button");
+  var $reset = jQueryFrame("#page\\:mainForm\\:reset\\:button");
+  var $forEachBoxes = jQueryFrame("#page\\:mainForm\\:forEach .tobago-box");
+  var $uiRepeatSections = jQueryFrame("#page\\:mainForm\\:uiRepeat .tobago-section");
+
+  $reset.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $name = jQueryFrame($name.selector);
+      $length = jQueryFrame($length.selector);
+      $discharge = jQueryFrame($discharge.selector);
+      $add = jQueryFrame($add.selector);
+      $forEachBoxes = jQueryFrame($forEachBoxes.selector);
+      $uiRepeatSections = jQueryFrame($uiRepeatSections.selector);
+
+      assert.equal($forEachBoxes.length, 3);
+      assert.equal($uiRepeatSections.length, 3);
+
+      $name.val("Mississippi");
+      $length.val("6275");
+      $discharge.val("16200");
+      $add.click();
+
+      done();
+    } else if (step == 2) {
+      $reset = jQueryFrame($reset.selector);
+      $forEachBoxes = jQueryFrame($forEachBoxes.selector);
+      $uiRepeatSections = jQueryFrame($uiRepeatSections.selector);
+
+      assert.equal($forEachBoxes.length, 4);
+      assert.equal($uiRepeatSections.length, 4);
+
+      $reset.click();
+
+      done();
+    } else if (step == 3) {
+      $forEachBoxes = jQueryFrame($forEachBoxes.selector);
+      $uiRepeatSections = jQueryFrame($uiRepeatSections.selector);
+
+      assert.equal($forEachBoxes.length, 3);
+      assert.equal($uiRepeatSections.length, 3);
+
+      done();
+    }
+    step++;
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/for-each.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/for-each.xhtml
new file mode 100644
index 0000000..b61a69e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/51-for-each/for-each.xhtml
@@ -0,0 +1,81 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:c="http://java.sun.com/jsp/jstl/core">
+  <ui:param name="title" value="#{demoBundle.for_each} &lt;c:forEach> &lt;ui:repeat>"/>
+  <p>Generating content with a loop can be done
+    with the <code class="language-markup">&lt;c:forEach/></code> tag and
+    with the <code class="language-markup">&lt;ui:repeat/></code> tag.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;c:forEach/>"
+             link="http://docs.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/c/forEach.html"/>
+    |
+    <tc:link label="&lt;ui:repeat/>"
+             link="http://docs.oracle.com/javaee/6/javaserverfaces/2.0/docs/pdldocs/facelets/ui/repeat.html"/></p>
+
+  <tc:section label="Example">
+    <p>The following example show three rivers with their length and average dischage by default.</p>
+
+    <tc:section label="New River">
+      <p>You can add a new river to the list
+        or reset the list to the default value of 'Nile', 'Amazon' and 'Yangtze'.</p>
+      <tc:form id="add">
+        <tc:in id="inName" label="Name" value="#{forEachController.name}" required="true"/>
+        <tc:in id="inLength" label="Length (km)" value="#{forEachController.length}" required="true" markup="number"/>
+        <tc:in id="inDischarge" label="Discharge (m³/s)" value="#{forEachController.discharge}" required="true"/>
+        <tc:button id="button" label="Add" action="#{forEachController.addNewRiver}" defaultCommand="true"/>
+      </tc:form>
+      <tc:form id="reset">
+        <tc:button id="button" label="Reset" action="#{forEachController.reset}"/>
+      </tc:form>
+    </tc:section>
+
+    <tc:section id="forEach" label="For Each">
+      <p>The rivers are displayed as <code class="language-markup">&lt;tc:box/></code>
+        tags withing a <code class="language-markup">&lt;tc:segmentLayout/></code>.</p>
+    <pre><code class="language-markup">&lt;tc:segmentLayout medium="6;6">
+  &lt;c:forEach items="\#{forEachController.rivers}" var="river">
+    &lt;tc:box label="\#{river.name}">
+      ...</code></pre>
+      <tc:segmentLayout medium="6;6">
+        <c:forEach items="#{forEachController.rivers}" var="river">
+          <tc:box label="#{river.name}">
+            <tc:out label="Length" value="#{river.length} km" markup="number"/>
+            <tc:out label="Discharge" value="#{river.discharge} m³/s" markup="number"/>
+          </tc:box>
+        </c:forEach>
+      </tc:segmentLayout>
+    </tc:section>
+
+    <tc:section id="uiRepeat" label="UI:Repeat">
+      <p>In this example, the each data of a river is put in a <code class="language-markup">&lt;tc:section/></code></p>
+    <pre><code class="language-markup">&lt;ui:repeat value="\#{forEachController.rivers}" var="river">
+  &lt;tc:section label="\#{river.name}">
+    ...</code></pre>
+      <ui:repeat value="#{forEachController.rivers}" var="river">
+        <tc:section label="#{river.name}">
+          <tc:out label="Length" value="#{river.length} km" markup="number"/>
+          <tc:out label="Discharge" value="#{river.discharge} m³/s" markup="number"/>
+        </tc:section>
+      </ui:repeat>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.test.js
new file mode 100644
index 0000000..00deee4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.test.js
@@ -0,0 +1,408 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Simple Collapsible Box: show -> hide transition", function (assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $show = jQueryFrame("#page\\:mainForm\\:controller\\:show");
+  var $hide = jQueryFrame("#page\\:mainForm\\:controller\\:hide");
+  var $content = jQueryFrame("#page\\:mainForm\\:controller\\:content");
+
+  $show.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $hide = jQueryFrame($hide.selector);
+      $content = jQueryFrame($content.selector);
+
+      assert.equal($content.length, 1);
+      $hide.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $content = jQueryFrame($content.selector);
+
+      assert.equal($content.length, 0);
+
+      step++;
+      done();
+    }
+  });
+});
+
+QUnit.test("Simple Collapsible Box: hide -> show transition", function (assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $show = jQueryFrame("#page\\:mainForm\\:controller\\:show");
+  var $hide = jQueryFrame("#page\\:mainForm\\:controller\\:hide");
+  var $content = jQueryFrame("#page\\:mainForm\\:controller\\:content");
+
+  $hide.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $show = jQueryFrame($show.selector);
+      $content = jQueryFrame($content.selector);
+
+      assert.equal($content.length, 0);
+      $show.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $content = jQueryFrame($content.selector);
+
+      assert.equal($content.length, 1);
+
+      step++;
+      done();
+    }
+  });
+});
+
+QUnit.test("Full Server Request: open both boxes", function (assert) {
+  assert.expect(4);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $show1 = jQueryFrame("#page\\:mainForm\\:server\\:show1");
+  var $show2 = jQueryFrame("#page\\:mainForm\\:server\\:show2");
+  var $content1 = jQueryFrame("#page\\:mainForm\\:server\\:content1");
+  var $content2 = jQueryFrame("#page\\:mainForm\\:server\\:content2");
+  var content2Length = $content2.length;
+
+  $show1.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $show2 = jQueryFrame($show2.selector);
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 1);
+      assert.equal($content2.length, content2Length);
+      $show2.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 1);
+      assert.equal($content2.length, 1);
+
+      step++;
+      done();
+    }
+  });
+});
+
+QUnit.test("Full Server Request: open box 1, close box 2", function (assert) {
+  assert.expect(4);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $show1 = jQueryFrame("#page\\:mainForm\\:server\\:show1");
+  var $hide2 = jQueryFrame("#page\\:mainForm\\:server\\:hide2");
+  var $content1 = jQueryFrame("#page\\:mainForm\\:server\\:content1");
+  var $content2 = jQueryFrame("#page\\:mainForm\\:server\\:content2");
+  var content2Length = $content2.length;
+
+  $show1.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $hide2 = jQueryFrame($hide2.selector);
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 1);
+      assert.equal($content2.length, content2Length);
+      $hide2.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 1);
+      assert.equal($content2.length, 0);
+
+      step++;
+      done();
+    }
+  });
+});
+
+QUnit.test("Full Server Request: close box 1, open box 2", function (assert) {
+  assert.expect(4);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $hide1 = jQueryFrame("#page\\:mainForm\\:server\\:hide1");
+  var $show2 = jQueryFrame("#page\\:mainForm\\:server\\:show2");
+  var $content1 = jQueryFrame("#page\\:mainForm\\:server\\:content1");
+  var $content2 = jQueryFrame("#page\\:mainForm\\:server\\:content2");
+  var content2Length = $content2.length;
+
+  $hide1.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $show2 = jQueryFrame($show2.selector);
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 0);
+      assert.equal($content2.length, content2Length);
+      $show2.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 0);
+      assert.equal($content2.length, 1);
+
+      step++;
+      done();
+    }
+  });
+});
+
+QUnit.test("Full Server Request: close both boxes", function (assert) {
+  assert.expect(4);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $hide1 = jQueryFrame("#page\\:mainForm\\:server\\:hide1");
+  var $hide2 = jQueryFrame("#page\\:mainForm\\:server\\:hide2");
+  var $content1 = jQueryFrame("#page\\:mainForm\\:server\\:content1");
+  var $content2 = jQueryFrame("#page\\:mainForm\\:server\\:content2");
+  var content2Length = $content2.length;
+
+  $hide1.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $hide2 = jQueryFrame($hide2.selector);
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 0);
+      assert.equal($content2.length, content2Length);
+      $hide2.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $content1 = jQueryFrame($content1.selector);
+      $content2 = jQueryFrame($content2.selector);
+
+      assert.equal($content1.length, 0);
+      assert.equal($content2.length, 0);
+
+      step++;
+      done();
+    }
+  });
+});
+
+QUnit.test("Client Sided: show -> hide transition", function (assert) {
+  assert.expect(2);
+
+  var $show = jQueryFrame("#page\\:mainForm\\:client\\:showNoRequestBox");
+  var $hide = jQueryFrame("#page\\:mainForm\\:client\\:hideNoRequestBox");
+  var $box = jQueryFrame("#page\\:mainForm\\:client\\:noRequestBox");
+
+  $show.click();
+  assert.equal($box.hasClass("tobago-collapsed"), false);
+
+  $hide.click();
+  assert.equal($box.hasClass("tobago-collapsed"), true);
+});
+
+QUnit.test("Client Sided: hide -> show transition", function (assert) {
+  assert.expect(2);
+
+  var $show = jQueryFrame("#page\\:mainForm\\:client\\:showNoRequestBox");
+  var $hide = jQueryFrame("#page\\:mainForm\\:client\\:hideNoRequestBox");
+  var $box = jQueryFrame("#page\\:mainForm\\:client\\:noRequestBox");
+
+  $hide.click();
+  assert.equal($box.hasClass("tobago-collapsed"), true);
+
+  $show.click();
+  assert.equal($box.hasClass("tobago-collapsed"), false);
+});
+
+QUnit.test("Client Sided: hide content and submit empty string", function (assert) {
+  assert.expect(2);
+  var done = assert.async();
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $show = jQueryFrame("#page\\:mainForm\\:client\\:showNoRequestBox");
+  var $hide = jQueryFrame("#page\\:mainForm\\:client\\:hideNoRequestBox");
+  var $box = jQueryFrame("#page\\:mainForm\\:client\\:noRequestBox");
+  var $in = jQueryFrame("#page\\:mainForm\\:client\\:inNoRequestBox\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:client\\:submitNoRequestBox");
+
+  $hide.click();
+  assert.equal($box.hasClass("tobago-collapsed"), true);
+
+  $in.val("");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    $messages = jQueryFrame($messages.selector);
+    assert.equal($messages.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Ajax: show -> hide transition", function (assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $show = jQueryFrame("#page\\:mainForm\\:ajax\\:showAjaxBox");
+  var $hide = jQueryFrame("#page\\:mainForm\\:ajax\\:hideAjaxBox");
+  var $in = jQueryFrame("#page\\:mainForm\\:ajax\\:inAjaxBox\\:\\:field");
+
+  $show.click();
+
+  waitForAjax(function () {
+    $in = jQueryFrame($in.selector);
+    console.log("step: " + step + " active: " + jQuery.active);
+    return step == 1 && jQuery.active == 0;
+  }, function () {
+    $hide = jQueryFrame($hide.selector);
+    $in = jQueryFrame($in.selector);
+
+    console.log("$hide.selector: " + $hide.selector);
+    assert.equal($in.length, 1);
+    $hide.click();
+
+    step++;
+    done();
+  });
+
+  waitForAjax(function () {
+    $in = jQueryFrame($in.selector);
+    return step == 2 && $in.length == 0;
+  }, function () {
+    $in = jQueryFrame($in.selector);
+    assert.equal($in.length, 0);
+    done();
+  });
+});
+
+
+QUnit.test("Ajax: hide -> show transition", function (assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+  var step = 1;
+
+  var $show = jQueryFrame("#page\\:mainForm\\:ajax\\:showAjaxBox");
+  var $hide = jQueryFrame("#page\\:mainForm\\:ajax\\:hideAjaxBox");
+  var $in = jQueryFrame("#page\\:mainForm\\:ajax\\:inAjaxBox\\:\\:field");
+
+  $hide.click();
+
+  waitForAjax(function () {
+    $in = jQueryFrame($in.selector);
+    return step == 1 && $in.length == 0;
+  }, function () {
+    $show = jQueryFrame($show.selector);
+    $in = jQueryFrame($in.selector);
+
+    assert.equal($in.length, 0);
+    $show.click();
+
+    step++;
+    done();
+  });
+
+  waitForAjax(function () {
+    $in = jQueryFrame($in.selector);
+    return step == 2 && $in.length == 1;
+  }, function () {
+    $in = jQueryFrame($in.selector);
+    assert.equal($in.length, 1);
+    done();
+  });
+});
+
+QUnit.test("Ajax: hide content and submit empty string", function (assert) {
+  assert.expect(3);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $show = jQueryFrame("#page\\:mainForm\\:ajax\\:showAjaxBox");
+  var $hide = jQueryFrame("#page\\:mainForm\\:ajax\\:hideAjaxBox");
+  var $in = jQueryFrame("#page\\:mainForm\\:ajax\\:inAjaxBox\\:\\:field");
+  var $submit = jQueryFrame("#page\\:mainForm\\:ajax\\:submitAjaxBox");
+
+  $show.click();
+
+  waitForAjax(function () {
+    $in = jQueryFrame($in.selector);
+    return step == 1 && $in.length == 1;
+  }, function () {
+    $hide = jQueryFrame($hide.selector);
+    $in = jQueryFrame($in.selector);
+
+    assert.equal($in.length, 1);
+    $in.val("");
+    $hide.click();
+
+    step++;
+    done();
+  });
+
+  waitForAjax(function () {
+    $in = jQueryFrame($in.selector);
+    return step == 2 && $in.length == 0;
+  }, function () {
+    $in = jQueryFrame($in.selector);
+    $submit = jQueryFrame($submit.selector);
+
+    assert.equal($in.length, 0);
+    $submit.click();
+
+    step++;
+    done();
+  });
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      assert.equal($messages.length, 0);
+      done();
+    }
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.xhtml
new file mode 100644
index 0000000..d37fc21
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.xhtml
@@ -0,0 +1,149 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.collapsible_box} &lt;tc:box>"/>
+  <p>On this page the collapsible concept is explained for a
+    <tc:link label="#{demoBundle.box}" link="/faces/content/20-component/050-container/10-box/box.xhtml"/>.</p>
+
+  <tc:section label="Simple Collapsible Box">
+    <tc:form id="controller">
+      <p>This is a simple collapsible box which open and close the content via a controller.</p>
+      <pre><code class="language-markup">&lt;tc:button label="show" immediate="true"
+        action="\#{collapsibleBoxController.showCollapsed1}"/></code></pre>
+      <tc:box label="Box" collapsed="#{collapsibleBoxController.collapsed}" collapsedMode="absent">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="show" label="show" immediate="true" action="#{collapsibleBoxController.show}"/>
+            <tc:button id="hide" label="hide" immediate="true" action="#{collapsibleBoxController.hide}"/>
+          </tc:buttons>
+        </f:facet>
+        <tc:out id="content" value="Content"/>
+      </tc:box>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Full Server Request">
+    <tc:form id="server">
+      <p>In this example, the operaction tag is used to change the state of the boxes.</p>
+      <pre><code class="language-markup">&lt;tc:box id="box1" label="Full Request Box 1" collapsedMode="absent">
+  &lt;f:facet name="bar">
+    &lt;tc:buttons>
+      &lt;tc:button label="show">
+        &lt;tc:operation name="show" for="box1"/>
+      ...</code></pre>
+      <tc:box id="box1" label="Full Request Box 1" collapsedMode="absent">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="show1" label="show">
+              <tc:operation name="show" for="box1"/>
+            </tc:button>
+            <tc:button id="hide1" label="hide">
+              <tc:operation name="hide" for="box1"/>
+            </tc:button>
+          </tc:buttons>
+        </f:facet>
+        <tc:out id="content1" value="Content"/>
+      </tc:box>
+      <tc:box id="box2" label="Full Request Box 2" collapsedMode="absent">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="show2" label="show">
+              <tc:operation name="show" for="box2"/>
+            </tc:button>
+            <tc:button id="hide2" label="hide">
+              <tc:operation name="hide" for="box2"/>
+            </tc:button>
+          </tc:buttons>
+        </f:facet>
+        <tc:out id="content2" value="Content"/>
+      </tc:box>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Client Sided">
+    <tc:form id="client">
+      <p>This example show a content box which could be opened and closed without a server request.<br/>
+        To render the hidden content of the box, <code>collapsedMode="hidden"</code> must be set.
+        The content is hidden by CSS display property.</p>
+      <p>Also the content contain a required inputfield.
+        This field will be also validated if the content is hidden.<br/>
+        To demonstrate that, leave the inputfield blank, hide the content and press the 'Submit'-button.</p>
+      <p>Notice the <code>omit</code> attribute of the buttons is set to avoid server request.</p>
+      <pre><code class="language-markup">&lt;tc:box id="noRequestBox" label="No Request Box"
+        collapsed="true" collapsedMode="hidden">
+  &lt;tc:button label="show" omit="true">
+    &lt;tc:operation name="show" for="noRequestBox"/>
+  ...</code></pre>
+      <tc:box id="noRequestBox" label="No Request Box" collapsed="true" collapsedMode="hidden">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="showNoRequestBox" label="show" omit="true">
+              <tc:operation name="show" for="noRequestBox"/>
+            </tc:button>
+            <tc:button id="hideNoRequestBox" label="hide" omit="true">
+              <tc:operation name="hide" for="noRequestBox"/>
+            </tc:button>
+          </tc:buttons>
+        </f:facet>
+        <tc:in id="inNoRequestBox" label="Required" required="true"/>
+      </tc:box>
+      <tc:button id="submitNoRequestBox" label="Submit"/>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <tc:form id="ajax">
+      <p>Here we have the transitions <code>show</code> and <code>hide</code> with AJAX request.
+        The buttons have set <code>omit="false"</code> which is the default.
+        Also the attribute <code>immediate="true"</code> is set to execute the transition without validation.</p>
+      <p>The mode is set to <code>collapsedMode="absent"</code> (default), so the hidden content won't be rendered
+        and therefor not validated.</p>
+      <p>You can press the 'Submit'-button after hiding the blank inputfield.
+        The submit will be executed without validation.
+        If the content is shown and the field is empty, a violation occurs after hitting 'Submit'.</p>
+      <pre><code class="language-markup">&lt;tc:box id="ajaxBox" label="Collapsible Box (AJAX)" collapsedMode="absent">
+  ...
+    &lt;tc:button label="show" immediate="true">
+      &lt;f:ajax execute="ajaxBox" render="ajaxBox"/>
+      &lt;tc:operation name="show" for="ajaxBox"/>
+    ...</code></pre>
+      <tc:box id="ajaxBox" label="Ajax Box" collapsedMode="absent">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="showAjaxBox" label="show" immediate="true">
+              <f:ajax execute="ajaxBox" render="ajaxBox"/>
+              <tc:operation name="show" for="ajaxBox"/>
+            </tc:button>
+            <tc:button id="hideAjaxBox" label="hide" immediate="true">
+              <f:ajax execute="ajaxBox" render="ajaxBox"/>
+              <tc:operation name="hide" for="ajaxBox"/>
+            </tc:button>
+          </tc:buttons>
+        </f:facet>
+        <tc:in id="inAjaxBox" label="Required" required="true"/>
+      </tc:box>
+      <tc:button id="submitAjaxBox" label="Submit"/>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.test.js
new file mode 100644
index 0000000..75fb6a4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.test.js
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Simple Popup", function (assert) {
+  assert.expect(9);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $open = jQueryFrame("#page\\:mainForm\\:simple\\:open1");
+  var $submitOnPage = jQueryFrame("#page\\:mainForm\\:simple\\:submitOnPage1");
+  var $in = jQueryFrame("#page\\:mainForm\\:simple\\:controllerPopup\\:in1\\:\\:field");
+  var $submitOnPopup = jQueryFrame("#page\\:mainForm\\:simple\\:controllerPopup\\:submitOnPopup1");
+  var $close = jQueryFrame("#page\\:mainForm\\:simple\\:controllerPopup\\:close1");
+
+  $open.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $in = jQueryFrame($in.selector);
+      $submitOnPopup = jQueryFrame($submitOnPopup.selector);
+
+      assert.equal($in.length, 1);
+      $in.val("some text");
+      $submitOnPopup.click();
+
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $in = jQueryFrame($in.selector);
+      $submitOnPopup = jQueryFrame($submitOnPopup.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($in.length, 1);
+      assert.equal($in.val(), "some text");
+      $in.val("");
+      $submitOnPopup.click();
+
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $in = jQueryFrame($in.selector);
+      $close = jQueryFrame($close.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($in.length, 1);
+      assert.equal($in.val(), "");
+      $close.click();
+
+      done();
+    } else if (step == 4) {
+      $submitOnPage = jQueryFrame($submitOnPage.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($in.length, 0);
+      $submitOnPage.click();
+
+      done();
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+
+      assert.equal($messages.length, 0);
+
+      done();
+    }
+    step++;
+  });
+});
+
+QUnit.test("Full Server Request", function (assert) {
+  assert.expect(9);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $open = jQueryFrame("#page\\:mainForm\\:server\\:open2");
+  var $submitOnPage = jQueryFrame("#page\\:mainForm\\:server\\:submitOnPage2");
+  var $in = jQueryFrame("#page\\:mainForm\\:server\\:fullServerRequestPopup\\:in2\\:\\:field");
+  var $submitOnPopup = jQueryFrame("#page\\:mainForm\\:server\\:fullServerRequestPopup\\:submitOnPopup2");
+  var $close = jQueryFrame("#page\\:mainForm\\:server\\:fullServerRequestPopup\\:close2");
+
+  $open.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $in = jQueryFrame($in.selector);
+      $submitOnPopup = jQueryFrame($submitOnPopup.selector);
+
+      assert.equal($in.length, 1);
+      $in.val("some text");
+      $submitOnPopup.click();
+
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $in = jQueryFrame($in.selector);
+      $submitOnPopup = jQueryFrame($submitOnPopup.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($in.length, 1);
+      assert.equal($in.val(), "some text");
+      $in.val("");
+      $submitOnPopup.click();
+
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $in = jQueryFrame($in.selector);
+      $close = jQueryFrame($close.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($in.length, 1);
+      assert.equal($in.val(), "");
+      $close.click();
+
+      done();
+    } else if (step == 4) {
+      $submitOnPage = jQueryFrame($submitOnPage.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($in.length, 0);
+      $submitOnPage.click();
+
+      done();
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+
+      assert.equal($messages.length, 0);
+
+      done();
+    }
+    step++;
+  });
+});
+
+QUnit.test("Client Sided", function (assert) {
+  assert.expect(9);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $open = jQueryFrame("#page\\:mainForm\\:client\\:open3");
+  var $submitOnPage = jQueryFrame("#page\\:mainForm\\:client\\:submitOnPage3");
+  var $popupCollapsed = jQueryFrame("#page\\:mainForm\\:client\\:clientPopup\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:client\\:clientPopup\\:in3\\:\\:field");
+  var $submitOnPopup = jQueryFrame("#page\\:mainForm\\:client\\:clientPopup\\:submitOnPopup3");
+  var $close = jQueryFrame("#page\\:mainForm\\:client\\:clientPopup\\:close3");
+
+  $open.click();
+  assert.equal($popupCollapsed.val(), "false");
+  $close.click();
+  assert.equal($popupCollapsed.val(), "true");
+  $open.click();
+  assert.equal($popupCollapsed.val(), "false");
+  $in.val("some text");
+  $submitOnPopup.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $messages = jQueryFrame($messages.selector);
+      $open = jQueryFrame($open.selector);
+      $popupCollapsed = jQueryFrame($popupCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submitOnPopup = jQueryFrame($submitOnPopup.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($popupCollapsed.val(), "true");
+      $open.click();
+      assert.equal($popupCollapsed.val(), "false");
+      $in.val("");
+      $submitOnPopup.click();
+
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $submitOnPage = jQueryFrame($submitOnPage.selector);
+      $popupCollapsed = jQueryFrame($popupCollapsed.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($popupCollapsed.val(), "true");
+      $submitOnPage.click();
+
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+
+      assert.equal($messages.length, 1);
+
+      done();
+    }
+    step++;
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.xhtml
new file mode 100644
index 0000000..51db08e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.xhtml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.collapsible_popup} &lt;tc:popup>"/>
+  <p>This page contain some examples for the collapsible concept of a popup. Please have a look at the
+    <tc:link label="#{demoBundle.popup}" link="/faces/content/20-component/060-popup/popup.xhtml"/> page
+    in the components section for more details.</p>
+
+  <tc:section label="Simple Popup">
+    <tc:form id="simple">
+      <p>A popup opened with the help of a controller. The popup contain a required inputfield.
+        The attribute <code>collapsedMode="absent"</code> is set,
+        so the 'Submit'-button outside the popup could be executed while popup is hidden.
+        Even if the required inputfield is empty.</p>
+      <tc:button id="open1" label="Open" action="#{collapsiblePopupController.open}"/>
+      <tc:button id="submitOnPage1" label="Submit"/>
+      <tc:popup id="controllerPopup" collapsed="#{collapsiblePopupController.collapsed}">
+        <tc:box label="Simple Popup">
+          <tc:in id="in1" label="Required" required="true"/>
+          <tc:button id="submitOnPopup1" label="Submit"/>
+          <tc:button id="close1" label="Close" immediate="true" action="#{collapsiblePopupController.close}"/>
+        </tc:box>
+      </tc:popup>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Full Server Request">
+    <tc:form id="server">
+      <p>Server sided popup with <code class="language-markup">&lt;tc:operation/></code>.
+        The attribute <code>collapsedMode="absent"</code> is set by default.
+        If you press the 'Submit'-button in the popup, the popup remains open,
+        because the server know the current state.</p>
+      <tc:button id="open2" label="Open">
+        <tc:operation name="show" for="fullServerRequestPopup"/>
+      </tc:button>
+      <tc:button id="submitOnPage2" label="Submit"/>
+      <tc:popup id="fullServerRequestPopup">
+        <tc:box label="Full Server Request">
+          <tc:in id="in2" label="Required" required="true"/>
+          <tc:button id="submitOnPopup2" label="Submit"/>
+          <tc:button id="close2" label="Close" immediate="true">
+            <tc:operation name="hide" for="fullServerRequestPopup"/>
+          </tc:button>
+        </tc:box>
+      </tc:popup>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Client Sided">
+    <tc:form id="client">
+      <p>For the client sided popup the attribute <code>collapsedMode="hidden"</code> must be set.
+        So the hidden popup is already rendered on the site. Otherwise a client sided opened popup has no content.</p>
+      <p>This leads to the problem of violations of hidden content.
+        In this case you cannot press the 'Submit'-button if the required field is empty.
+        Even if the popup is hidden.</p>
+      <p>The 'Submit'-button in the popup will close the popup, because the server didn't know the current state.</p>
+      <p>To avoid server request, the attribute <code>omit="true"</code>
+        is added to the 'Open'-button and the 'Close'-button.</p>
+      <tc:button id="open3" label="Open" omit="true">
+        <tc:operation name="show" for="clientPopup"/>
+      </tc:button>
+      <tc:button id="submitOnPage3" label="Submit"/>
+      <tc:popup id="clientPopup" collapsedMode="hidden">
+        <tc:box label="Full Server Request">
+          <p>The opening of the popup is client sided.
+            Therefor the popup will be closed after pressing the 'Submit'-button which reload the page.</p>
+          <tc:in id="in3" label="Required" required="true"/>
+          <tc:button id="submitOnPopup3" label="Submit"/>
+          <tc:button id="close3" label="Close" omit="true">
+            <tc:operation name="hide" for="clientPopup"/>
+          </tc:button>
+        </tc:box>
+      </tc:popup>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/collapsible-panel.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/collapsible-panel.test.js
new file mode 100644
index 0000000..01f650f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/collapsible-panel.test.js
@@ -0,0 +1,339 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Simple Panel", function (assert) {
+  assert.expect(14);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:simple\\:showSimple");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:simple\\:hideSimple");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:simple\\:submitSimple");
+  var $panelCollapsed = jQueryFrame("#page\\:mainForm\\:simple\\:simplePanel\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:simple\\:inSimple\\:\\:field");
+
+  $show.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("some text");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      step++;
+      done();
+    } else if (step == 4) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Full Server Request", function (assert) {
+  assert.expect(14);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:server\\:showServer");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:server\\:hideServer");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:server\\:submitServer");
+  var $panelCollapsed = jQueryFrame("#page\\:mainForm\\:server\\:serverPanel\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:server\\:inServer\\:\\:field");
+
+  $show.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("some text");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      step++;
+      done();
+    } else if (step == 4) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Client Sided", function (assert) {
+  assert.expect(14);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:client\\:showClient");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:client\\:hideClient");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:client\\:submitClient");
+  var $panelCollapsed = jQueryFrame("#page\\:mainForm\\:client\\:clientPanel\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:client\\:inClient\\:\\:field");
+
+  $show.click();
+  assert.equal($panelCollapsed.val(), "false");
+  assert.equal($in.length, 1);
+  $in.val("some text");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      assert.equal($messages.length, 1);
+      assert.equal($panelCollapsed.val(), "true");
+      assert.equal($in.length, 1);
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Ajax", function (assert) {
+  assert.expect(13);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:ajax\\:showAjax");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:ajax\\:hideAjax");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:ajax\\:submitAjax");
+  var $panelCollapsed = jQueryFrame("#page\\:mainForm\\:ajax\\:ajaxPanel\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:ajax\\:inAjax\\:\\:field");
+
+  $show.click();
+
+  waitForAjax(function () {
+    $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+    $in = jQueryFrame($in.selector);
+    return step == 1
+        && $panelCollapsed.val() == "false"
+        && $in.length == 1;
+  }, function () {
+    $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+    $in = jQueryFrame($in.selector);
+    $submit = jQueryFrame($submit.selector);
+
+    assert.equal($panelCollapsed.val(), "false");
+    assert.equal($in.length, 1);
+    $in.val("some text");
+    $submit.click();
+
+    step++;
+    done();
+  });
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($panelCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      step++;
+      done();
+
+      waitForAjax(function () {
+        $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+        $in = jQueryFrame($in.selector);
+        return step == 4
+            && $panelCollapsed.val() == "true"
+            && $in.length == 0;
+      }, function () {
+        $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+        $in = jQueryFrame($in.selector);
+        $submit = jQueryFrame($submit.selector);
+
+        assert.equal($panelCollapsed.val(), "true");
+        assert.equal($in.length, 0);
+        $submit.click();
+
+        step++;
+        done();
+      });
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+      $panelCollapsed = jQueryFrame($panelCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($panelCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+
+      done();
+    }
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/collapsible-panel.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/collapsible-panel.xhtml
new file mode 100644
index 0000000..5f231ac
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/20-collapsible-panel/collapsible-panel.xhtml
@@ -0,0 +1,123 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.collapsible_panel} &lt;tc:panel>"/>
+  <p>This page show some examples for the collapsible concept of a
+    <tc:link label="#{demoBundle.panel}" link="/faces/content/20-component/050-container/20-panel/panel.xhtml"/>.
+    Every panel contain a required inputfield to see if a validation occur while submitting.
+    For better visibility every panel has a border.</p>
+  <tc:section label="Simple Panel">
+    <p>A simple panel using an controller for the collapsible state.
+      For the 'hide'-Button is the attribute <code>immediate="true"</code> set to submitting without validation.
+      So the panel could be hide even if the inputfield is empty.</p>
+    <p>For the panel <code>collapsibleMode="absent"</code> is set.
+      The 'Submit'-button can be executed without violation if the panel is in the hidden state.</p>
+    <tc:form id="simple">
+      <tc:buttons>
+        <tc:button id="showSimple" label="show" action="#{collapsiblePanelController.showPanel}"/>
+        <tc:button id="hideSimple" label="hide" action="#{collapsiblePanelController.hidePanel}" immediate="true"/>
+      </tc:buttons>
+      <tc:button id="submitSimple" label="Submit"/>
+      <tc:panel id="simplePanel" collapsed="#{collapsiblePanelController.panelCollapsed}" collapsedMode="absent">
+        <tc:style customClass="demo-data-attribute"/>
+        <tc:in id="inSimple" label="Required" required="true"/>
+      </tc:panel>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Full Server Request">
+    <p>In this example the collapsible state is changed by <code class="language-markup">&lt;tc:operation/></code>
+      with full server request. So the server get the current state.</p>
+    <p>The <code>collapsibleMode="absent"</code> is set.
+      The 'Submit'-button can be executed without violation if the panel is hidden.</p>
+    <p>For the 'hide'-Button the attribute <code>immediate="true"</code> is set to submitting without validation.</p>
+    <tc:form id="server">
+      <tc:buttons>
+        <tc:button id="showServer" label="show">
+          <tc:operation name="show" for="serverPanel"/>
+        </tc:button>
+        <tc:button id="hideServer" label="hide" immediate="true">
+          <tc:operation name="hide" for="serverPanel"/>
+        </tc:button>
+      </tc:buttons>
+      <tc:button id="submitServer" label="Submit"/>
+      <tc:panel id="serverPanel" collapsedMode="absent">
+        <tc:style customClass="demo-data-attribute"/>
+        <tc:in id="inServer" label="Required" required="true"/>
+      </tc:panel>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Client Sided">
+    <p>A panel which is opened and closed only by the client.
+      The attribute <code>omit="true"</code> is set for the 'show'-button and the 'hide'-button.</p>
+    <p>For the panel <code>collapsibleMode="hidden"</code> is set.
+      After the 'hide' transition, the panel will be in the 'hidden' state - not the 'absent' state.
+      The content of the hidden panel will also be validated.<br/>
+      So, if the inputfield is empty and the panel is hidden, a violation occur when pressing the 'Submit'-button.</p>
+    <tc:form id="client">
+      <tc:buttons>
+        <tc:button id="showClient" label="show" omit="true">
+          <tc:operation name="show" for="clientPanel"/>
+        </tc:button>
+        <tc:button id="hideClient" label="hide" omit="true" immediate="true">
+          <tc:operation name="hide" for="clientPanel"/>
+        </tc:button>
+      </tc:buttons>
+      <tc:button id="submitClient" label="Submit"/>
+      <tc:panel id="clientPanel" collapsedMode="hidden">
+        <tc:style customClass="demo-data-attribute"/>
+        <tc:in id="inClient" label="Required" required="true"/>
+      </tc:panel>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>Here we have the transitions <code>show</code> and <code>hide</code> with AJAX request.
+      The buttons have set <code>immediate="true"</code> to execute the transition without validation.</p>
+    <p>The <code>collapsibleMode="absent"</code> is set.
+      The 'Submit'-button can be executed without violation if the panel is hidden.</p>
+    <pre><code class="language-markup">&lt;tc:button label="show" immediate="true">
+  &lt;f:ajax execute="ajaxPanel" render="ajaxPanel"/>
+  &lt;tc:operation name="show" for="ajaxPanel"/>
+&lt;/tc:button></code></pre>
+    <tc:form id="ajax">
+      <tc:buttons>
+        <tc:button id="showAjax" label="show" immediate="true">
+          <f:ajax execute="ajaxPanel" render="ajaxPanel"/>
+          <tc:operation name="show" for="ajaxPanel"/>
+        </tc:button>
+        <tc:button id="hideAjax" label="hide" immediate="true">
+          <f:ajax execute="ajaxPanel" render="ajaxPanel"/>
+          <tc:operation name="hide" for="ajaxPanel"/>
+        </tc:button>
+      </tc:buttons>
+      <tc:button id="submitAjax" label="Submit"/>
+      <tc:panel id="ajaxPanel" collapsedMode="absent">
+        <tc:style customClass="demo-data-attribute"/>
+        <tc:in id="inAjax" label="Required" required="true"/>
+      </tc:panel>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/collapsible-section.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/collapsible-section.test.js
new file mode 100644
index 0000000..6b0535f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/collapsible-section.test.js
@@ -0,0 +1,340 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Simple Panel", function (assert) {
+  assert.expect(14);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:simple\\:submitSimple");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:simple\\:showSimple");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:simple\\:hideSimple");
+  var $sectionCollapsed = jQueryFrame("#page\\:mainForm\\:simple\\:simpleSection\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:simple\\:inSimple\\:\\:field");
+
+  $show.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("some text");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      step++;
+      done();
+    } else if (step == 4) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Full Server Request", function (assert) {
+  assert.expect(14);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:server\\:submitServer");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:server\\:showServer");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:server\\:hideServer");
+  var $sectionCollapsed = jQueryFrame("#page\\:mainForm\\:server\\:fullRequestSection\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:server\\:inServer\\:\\:field");
+
+  $show.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("some text");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      step++;
+      done();
+    } else if (step == 4) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Client Sided", function (assert) {
+  assert.expect(14);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:client\\:submitClient");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:client\\:showClient");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:client\\:hideClient");
+  var $sectionCollapsed = jQueryFrame("#page\\:mainForm\\:client\\:clientSection\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:client\\:inClient\\:\\:field");
+
+  $show.click();
+  assert.equal($sectionCollapsed.val(), "false");
+  assert.equal($in.length, 1);
+  $in.val("some text");
+  $submit.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      assert.equal($messages.length, 1);
+      assert.equal($sectionCollapsed.val(), "true");
+      assert.equal($in.length, 1);
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+
+      done();
+    }
+  });
+});
+
+QUnit.test("Ajax", function (assert) {
+  assert.expect(13);
+  var done = assert.async(5);
+  var step = 1;
+
+  var $messages = jQueryFrame("#page\\:messages .tobago-messages");
+  var $submit = jQueryFrame("#\\page\\:mainForm\\:ajax\\:submitAjax");
+  var $show = jQueryFrame("#\\page\\:mainForm\\:ajax\\:showAjax");
+  var $hide = jQueryFrame("#\\page\\:mainForm\\:ajax\\:hideAjax");
+  var $sectionCollapsed = jQueryFrame("#page\\:mainForm\\:ajax\\:ajaxSection\\:\\:collapse");
+  var $in = jQueryFrame("#page\\:mainForm\\:ajax\\:inAjax\\:\\:field");
+
+  $show.click();
+
+  waitForAjax(function () {
+    $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+    $in = jQueryFrame($in.selector);
+    return step == 1
+        && $sectionCollapsed.val() == "false"
+        && $in.length == 1;
+  }, function () {
+    $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+    $in = jQueryFrame($in.selector);
+    $submit = jQueryFrame($submit.selector);
+
+    assert.equal($sectionCollapsed.val(), "false");
+    assert.equal($in.length, 1);
+    $in.val("some text");
+    $submit.click();
+
+    step++;
+    done();
+  });
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 2) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $submit = jQueryFrame($submit.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $in.val("");
+      $submit.click();
+
+      step++;
+      done();
+    } else if (step == 3) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+      $hide = jQueryFrame($hide.selector);
+
+      assert.equal($messages.length, 1);
+      assert.equal($sectionCollapsed.val(), "false");
+      assert.equal($in.length, 1);
+      $hide.click();
+
+      step++;
+      done();
+
+      waitForAjax(function () {
+        $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+        $in = jQueryFrame($in.selector);
+        return step == 4
+            && $sectionCollapsed.val() == "true"
+            && $in.length == 0;
+      }, function () {
+        $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+        $in = jQueryFrame($in.selector);
+        $submit = jQueryFrame($submit.selector);
+
+        assert.equal($sectionCollapsed.val(), "true");
+        assert.equal($in.length, 0);
+        $submit.click();
+
+        step++;
+        done();
+      });
+    } else if (step == 5) {
+      $messages = jQueryFrame($messages.selector);
+      $sectionCollapsed = jQueryFrame($sectionCollapsed.selector);
+      $in = jQueryFrame($in.selector);
+
+      assert.equal($messages.length, 0);
+      assert.equal($sectionCollapsed.val(), "true");
+      assert.equal($in.length, 0);
+
+      step++;
+      done();
+    }
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/collapsible-section.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/collapsible-section.xhtml
new file mode 100644
index 0000000..b7b4d59
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/30-collapsible-section/collapsible-section.xhtml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.collapsible_section} &lt;tc:section>"/>
+  <p>Collapsible concept explained for a
+    <tc:link label="#{demoBundle.section}"
+             link="/faces/content/20-component/050-container/40-section/section.xhtml"/>.</p>
+  <tc:section label="Simple Section">
+    <p>A simple collapsible section. The <code>collapsed</code> attribute is set by a controller.
+      The 'hide'-button got <code>immediate="true"</code> to submitting without validation.</p>
+    <p>The <code>collapsedMode="absent"</code> is set.
+      The 'Submit'-button can be executed without violation if the content of section is hidden.</p>
+    <tc:form id="simple">
+      <tc:button id="submitSimple" label="Submit"/>
+      <tc:section id="simpleSection" label="Collapsible Section" collapsed="#{collapsibleSectionController.collapsed}"
+                  collapsedMode="absent">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="showSimple" label="show" action="#{collapsibleSectionController.show}"/>
+            <tc:button id="hideSimple" label="hide" action="#{collapsibleSectionController.hide}" immediate="true"/>
+          </tc:buttons>
+        </f:facet>
+        <tc:in id="inSimple" label="Required" required="true"/>
+      </tc:section>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Full Server Request">
+    <p>The state is changed by <code class="language-markup">&lt;tc:operation/></code> with a full server request.
+      The attribute <code>immediate="true"</code> is set for the 'hide'-button
+      to change the state without validating the inputfield.</p>
+    <p>The <code>collapsedMode="absent"</code> is set.
+      The 'Submit'-button can be executed without violation if the content of section is hidden.</p>
+    <tc:form id="server">
+      <tc:button id="submitServer" label="Submit"/>
+      <tc:section id="fullRequestSection" label="Collapsible Section" collapsedMode="absent">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="showServer" label="show">
+              <tc:operation name="show" for="fullRequestSection"/>
+            </tc:button>
+            <tc:button id="hideServer" label="hide" immediate="true">
+              <tc:operation name="hide" for="fullRequestSection"/>
+            </tc:button>
+          </tc:buttons>
+        </f:facet>
+        <tc:in id="inServer" label="Required" required="true"/>
+      </tc:section>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Client Sided">
+    <p>In this example opening and closing is done by the client.
+      The attribute <code>omit="true"</code> set for the 'show'-button and the 'hide'-button to prevent submitting.</p>
+    <p>For the section <code>collapsedMode="hidden"</code> is set.
+      After the 'hide' transition, the content of the section will be in the 'hidden' state.
+      The hidden content of the section will also be validated.<br/>
+      If the 'Submit'-button is pressed while the inputfield is empty, a violation occurs.</p>
+    <tc:form id="client">
+      <tc:button id="submitClient" label="Submit"/>
+      <tc:section id="clientSection" label="Collapsible Section" collapsedMode="hidden">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="showClient" label="show" omit="true">
+              <tc:operation name="show" for="clientSection"/>
+            </tc:button>
+            <tc:button id="hideClient" label="hide" omit="true">
+              <tc:operation name="hide" for="clientSection"/>
+            </tc:button>
+          </tc:buttons>
+        </f:facet>
+        <tc:in id="inClient" label="Required" required="true"/>
+      </tc:section>
+    </tc:form>
+  </tc:section>
+
+  <tc:section label="Ajax">
+    <p>The show and hide transitions are run with an ajax request.
+      The 'hide'-button got <code>immediate="true"</code> to submitting without validation.</p>
+    <p>The <code>collapsedMode="absent"</code> is set.
+      The 'Submit'-button can be executed without violation if the content of section is hidden.</p>
+    <tc:form id="ajax">
+      <tc:button id="submitAjax" label="Submit"/>
+      <tc:section id="ajaxSection" label="Collapsible Section" collapsedMode="absent">
+        <f:facet name="bar">
+          <tc:buttons>
+            <tc:button id="showAjax" label="show">
+              <f:ajax execute="ajaxSection" render="ajaxSection"/>
+              <tc:operation name="show" for="ajaxSection"/>
+            </tc:button>
+            <tc:button id="hideAjax" label="hide" immediate="true">
+              <f:ajax execute="ajaxSection" render="ajaxSection"/>
+              <tc:operation name="hide" for="ajaxSection"/>
+            </tc:button>
+          </tc:buttons>
+        </f:facet>
+        <tc:in id="inAjax" label="Required" required="true"/>
+      </tc:section>
+    </tc:form>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/collapsible.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/collapsible.xhtml
new file mode 100644
index 0000000..dc39748
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/53-collapsible/collapsible.xhtml
@@ -0,0 +1,101 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.collapsible}"/>
+
+  <p>
+    <span class="tag tag-danger">Warning!</span>
+    <b>This feature is preliminary and may be subject of change in later versions!</b>
+  </p>
+
+  <p>The collapsible concept is the base for
+    <tc:link label="#{demoBundle.box}" link="/faces/content/20-component/050-container/10-box/box.xhtml"/>,
+    <tc:link label="#{demoBundle.popup}" link="/faces/content/20-component/060-popup/popup.xhtml"/>,
+    <tc:link label="#{demoBundle.panel}" link="/faces/content/20-component/050-container/20-panel/panel.xhtml"/>
+    and
+    <tc:link label="#{demoBundle.section}"
+             link="/faces/content/20-component/050-container/40-section/section.xhtml"/>.
+    It determines how parts or whole components are shown or hidden.
+    For example, a #{demoBundle.popup} is hidden completely while for #{demoBundle.box} only the content
+    could be hidden.</p>
+
+  <tc:section label="States">
+    <p>There are four possible states - visible, hidden, absent and none.<br/>
+    The value 'none' deactivate this feature and is the default for #{demoBundle.box}, #{demoBundle.panel} and
+     #{demoBundle.section}.</p>
+    <p>The (not-'none') states are explained using the following #{demoBundle.box}es.</p>
+    <p>The 'visible' state show the content of the box like you expected.
+      <br/>
+      The 'hidden' state hide the content via CSS. You can see is still in the source code.
+      This also means that hidden content would be validated when submitted, e. g. a required inputfield.
+      <br/>
+      The 'absent' state don't even render the content of the box.</p>
+    <tc:segmentLayout medium="4;4;4">
+      <tc:box label="Visible" collapsed="false">
+        <p>Content</p>
+      </tc:box>
+      <tc:box label="Hidden" collapsed="true" collapsedMode="hidden">
+        <p>Content</p>
+      </tc:box>
+      <tc:box label="Absent" collapsed="true" collapsedMode="absent">
+        <p>Content</p>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="Attributes">
+    <p>The state can be changed by the server with the attributes
+      <code>collapsed</code> and <code>collapsedMode</code>.</p>
+    <tc:section label="collapsed">
+      <p>The <code>collapsed</code> attribute is of type boolean. The default value is 'false'.</p>
+      <ul>
+        <li><code>false</code> (default): The state is 'visible'.</li>
+        <li><code>true</code>: The state is 'hidden' or 'absent', depending on the
+          <code>collapsedMode</code> attribute.
+        </li>
+      </ul>
+    </tc:section>
+    <tc:section label="collapsedMode">
+      <p>The attribute <code>collapsedMode</code> determine the behavior of a hidden component.
+        Possible values are <code>absent</code> which is the default and <code>hidden</code>.
+        It has only an effect if <code>collapsed="true"</code>.</p>
+      <ul>
+        <li><code>absent</code> (default for #{demoBundle.popup}): Hidden components have the state 'hidden'.</li>
+        <li><code>hidden</code>: Hidden components have the state 'absent'.</li>
+      </ul>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Operation">
+    <pre><code class="language-markup">&lt;tc:operation name="show|hide" for="[ID]"/></code></pre>
+    <p>Operations can be used to change the state client sided. It can be placed
+      within a <code class="language-markup">&lt;tc:button/></code> tag or a
+      <code class="language-markup">&lt;tc:link/></code> tag.
+      The name of the transition can be set in the <code>name</code> attribute. Values are 'show' and 'hide'.</p>
+    <ul>
+      <li><code>show</code>: Change the state to 'visible'.</li>
+      <li><code>hide</code>: Set the state to 'absent' or 'hidden', depending on <code>collapsedMode</code>.</li>
+    </ul>
+    <p>The <code>for</code> attribute has to contain the ID of the component
+      on which the transition should be executed.
+      Both attributes are mandatory.</p>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/65-accessKey/accessKey.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/65-accessKey/accessKey.xhtml
new file mode 100644
index 0000000..1871062
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/65-accessKey/accessKey.xhtml
@@ -0,0 +1,92 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.accessKey}"/>
+  <p>The <code>accessKey</code> attribute is available for many components like buttons, checkboxes or links.
+    A component with this attribute is accessible by the given character. The character is not case sensitive.</p>
+  <p>Logging the accessKey can be configured by setting the category
+    <code>org.apache.myfaces.tobago.internal.util.AccessKeyLogger</code> to log level "debug".</p>
+
+  <p>The usage of accesskeys is different for every OS and browser.<br/>
+    For example, in the Windows-Firefox, you have to press 'Alt + Shift + key'.
+    In Chrome for Mac OS X it's only 'Control + Alt + key'.
+    A complete listing can be found at the
+    <tc:link label="Mozilla Developer Network"
+             link="https://developer.mozilla.org/de/docs/Web/HTML/Global_attributes/accesskey"/>.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:button/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/button.html"/>
+    |
+    <tc:link label="&lt;tc:checkbox/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/checkbox.html"/>
+    |
+    <tc:link label="&lt;tc:link/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/link.html"/>
+    |
+    <tc:link label="&lt;tc:label/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/label.html"/></p>
+
+  <tc:section label="Basics">
+    <p>The accesskey is set to 'a'. Notice, that the 'A' in the label of the button has an underscore.</p>
+    <pre><code class="language-markup">&lt;tc:button label="Button AccessKey" accessKey="a"></code></pre>
+    <tc:button label="Button AccessKey" accessKey="a">
+      <f:facet name="confirmation">
+        <tc:out value="'Button AccessKey' pressed"/>
+      </f:facet>
+    </tc:button>
+  </tc:section>
+
+  <tc:section label="Invisible Key">
+    <p>The accesskey is '3'. Nothing is underlinded, because the value of the label doesn't contain a '3'.</p>
+    <pre><code class="language-markup">&lt;tc:button label="Button Three" accessKey="3"></code></pre>
+    <tc:button label="Button Three" accessKey="3">
+      <f:facet name="confirmation">
+        <tc:out value="Button 3 pressed"/>
+      </f:facet>
+    </tc:button>
+  </tc:section>
+
+  <tc:section label="#{demoBundle.input}">
+    <p>The <code>accessKey</code> is also available for input fields.
+      An input field will get the focus after pressing the accesskey.</p>
+    <tc:section label="#{demoBundle.in}">
+      <pre><code class="language-markup">&lt;tc:in label="Input" accessKey="i"/></code></pre>
+      <tc:in label="Input" accessKey="i"/>
+    </tc:section>
+    <tc:section label="#{demoBundle.textarea}">
+      <pre><code class="language-markup">&lt;tc:textarea label="Textarea" accessKey="t"/></code></pre>
+      <tc:textarea label="Textarea" accessKey="t"/>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Label">
+    <p>For the <code class="language-markup">&lt;tc:label/></code> tag
+      an accesskey can be set in combination with the <code>for</code> attribute.</p>
+    <p>The following example show a label which is automatically bound to the inputfield after that.</p>
+    <pre><code class="language-markup">&lt;tc:label value="Label" accessKey="l" for="@auto"/>
+&lt;tc:in/></code></pre>
+    <tc:flowLayout textAlign="right">
+      <tc:label value="Label" accessKey="l" for="@auto"/>
+      <tc:in/>
+    </tc:flowLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/70-dataAttribute/dataAttribute.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/70-dataAttribute/dataAttribute.js
new file mode 100644
index 0000000..f739d07
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/70-dataAttribute/dataAttribute.js
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ jQuery(document).ready(function () {
+ jQuery("[data-colored]")
+ .css("background-color", "#aaaaaa")
+ .click(function () {
+ jQuery(this).css("background-color", jQuery(this).data("colored"));
+ })
+ .dblclick(function () {
+ jQuery(this).css("background-color", "#aaaaaa");
+ });
+ });
+ */
+
+(function ($) {
+
+    $.widget("demo.colored", {
+
+        options: {
+            resetColor: "#aaaaaa"
+        },
+
+        _create: function () {
+            this.element.css("background-color", this.options.resetColor);
+            this._on({
+                click: function (event) {
+                    this.element.css("background-color", this.element.data("color"));
+                },
+                dblclick: function (event) {
+                    this.element.css("background-color", this.options.resetColor);
+                }
+            });
+        },
+
+        _setOption: function (key, value) {
+            switch (key) {
+                case "resetColor":
+                    this.options.resetColor = value;
+                    break;
+            }
+            this._super("_setOption", key, value);
+        },
+
+        _destroy: function () {
+        }
+
+    });
+
+}(jQuery));
+
+Tobago.registerListener(function() {
+    jQuery("[data-color]").colored({resetColor: "#f8f8f8"});
+}, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/70-dataAttribute/dataAttribute.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/70-dataAttribute/dataAttribute.xhtml
new file mode 100644
index 0000000..bab37f7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/70-dataAttribute/dataAttribute.xhtml
@@ -0,0 +1,71 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.dataAttribute} &lt;tc:dataAttribute>"/>
+  <tc:script file="content/30-concept/70-dataAttribute/dataAttribute.js"/>
+  <p>Add a data attribute to an UIComponent with
+    <code class="language-markup">&lt;tc:dataAttribute/></code>.
+    The data attribute is added to the parent and can be used by scripts.</p>
+  <tc:link label="Tag Library Documentation" image="#{request.contextPath}/image/feather-leaf.png"
+           link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/dataAttribute.html"/>
+
+  <tc:section label="Example">
+    <p>Each box contains a panel with a data attribute.
+      It contains a color code which will be used by a JavaScript which is included into this page.
+      <b>Click</b> in the content area of the boxes to set up a color. <b>Doubleclick</b> to remove it.</p>
+    <pre><code class="language-markup">&lt;tc:box label="Green">
+  &lt;tc:panel>
+    &lt;tc:style customClass="demo-data-attribute"/>
+    &lt;tc:dataAttribute name="color" value="#00ff00"/>
+    ...</code></pre>
+    <tc:segmentLayout small="6;6">
+      <tc:box label="Green">
+        <tc:panel>
+          <tc:style customClass="demo-data-attribute"/>
+          <tc:dataAttribute name="color" value="#00ff00"/>
+        </tc:panel>
+      </tc:box>
+
+      <tc:box label="Red">
+        <tc:panel>
+          <tc:style customClass="demo-data-attribute"/>
+          <tc:dataAttribute name="color" value="#ff0000"/>
+        </tc:panel>
+      </tc:box>
+
+      <tc:box label="Yellow">
+        <tc:panel>
+          <tc:style customClass="demo-data-attribute"/>
+          <tc:dataAttribute name="color" value="#ffff00"/>
+        </tc:panel>
+      </tc:box>
+
+      <tc:box label="Blue">
+        <tc:panel>
+          <tc:style customClass="demo-data-attribute"/>
+          <tc:dataAttribute name="color" value="#0000ff"/>
+        </tc:panel>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/75-resize/resize.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/75-resize/resize.xhtml
new file mode 100644
index 0000000..fbe4c12
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/75-resize/resize.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/plain.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Resize Event"/>
+
+  <f:facet name="resize">
+    <tc:link id="resize" action="#{resizeController.resize}"/>
+  </f:facet>
+
+  Todo: make nicer example
+  <br/>
+
+  Resizing demo. Resizing the window will call a command (from the resize facet).
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/77-focus/focus.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/77-focus/focus.xhtml
new file mode 100644
index 0000000..e6f4d34
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/77-focus/focus.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Focus"/>
+
+  <p>
+    After a page is loaded, some input element may have the focus, so the user
+    can immediately begin typing information in the form. There is a ruleset to define
+    which element have the focus, at first.
+  </p>
+  <p>
+    The boolean focus attribute of an input field sets the focus to the element explicitly.
+  </p>
+  <p>
+    The priority order is:
+    <ul>
+      <li>error (the first error element gets the focus)</li>
+      <li>auto (the element with the tobago tag attribute focus="true" gets the focus)</li>
+      <li>last (the element from the last request with same id gets the focus, not AJAX)</li>
+      <li>page (use the focusId attribute of the tc:page)</li>
+      <li>first (the first input element (without tabindex=-1) gets the focus, not AJAX)</li>
+    </ul>
+  </p>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/10/sanitize.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/10/sanitize.xhtml
new file mode 100644
index 0000000..1792ba6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/10/sanitize.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+
+  <ui:param name="title" value="Sanitizer"/>
+
+  <p>
+    <b>Todo: </b>Explain the concept of the sanitizer. Short:
+  </p>
+  <ul>
+    <li>Filter all suspicious content from tc:textarea and tc:out with escape=false.</li>
+  </ul>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/20-roles/roles.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/20-roles/roles.xhtml
new file mode 100644
index 0000000..cb5dbbd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/20-roles/roles.xhtml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.roles}"/>
+  <p>It is possible to define roles for users. Based on this roles, components with an <code>action</code> attribute
+    like a button are enabled or disabled for the current user.</p>
+
+  <tc:section label="Basics">
+    <p>To allow an action only for a specific role, you have to annotate a method with
+      <code class="language-java">@RolesAllowed({"role1", "role2"})</code>.
+      This method must not have a parameter.</p>
+    <p>Also, the name of the beans must be distinct.
+      Tobago only read an el expression once and put it in the cache including the annotation.
+      After that, Tobago only work with the cache.</p>
+    <p>There are different ways to define roles for Tomcat and Jetty.</p>
+    <tc:section label="Tomcat">
+      <p>Roles are defined in a tomcat-users.xml within the <code class="language-markup">&lt;tomcat-users></code>
+        tag.</p>
+      <pre><code class="language-markup">&lt;tomcat-users>
+  &lt;user username="guest" password="guest" roles="demo-guest"/>
+  &lt;user username="admin" password="admin" roles="demo-admin"/>
+&lt;/tomcat-users></code></pre>
+    </tc:section>
+    <tc:section label="Jetty">
+      <p>For Jetty, roles are defined in a config file. This config file could be set in the configuration of the
+        jetty-plugin in the pom file.</p>
+      <pre><code class="language-markup"># username: password [,rolename ...]
+guest: guest,demo-guest
+admin: admin,demo-admin</code></pre>
+    </tc:section>
+  </tc:section>
+
+  <tc:section label="Example">
+    <p>In this example there are two content boxes. The left one is for admin users.
+      The right one is for guests and admins.</p>
+    <p>If you run the demo on your local machine, you may change the scope of the
+      <code>RoleController</code> from <code class="language-java">@SessionScoped</code> to
+      <code class="language-java">@ApplicationScoped</code>.
+      In that case, the guest can read the text added by the admin.</p>
+    <tc:segmentLayout medium="6;6">
+      <tc:box label="Admin Box">
+        <p>This is a box only for admins. A text can be added in the inputfield.
+          The submit button is only enabled for admin users.
+          Notice, that the method set in the <code>action</code> attribute of the
+          <code class="language-markup">&lt;tc:button/></code> have the annotation
+          <code class="language-java">@RolesAllowed({"admin"})</code>.</p>
+        <tc:in id="i1" label="Input" value="#{roleController.text}"/>
+        <tc:button label="Submit" action="#{roleController.admin}"/>
+      </tc:box>
+      <tc:box label="Guest Box">
+        <p>This is a box for guests and admins. It displays the text which is set by an admin on the left.
+          You also can hit the logout button to relogin.</p>
+        <tc:out id="o1" label="Output" value="#{roleController.text}"/>
+        <tc:separator/>
+        <tc:form>
+          <tc:button label="Logout" action="#{login.logout}"/>
+        </tc:form>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/content-security-policy.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/content-security-policy.xhtml
new file mode 100644
index 0000000..0d3ec87
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/80-security/content-security-policy.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Content Security Policy"/>
+
+  Tobago supports Content Security Policy (CSP) to prevent cross-site
+  scripting (XSS) and related attacks.
+  <tc:link link="http://www.w3.org/TR/CSP/" label="Specification link"/>.
+  In short: The HTML page doesn't contain any JavaScript or CSS information.
+  All allowed sources for JavaScript, CSS and other resources have to be declared in special header.
+  If you have own renderers or own JavaScript in your application, this code also needs to support SCP, to use this feature.
+
+  <tc:box label="This box may be manipulated by JavaScript">
+    <tc:style maxWidth="400px"/>
+    <tc:panel id="panel">
+      <tc:out value="When you can read this text, it hasn't been manipulated by JavaScript.
+        That means the CSP is working correctly."/>
+    </tc:panel>
+    <script>
+      <![CDATA[
+      function cspDemo() {
+        jQuery(Tobago.Utils.escapeClientId("page:panel")).html(
+            "<span style='color: #ff0000; font-weight: bold;'>Attention: When you can read this text, the content was manipulated by JavaScript."
+            + " It seems, your browser doesn't support CSP!</span>");
+      }
+
+      cspDemo();
+      ]]>
+    </script>
+  </tc:box>
+
+  <h5 class="alert alert-danger">This example is currently not working!</h5>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/90-non-faces-request/non-faces-request.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/90-non-faces-request/non-faces-request.xhtml
new file mode 100644
index 0000000..06a24f3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/90-non-faces-request/non-faces-request.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <ui:param name="title" value="Non-Faces-Request Demo: Start"/>
+
+  <tc:panel>
+
+    <p>
+      This demo works with &lt;f:viewParam>.<br/>
+    </p>
+
+    <p>
+      Use these links from external applications:<br/>
+
+      <a href="#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=0&amp;dswid=#{request.parameterMap['dswid'][0]}">#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=0&amp;dswid=#{request.parameterMap['dswid'][0]}</a><br/>
+      <a href="#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=1&amp;dswid=#{request.parameterMap['dswid'][0]}">#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=1&amp;dswid=#{request.parameterMap['dswid'][0]}</a><br/>
+      <a href="#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=2&amp;dswid=#{request.parameterMap['dswid'][0]}">#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=2&amp;dswid=#{request.parameterMap['dswid'][0]}</a><br/>
+      <a href="#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=3&amp;dswid=#{request.parameterMap['dswid'][0]}">#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=3&amp;dswid=#{request.parameterMap['dswid'][0]}</a><br/>
+      <a href="#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=4&amp;dswid=#{request.parameterMap['dswid'][0]}">#{request.contextPath}/faces/content/30-concept/90-non-faces-request/x-fish-pond.xhtml?fishId=4&amp;dswid=#{request.parameterMap['dswid'][0]}</a><br/>
+    </p>
+
+  </tc:panel>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/90-non-faces-request/x-fish-pond.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/90-non-faces-request/x-fish-pond.xhtml
new file mode 100644
index 0000000..fcf16e4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/90-non-faces-request/x-fish-pond.xhtml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Non-Faces-Request Demo: Fish Pont"/>
+
+  <ui:define name="metadata">
+    <f:metadata>
+      <f:viewParam name="fishId" value="#{fishPond.selectedFishId}"/>
+      <f:event type="preRenderView" listener="#{fishPond.action}"/>
+    </f:metadata>
+  </ui:define>
+
+  <tc:panel id="pond">
+
+    <tc:in label="Selected:" value="#{fishPond.selectedFish}" readonly="true"/>
+
+    <tc:buttons>
+      <tc:button label="random" action="#{fishPond.random}">
+        <f:ajax render="pond :page:header:headerInfo" execute="pond"/>
+      </tc:button>
+      <tc:button label="back to start" action="/content/30-concept/90-non-faces-request/non-faces-request.xhtml"/>
+    </tc:buttons>
+
+  </tc:panel>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/concept.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/concept.xhtml
new file mode 100644
index 0000000..d93351e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/30-concept/concept.xhtml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <ui:param name="title" value="#{demoBundle.concept}"/>
+  <p>In this section the different concepts of Tobago are described
+    like the concept of validation, forms, layouts or access keys.</p>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/10-tx/tx.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/10-tx/tx.xhtml
new file mode 100644
index 0000000..8df860b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/10-tx/tx.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.tx}"/>
+  <p>The TX-library is no longer supported. Use components from the TC-library.</p>
+
+  <tc:section label="Replacements">
+    <p>Most components of the TX-library can be also found in the TC-library.
+      The names are still the same. For example instead of
+      <code class="language-markup">&lt;tx:in></code> and <code class="language-markup">&lt;tx:textarea></code>
+      you should be use
+      <code class="language-markup">&lt;tc:in></code> and <code class="language-markup">&lt;tc:textarea></code>.
+      However, there are a few exceptions described in the following sections.</p>
+
+    <tc:section label="&lt;tx:label>">
+      <p><code class="language-markup">&lt;tx:label></code> is not available anymore.
+        Please use <code class="language-markup">&lt;tc:label></code> or the <code>label</code> attribute instead.</p>
+    </tc:section>
+    <tc:section label="&lt;tx:menuCheckbox> &lt;tx:menuRadio>">
+      <p><code class="language-markup">&lt;tc:menu></code> is deprecated.
+        Use dropdown-menus instead. Have a look at 'Dropdown'-section of the
+        <tc:link label="#{demoBundle.button_link}"
+                 link="/faces/content/20-component/040-command/00-button+link/button+link.xhtml"/> page.</p>
+    </tc:section>
+    <tc:section label="&lt;tx:time">
+      <p><code class="language-markup">&lt;tx:time></code> has no counterpart of the same name.
+        Instead use <code class="language-markup">&lt;tc:date></code>.</p>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/suggest-method.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/suggest-method.test.js
new file mode 100644
index 0000000..7608af9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/suggest-method.test.js
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Deprecated: 'Chile'", function (assert) {
+  var inputString = "Chile";
+  var expectedLength = 7;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:deprecated\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:deprecated");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function () {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function () {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+QUnit.test("Replacement: 'Chile'", function (assert) {
+  var inputString = "Chile";
+  var expectedLength = 7;
+
+  assert.expect(expectedLength + 1);
+  var done = assert.async();
+
+  var $in = jQueryFrame("#page\\:mainForm\\:replacement\\:\\:field");
+  var $suggestions = getSuggestions("#page\\:mainForm\\:replacement");
+
+  $in.val(inputString).trigger('input');
+
+  waitForAjax(function () {
+    $suggestions = jQueryFrame($suggestions.selector);
+    return $suggestions.length == expectedLength;
+  }, function () {
+    $suggestions = jQueryFrame($suggestions.selector);
+
+    assert.equal($suggestions.length, expectedLength);
+    for (i = 0; i < expectedLength; i++) {
+      assert.ok($suggestions.eq(i).find("strong").text().toUpperCase().indexOf(inputString.toUpperCase()) >= 0);
+    }
+
+    done();
+  });
+});
+
+function getSuggestions(id) {
+  return jQueryFrame(Tobago.Utils.escapeClientId(
+          jQueryFrame(id + " .tobago-suggest").attr("id") + "::popup") + " .tt-suggestion");
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/suggest-method.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/suggest-method.xhtml
new file mode 100644
index 0000000..1acc691
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/15-suggest-method/suggest-method.xhtml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.suggest_method} &lt;tc:suggest&gt;"/>
+  <p>The <code>suggestMethod</code> attribute of <code class="language-markup">&lt;tc:suggest/></code>
+    is deprecated.
+    Please use <code class="language-markup">&lt;tc:selectItems/></code> instead.
+    For more examples please have a look at the
+    <tc:link label="#{demoBundle.suggest}" link="/faces/content/20-component/010-input/20-suggest/suggest.xhtml"/>
+    section.</p>
+
+  <tc:section label="Deprecated">
+    <pre><code class="language-markup">&lt;tc:in label="Language">
+  &lt;tc:suggest totalCount="10" suggestMethod="\#{suggestController.getInputSuggestItems}"/>
+&lt;/tc:in></code></pre>
+    <tc:in id="deprecated" label="Language">
+      <tc:suggest totalCount="10" suggestMethod="#{suggestController.getInputSuggestItems}"/>
+    </tc:in>
+  </tc:section>
+
+  <tc:section label="Replacement">
+    <pre><code class="language-markup">&lt;tc:in label="Language">
+  &lt;tc:suggest totalCount="10" query="\#{suggestController.query}">
+    &lt;tc:selectItems value="\#{suggestController.languages}" var="language" itemValue="\#{language}"/>
+  &lt;/tc:suggest>
+&lt;/tc:in></code></pre>
+    <tc:in id="replacement" label="Language">
+      <tc:suggest totalCount="10" query="#{suggestController.query}">
+        <tc:selectItems value="#{suggestController.languages}" var="language" itemValue="#{language}"/>
+      </tc:suggest>
+    </tc:in>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/20-toolBar/toolBar.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/20-toolBar/toolBar.xhtml
new file mode 100644
index 0000000..873611a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/20-toolBar/toolBar.xhtml
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.toolBar} &lt;tc:toolBar>"/>
+  <p><code class="language-markup">&lt;tc:toolBar/></code> and
+    <code class="language-markup">&lt;tc:toolBarCommand/></code> are deprecated.
+    To replace a toolbar in the header of a component use <tc:link label="#{demoBundle.buttons}"
+                                                                   link="/faces/content/20-component/040-command/20-buttons/buttons.xhtml"/> or
+    <tc:link label="#{demoBundle.links}"
+             link="/faces/content/20-component/040-command/25-links/links.xhtml"/> instead.
+    To replace a plain toolbar, use
+    <tc:link label="#{demoBundle.bar}"
+             link="/faces/content/20-component/050-container/60-bar/bar.xhtml"/>.</p>
+
+  <tc:section label="Content Box Header">
+    <p>The first box show the deprecated version of a toolbar.
+      The second and the third one are solutions with #{demoBundle.buttons} and #{demoBundle.links}.</p>
+
+    <p>Instead of <code class="language-markup">&lt;f:facet name="toolBar"/></code>
+      use <code class="language-markup">&lt;f:facet name="bar"/></code>.</p>
+    <p>Instead of <code class="language-markup">&lt;tc:toolBar/></code>
+      use <code class="language-markup">&lt;tc:buttons/></code>
+      or <code class="language-markup">&lt;tc:links/></code>.</p>
+    <p>Instead of <code class="language-markup">&lt;tc:toolBarCommand/></code>
+      use <code class="language-markup">&lt;tc:button/></code>
+      or <code class="language-markup">&lt;tc:link/></code>.</p>
+
+    <tc:box label="#{demoBundle.buttons}">
+      <f:facet name="bar">
+        <tc:buttons>
+          <tc:button label="Text Button"/>
+          <tc:button label="Image Button" image="fa-cube"/>
+          <tc:button label="Dropdown" omit="true">
+            <tc:link label="Action 1"/>
+            <tc:link label="Action 2"/>
+            <tc:link label="Action 3"/>
+          </tc:button>
+        </tc:buttons>
+      </f:facet>
+      <p>Content</p>
+    </tc:box>
+    <tc:box label="#{demoBundle.links}">
+      <f:facet name="bar">
+        <tc:links>
+          <tc:link label="Text Link"/>
+          <tc:link label="Image Link" image="fa-cube"/>
+          <tc:link label="Dropdown" omit="true">
+            <tc:link label="Action 1"/>
+            <tc:link label="Action 2"/>
+            <tc:link label="Action 3"/>
+          </tc:link>
+        </tc:links>
+      </f:facet>
+      <p>Content</p>
+    </tc:box>
+  </tc:section>
+
+  <tc:section label="Plain toolbar">
+    <p>For a plain toolbar use the <code class="language-markup">&lt;tc:bar/></code> tag.</p>
+    <tc:section label="Deprecated">
+      <pre><code class="language-markup">&lt;tc:toolBar>
+  &lt;tc:toolBarCommand label="Text Button"/>
+  &lt;tc:toolBarCommand label="Image Button" image="fa-cube"/>
+  &lt;tc:in placeholder="Search"/>
+&lt;/tc:toolBar></code></pre>
+    </tc:section>
+
+    <tc:section label="#{demoBundle.bar}">
+      <pre><code class="language-markup">&lt;tc:bar>
+  &lt;tc:buttons>
+    &lt;tc:button label="Text Button"/>
+    &lt;tc:button label="Image Button" image="fa-cube"/>
+  &lt;/tc:buttons>
+  &lt;tc:flowLayout textAlign="right">
+    &lt;tc:button label="Dropdown" omit="true"> ... &lt;/tc:button>
+    &lt;tc:in placeholder="Search"/>
+  &lt;/tc:flowLayout>
+&lt;/tc:bar></code></pre>
+      <tc:bar>
+        <tc:buttons>
+          <tc:button label="Text Button"/>
+          <tc:button label="Image Button" image="fa-cube"/>
+        </tc:buttons>
+        <tc:flowLayout textAlign="right">
+          <tc:button label="Dropdown" omit="true">
+            <tc:link label="Action 1"/>
+            <tc:link label="Action 2"/>
+            <tc:link label="Action 3"/>
+          </tc:button>
+          <tc:in placeholder="Search"/>
+        </tc:flowLayout>
+      </tc:bar>
+    </tc:section>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/25-menubar/menubar.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/25-menubar/menubar.xhtml
new file mode 100644
index 0000000..26f7b2d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/25-menubar/menubar.xhtml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.menubar}"/>
+
+  <p><code class="language-markup">&lt;tc:menubar></code>,
+    <code class="language-markup">&lt;tc:menu></code>,
+    <code class="language-markup">&lt;tc:menuCommand></code> and
+    <code class="language-markup">&lt;tc:menuSeparator></code> are deprecated.</p>
+  <p>Use the <code>bar</code> facet in a content box with a
+    <code class="language-markup">&lt;tc:buttons></code> tag instead.
+<br/>
+    For a dropdownmenus have a look at the 'Dropdown' section on the
+    <tc:link label="#{demoBundle.button_link}"
+             link="/faces/content/20-component/040-command/00-button+link/button+link.xhtml"/> page.
+    <br/>
+    To add a separator just use <code class="language-markup">&lt;tc:separator/></code>.</p>
+
+  <tc:section label="Replacement">
+    <pre><code class="language-markup">&lt;tc:box label="Content Box">
+  &lt;f:facet name="bar">
+    &lt;tc:buttons>
+      &lt;tc:button label="One" omit="true"/>
+      &lt;tc:button label="Two" omit="true"/>
+      &lt;tc:button label="Three" omit="true">
+        &lt;tc:command label="Four"/>
+        &lt;tc:command label="Five"/>
+        &lt;tc:separator/>
+        &lt;tc:command label="Six"/>
+      ...</code></pre>
+    <tc:box label="Content Box">
+      <f:facet name="bar">
+        <tc:buttons>
+          <tc:button label="One" omit="true"/>
+          <tc:button label="Two" omit="true"/>
+          <tc:button label="Three" omit="true">
+            <tc:link label="Four"/>
+            <tc:link label="Five"/>
+            <tc:separator/>
+            <tc:link label="Six"/>
+          </tc:button>
+        </tc:buttons>
+      </f:facet>
+      <p>Content</p>
+    </tc:box>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/70-grid-layout/grid-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/70-grid-layout/grid-layout.xhtml
new file mode 100644
index 0000000..42e2fbd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/70-grid-layout/grid-layout.xhtml
@@ -0,0 +1,101 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.grid_layout} (deprecated)"/>
+  <p>The GridLayout is deprecated. Instead you should use FlexLayout or SegmentLayout.
+    In the first section on this page, there is a typical GridLayout example.
+    The second section show how it's done with FlexLayout.</p>
+  <p>Tag Library Documentation:
+    <tc:link label="&lt;tc:gridLayout/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/gridLayout.html"/>
+    |
+    <tc:link label="&lt;tc:flexLayout/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/flexLayout.html"/>
+    |
+    <tc:link label="&lt;tc:segmentLayout/>" image="#{request.contextPath}/image/feather-leaf.png"
+             link="#{demoBundle.tagDocUrl}/#{info.stableVersion}/tld/tc/segmentLayout.html"/></p>
+
+  <tc:section label="GridLayout">
+    <tc:box label="Personal Information">
+      <tc:gridLayout columns="*;*" rows="auto;auto;auto;auto;auto;*">
+        <tc:selectOneChoice label="Salutation">
+          <f:selectItem itemLabel="none"/>
+          <f:selectItem itemLabel="Mr."/>
+          <f:selectItem itemLabel="Mrs."/>
+        </tc:selectOneChoice>
+        <tc:panel/>
+
+        <tc:in label="First Name"/>
+        <tc:in label="Last Name"/>
+
+        <tc:in label="c/o">
+          <tc:span column="2"/>
+        </tc:in>
+
+        <tc:in label="Street"/>
+        <tc:in label="No"/>
+
+        <tc:in label="ZIP"/>
+        <tc:in label="City"/>
+
+        <tc:textarea label="Note">
+          <tc:span column="2"/>
+        </tc:textarea>
+      </tc:gridLayout>
+    </tc:box>
+  </tc:section>
+
+  <tc:section label="FlexLayout">
+    <tc:box label="Personal Information">
+      <tc:flexLayout rows="auto;auto">
+        <tc:flexLayout columns="auto">
+          <tc:selectOneChoice label="Salutation">
+            <f:selectItem itemLabel="none"/>
+            <f:selectItem itemLabel="Mr."/>
+            <f:selectItem itemLabel="Mrs."/>
+          </tc:selectOneChoice>
+        </tc:flexLayout>
+
+        <tc:flexLayout columns="1;1">
+          <tc:in label="First Name"/>
+          <tc:in label="Last Name"/>
+        </tc:flexLayout>
+
+        <tc:in label="c/o"/>
+
+        <tc:flexLayout columns="1;1">
+          <tc:in label="Street"/>
+          <tc:in label="No"/>
+        </tc:flexLayout>
+
+        <tc:flexLayout columns="1;1">
+          <tc:in label="ZIP"/>
+          <tc:in label="City"/>
+        </tc:flexLayout>
+
+        <tc:textarea label="Note"/>
+      </tc:flexLayout>
+    </tc:box>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/deprecated.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/deprecated.xhtml
new file mode 100644
index 0000000..e7463db
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/35-deprecated/deprecated.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <ui:param name="title" value="#{demoBundle.deprecated}"/>
+  <p>This section list all deprecated components with the appropriate solution.</p>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/date.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/date.test.js
new file mode 100644
index 0000000..c9b47b6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/date.test.js
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("inputfield with label", function (assert) {
+  var $dateField = jQueryFrame("#page\\:mainForm\\:dateNoPattern\\:\\:field");
+  var $dateButton = jQueryFrame("#page\\:mainForm\\:dateNoPattern button");
+
+  assert.equal($dateField.val(), "");
+
+  $datepicker = jQueryFrame(".bootstrap-datetimepicker-widget");
+  assert.notOk($datepicker.get(0));
+
+  $dateButton.click();
+
+  $datepicker = jQueryFrame(".bootstrap-datetimepicker-widget");
+  assert.ok($datepicker.get(0));
+
+  assert.notEqual($dateField.val(), "");
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/date.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/date.xhtml
new file mode 100644
index 0000000..ec6c493
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/1040-date/date.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+                xsi:schemaLocation="http://myfaces.apache.org/tobago/component ">
+  <ui:param name="title" value="#{demoBundle.date}"/>
+
+  <tc:date id="dateNoPattern"/>
+  <tc:button label="Submit"/>
+
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/currency.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/currency.xhtml
new file mode 100644
index 0000000..72ca358
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/currency.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page label="Sample with model">
+
+    <tc:messages/>
+
+    <tc:label value="required input"/>
+
+    <tc:selectOneChoice required="true" value="#{selectItemModel.currency}" label="Input:">
+      <tc:selectItem itemLabel="&lt;please select>"/>
+      <tc:selectItems value="#{selectItemModel.availableCurrencies}"/>
+    </tc:selectOneChoice>
+
+    <tc:in readonly="true" value="#{selectItemModel.currency}" label="Model:"/>
+
+    <tc:button label="submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/list-of-objects.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/list-of-objects.xhtml
new file mode 100644
index 0000000..6701e91
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/list-of-objects.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+
+    <tc:messages/>
+
+    <tc:box label="&lt;f:selectItems>">
+
+      <tc:selectOneRadio required="true" value="#{selectItemModel.currency}">
+        <f:selectItems value="#{selectItemModel.availableCurrenciesAsObject}" var="currency"
+                       itemValue="#{currency}" itemLabel="#{currency.displayName}"/>
+      </tc:selectOneRadio>
+
+      <tc:out value="Current value on server: #{selectItemModel.currency.displayName}"/>
+
+    </tc:box>
+
+    <tc:box label="&lt;tc:selectItems>">
+
+    <tc:selectOneRadio required="true" value="#{selectItemModel.currency2}">
+      <tc:selectItems
+          value="#{selectItemModel.availableCurrenciesAsObject}" var="currency"
+          itemValue="#{currency}" itemLabel="#{currency.displayName}"
+          itemImage="#{request.contextPath}/data/#{currency.currencyCode}-14.png"/>
+    </tc:selectOneRadio>
+
+      <tc:out value="Current value on server: #{selectItemModel.currency2.displayName}"/>
+
+    </tc:box>
+
+    <tc:button label="Submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/type-of-literals.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/type-of-literals.xhtml
new file mode 100644
index 0000000..19287ad
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/2000-selectItem/type-of-literals.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page width="700px" height="600px">
+    <tc:gridLayout rows="auto;80px;80px;auto;*" columns="4*;*">
+
+      <tc:panel>
+        <tc:span column="2"/>
+        <tc:messages/>
+      </tc:panel>
+
+      <tc:selectOneListbox value="#{selectItemModel.number}" label="Model: int" labelWidth="160px">
+        <f:selectItem itemValue="1" itemLabel="f:selectItem 1 (literal), works not with JSF 1.1"/>
+        <f:selectItem itemValue="#{selectItemModel.two}" itemLabel="f:selectItem 2 (model)"/>
+        <tc:selectItem itemValue="3" itemLabel="tc:selectItem 3 (literal)"/>
+        <tc:selectItem itemValue="#{selectItemModel.four}" itemLabel="tc:selectItem 4 (model)"/>
+      </tc:selectOneListbox>
+
+      <tc:in readonly="true" value="#{selectItemModel.number}"/>
+
+      <tc:selectOneListbox value="#{selectItemModel.currency}" label="Model: java.util.Currency" labelWidth="160px">
+        <f:selectItem itemValue="TTD" itemLabel="f:selectItem TTD (literal), works not with JSF 1.1 and Sun-RI 1.2"/>
+        <f:selectItem itemValue="#{selectItemModel.usd}" itemLabel="f:selectItem USD (model)"/>
+        <tc:selectItem itemValue="JPY" itemLabel="tc:selectItem JPY (literal)"/>
+        <tc:selectItem itemValue="#{selectItemModel.eur}" itemLabel="tc:selectItem EUR (model)"/>
+      </tc:selectOneListbox>
+
+      <tc:in readonly="true" value="#{selectItemModel.currency}"/>
+
+      <tc:panel/>
+      <tc:button label="submit"/>
+
+      <tc:panel>
+        <tc:span column="2"/>
+      </tc:panel>
+
+    </tc:gridLayout>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/10-sheet-types/sheet-types.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/10-sheet-types/sheet-types.test.js
new file mode 100644
index 0000000..d980419
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/10-sheet-types/sheet-types.test.js
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Column 0: tc:columnSelector", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(0);
+  testWidthHeight(assert, $column, 50, 57, 13, 13);
+});
+
+QUnit.test("Column 1: tc:out", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(1);
+  testWidthHeight(assert, $column, 70, 57, 70, 40);
+});
+
+QUnit.test("Column 2: tc:out", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(2);
+  testWidthHeight(assert, $column, 70, 57, 70, 40);
+});
+
+QUnit.test("Column 3: tc:in", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(3);
+  testWidthHeight(assert, $column, 90, 57, 90, 38);
+});
+
+QUnit.test("Column 4: tc:date", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(4);
+  testWidthHeight(assert, $column, 160, 57, 160, 38);
+});
+
+QUnit.test("Column 5: tc:button", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(5);
+  testWidthHeight(assert, $column, 100, 57, 63, 38);
+});
+
+QUnit.test("Column 6: tc:link", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(6);
+  testWidthHeight(assert, $column, 70, 57, 29, 20);
+});
+
+QUnit.test("Column 7: tc:selectOneChoice", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(7);
+  testWidthHeight(assert, $column, 180, 57, 180, 40);
+});
+
+QUnit.test("Column 8: tc:image", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(8);
+  testWidthHeight(assert, $column, 90, 57, 72, 30);
+});
+
+QUnit.test("Column 9: tc:flexLayout", function(assert) {
+  assert.expect(4);
+
+  var $column = getColumn(9);
+  testWidthHeight(assert, $column, 130, 57, 130, 56);
+});
+
+function testWidthHeight(assert, $column, width, height, childWidth, childHeight) {
+  assert.equal($column.get(0).offsetWidth, width);
+  assert.equal($column.get(0).offsetHeight, height);
+
+  //maximal difference 2px
+  var offsetWidth = $column.children().get(0).offsetWidth;
+  var offsetHeight = $column.children().get(0).offsetHeight;
+  var delta = 2;
+  assert.ok(Math.abs(offsetWidth - childWidth) <= delta,
+      "expected: " + childWidth + " result: " + offsetWidth + " delta: " + delta);
+  assert.ok(Math.abs(offsetHeight - childHeight) <= delta,
+      "expected: " + childHeight + " result: " + offsetHeight + " delta: " + delta);
+}
+
+function getColumn(number) {
+  return jQueryFrame("tr").eq(1).find("td").eq(number);
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/10-sheet-types/sheet-types.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/10-sheet-types/sheet-types.xhtml
new file mode 100644
index 0000000..4dc6b92
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/10-sheet-types/sheet-types.xhtml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet_types}"/>
+  <tc:sheet value="#{sheetController.solarList}" id="sheet" var="luminary"
+            columns="50px;70px;70px;10px;90px;160px;100px;70px;180px;90px;130px"
+            rows="10">
+    <tc:columnSelector/>
+    <tc:column label="&lt;tc:out>" id="c_out">
+      <tc:out value="#{luminary.name}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="&lt;tc:out>" align="right" id="c_out_r">
+      <tc:out value="#{luminary.name}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column id="c_not_rendered" rendered="false">
+      <tc:out value="#{luminary.name}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="&lt;tc:in>" id="c_in">
+      <tc:in value="#{luminary.name}" id="in" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="&lt;tc:date>" id="c_date">
+      <tc:date value="#{luminary.discoverYear}" converter="#{sheetController.yearConverter}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="&lt;tc:button>" id="c_button">
+      <tc:button label="#{luminary.name}"/>
+    </tc:column>
+    <tc:column label="&lt;tc:link>" id="c_link">
+      <tc:link label="#{luminary.name}" link="https://en.wikipedia.org/wiki/#{luminary.name}"/>
+    </tc:column>
+    <tc:column label="&lt;tc:selectOneChoice>" id="c_selectOneChoice">
+      <tc:selectOneChoice labelLayout="skip">
+        <tc:selectItem itemLabel="first" itemValue="1"/>
+        <tc:selectItem itemLabel="second" itemValue="2"/>
+        <tc:selectItem itemLabel="third" itemValue="3"/>
+      </tc:selectOneChoice>
+    </tc:column>
+    <tc:column label="&lt;tc:image>" align="center" id="c_image">
+      <tc:image value="image/alps.png">
+        <tc:style width="72px" height="30px"/>
+      </tc:image>
+    </tc:column>
+    <tc:column label="&lt;tc:flexLayout>" id="c_panel">
+      <tc:flexLayout columns="1*;10px;1*">
+        <tc:in value="1st" labelLayout="skip"/>
+        <tc:out value="/" labelLayout="skip"/>
+        <tc:in value="2nd" labelLayout="skip"/>
+      </tc:flexLayout>
+    </tc:column>
+  </tc:sheet>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/20-1000-entries/1000-entries.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/20-1000-entries/1000-entries.xhtml
new file mode 100644
index 0000000..185ee4a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/20-1000-entries/1000-entries.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.sheet_types}"/>
+  <tc:sheet value="#{sheetController.hugeSolarList}" id="sheet" var="luminary"
+            rows="10" markup="small" >
+    <tc:column label="Name">
+      <tc:out value="#{luminary.name}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="Orbit">
+      <tc:out value="#{luminary.orbit}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="Period (Days)">
+      <tc:out value="#{luminary.period}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="Discoverer">
+      <tc:out value="#{luminary.discoverer}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="Year">
+      <tc:out value="#{luminary.discoverYear}" labelLayout="skip"/>
+    </tc:column>
+  </tc:sheet>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/sheet.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/sheet.xhtml
new file mode 100644
index 0000000..1d7ff42
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/3000-sheet/sheet.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <ui:param name="title" value="TODO"/>
+
+  TODO
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/button+link.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/button+link.test.js
new file mode 100644
index 0000000..3296d71
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/button+link.test.js
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("Standard Action Button", function(assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+
+  var $command = jQueryFrame("#page\\:mainForm\\:standardButtonAction");
+  var $destinationSection = jQueryFrame("#page\\:actionSection");
+  testStandardCommands($command, $destinationSection, assert, done);
+});
+
+QUnit.test("Standard Link Button", function(assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+
+  var $command = jQueryFrame("#page\\:mainForm\\:standardButtonLink");
+  var $destinationSection = jQueryFrame("#page\\:linkSection");
+  testStandardCommands($command, $destinationSection, assert, done);
+});
+
+QUnit.test("Standard Action Link", function(assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+
+  var $command = jQueryFrame("#page\\:mainForm\\:standardLinkAction");
+  var $destinationSection = jQueryFrame("#page\\:actionSection");
+  testStandardCommands($command, $destinationSection, assert, done);
+});
+
+QUnit.test("Standard Link Link", function(assert) {
+  assert.expect(2);
+  var done = assert.async(2);
+
+  var $command = jQueryFrame("#page\\:mainForm\\:standardLinkLink");
+  var $destinationSection = jQueryFrame("#page\\:linkSection");
+  testStandardCommands($command, $destinationSection, assert, done);
+});
+
+function testStandardCommands($command, $destinationSection, assert, done) {
+  var step = 1;
+  $command[0].click();
+
+  jQuery("#page\\:testframe").load(function() {
+    if (step == 1) {
+      $destinationSection = jQueryFrame($destinationSection.selector);
+      assert.equal($destinationSection.length, 1);
+
+      var $back = jQueryFrame("#page\\:back");
+      $back[0].click();
+    } else if (step == 2) {
+      $command = jQueryFrame($command.selector);
+      assert.equal($command.length, 1);
+    }
+    step++;
+    done();
+  });
+}
+
+QUnit.test("Target Action Button", function(assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $command = jQueryFrame("#page\\:mainForm\\:targetButtonAction");
+  var $destinationSection = jQueryTargetFrame("#page\\:actionSection");
+  testTargetCommands($command, $destinationSection, assert, done);
+});
+
+QUnit.test("Target Link Button", function(assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $command = jQueryFrame("#page\\:mainForm\\:targetButtonLink");
+  var $destinationSection = jQueryTargetFrame("#page\\:linkSection");
+  testTargetCommands($command, $destinationSection, assert, done);
+});
+
+QUnit.test("Target Action Link", function(assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $command = jQueryFrame("#page\\:mainForm\\:targetLinkAction");
+  var $destinationSection = jQueryTargetFrame("#page\\:actionSection");
+  testTargetCommands($command, $destinationSection, assert, done);
+});
+
+QUnit.test("Target Link Link", function(assert) {
+  assert.expect(1);
+  var done = assert.async();
+
+  var $command = jQueryFrame("#page\\:mainForm\\:targetLinkLink");
+  var $destinationSection = jQueryTargetFrame("#page\\:linkSection");
+  testTargetCommands($command, $destinationSection, assert, done);
+});
+
+function testTargetCommands($command, $destinationSection, assert, done) {
+  $command[0].click();
+
+  /*
+   * phantomJs don't recognize jQueryFrame("#page\\:mainForm\\:targetFrame").load(),
+   * so the waitForAjax() method is used instead.
+   */
+  waitForAjax(function() {
+    $destinationSection = jQueryTargetFrame($destinationSection.selector);
+    return $destinationSection.length == 1;
+  }, function() {
+    $destinationSection = jQueryTargetFrame($destinationSection.selector);
+    assert.equal($destinationSection.length, 1);
+    done();
+  });
+}
+
+function jQueryTargetFrame(expression) {
+  return jQueryFrame("#page\\:mainForm\\:targetFrame").contents().find(expression);
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/button+link.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/button+link.xhtml
new file mode 100644
index 0000000..fb8e873
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/button+link.xhtml
@@ -0,0 +1,89 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.button_link}"/>
+
+  <tc:section label="Standard">
+    <tc:buttons>
+      <tc:button id="standardButtonAction" label="Action" action="#{buttonLinkController.actionPage}"/>
+      <tc:button id="standardButtonLink" label="Link" link="x-link.xhtml"/>
+    </tc:buttons>
+    <tc:links>
+      <tc:link id="standardLinkAction" label="Action" action="#{buttonLinkController.actionPage}"/>
+      <tc:link id="standardLinkLink" label="Link" link="x-link.xhtml"/>
+    </tc:links>
+    <br/>
+    <br/>
+  </tc:section>
+
+  <tc:section label="Confirmation">
+    <tc:buttons>
+      <tc:button id="confirmationButtonAction" label="Action" action="#{buttonLinkController.actionPage}"
+                 confirmation="Are you sure?"/>
+      <tc:button id="confirmationButtonLink" label="Link" link="x-link.xhtml" confirmation="Are you sure?"/>
+    </tc:buttons>
+    <tc:links>
+      <tc:link id="confirmationLinkAction" label="Action" action="#{buttonLinkController.actionPage}"
+               confirmation="Are you sure?"/>
+      <tc:link id="confirmationLinkLink" label="Link" link="x-link.xhtml"
+               confirmation="Are you sure?"/>
+    </tc:links>
+    <br/>
+    <br/>
+  </tc:section>
+
+  <tc:section label="Target">
+    <tc:buttons>
+      <tc:button id="targetButtonAction" label="Action" action="#{buttonLinkController.actionPage}"
+                 target="targetFrame"/>
+      <tc:button id="targetButtonLink" label="Link" link="x-link.xhtml" target="targetFrame"/>
+    </tc:buttons>
+    <tc:links>
+      <tc:link id="targetLinkAction" label="Action" action="#{buttonLinkController.actionPage}" target="targetFrame"/>
+      <tc:link id="targetLinkLink" label="Link" link="x-link.xhtml" target="targetFrame"/>
+    </tc:links>
+    <br/>
+    <br/>
+    <tc:object id="targetFrame" name="targetFrame">
+      <tc:style width="100%" height="150px"/>
+    </tc:object>
+  </tc:section>
+
+  <tc:section label="JavaScript">
+    <p>Execute JavaScript on click.</p>
+    <tc:link label="JavaScript"/>
+    <tc:button label="JavaScript"/>
+
+    |
+    <tc:link label="OnClick Confirm" disabled="true" link="x-link.xhtml">
+      <f:facet name="confirmation">
+        <tc:out value="Are you sure?"/>
+      </f:facet>
+    </tc:link>
+    <tc:button label="OnClick Confirm" disabled="true" link="x-link.xhtml">
+      <f:facet name="confirmation">
+        <tc:out value="Are you sure?"/>
+      </f:facet>
+    </tc:button>
+    <p>target geht nicht</p>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/x-action.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/x-action.xhtml
new file mode 100644
index 0000000..dc9820b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/x-action.xhtml
@@ -0,0 +1,27 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/plain.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.button_link} &lt;tc:link> &lt;tc:button>"/>
+  <tc:section id="actionSection" label="Action">
+    <p>This page should be accessed by an link/button with <code>action</code> attribute.</p>
+    <tc:button id="back" label="Back" link="button+link.xhtml"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/x-link.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/x-link.xhtml
new file mode 100644
index 0000000..021f844
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/4000-button+link/x-link.xhtml
@@ -0,0 +1,27 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/plain.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.button_link} &lt;tc:link> &lt;tc:button>"/>
+  <tc:section id="linkSection" label="Link">
+    <p>This page should be accessed by an link/button with <code>link</code> attribute.</p>
+    <tc:button id="back" label="Back" link="button+link.xhtml"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/5000-form/sheet-in-form.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/5000-form/sheet-in-form.xhtml
new file mode 100644
index 0000000..eefe88a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/5000-form/sheet-in-form.xhtml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/plain.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:panel id="panel">
+
+  <tc:in required="true" label="Required"/>
+
+  <tc:box id="box" label="Form">
+
+    Here pressing planet names and "Submit 1" should not validate the required field.
+    Only pressing "Submit 2" should validate the required field.
+
+    <tc:form id="form">
+
+      <tc:in required="true" label="Required"/>
+
+      <tc:sheet id="sheet" value="#{sheetController.solarList}" var="object" rows="2">
+        <tc:column label="Name">
+          <tc:out value="#{object.name}"/>
+        </tc:column>
+        <tc:column label="Actions">
+          <tc:buttons>
+            <tc:button label="Submit #0"/>
+            <tc:button label="AJAX (self) #0">
+              <f:ajax />
+            </tc:button>
+            <tc:button label="AJAX (form) #0">
+              <f:ajax render=":::form" execute=":::form"/>
+            </tc:button>
+            <tc:button label="AJAX (panel) #0">
+              <f:ajax render="::::panel" execute="::::panel"/>
+            </tc:button>
+          </tc:buttons>
+        </tc:column>
+        <tc:column label="Input">
+          <tc:in id="in" required="true"/>
+        </tc:column>
+      </tc:sheet>
+
+      <tc:buttons>
+        <tc:button label="Submit #1"/>
+        <tc:button label="AJAX (self) #1">
+          <f:ajax />
+        </tc:button>
+        <tc:button label="AJAX (form) #1">
+          <f:ajax render=":::form" execute=":::form"/>
+        </tc:button>
+        <tc:button label="AJAX (panel) #1">
+          <f:ajax render=":::panel" execute=":::panel"/>
+        </tc:button>
+      </tc:buttons>
+
+    </tc:form>
+  </tc:box>
+
+  <tc:buttons>
+    <tc:button label="Submit #2"/>
+    <tc:button label="AJAX (self) #2">
+      <f:ajax />
+    </tc:button>
+    <tc:button label="AJAX (form) #2">
+      <f:ajax render="::form" execute="::form"/>
+    </tc:button>
+    <tc:button label="AJAX (panel) #2">
+      <f:ajax render="::panel" execute="::panel"/>
+    </tc:button>
+  </tc:buttons>
+
+  <tc:buttons>
+    <tc:button label="Reset" defaultCommand="true" immediate="true"/>
+  </tc:buttons>
+
+  </tc:panel>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/10-rendererBase-getCurrentValue/rendererBase-getCurrentValue.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/10-rendererBase-getCurrentValue/rendererBase-getCurrentValue.test.js
new file mode 100644
index 0000000..0513280
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/10-rendererBase-getCurrentValue/rendererBase-getCurrentValue.test.js
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function test(assert, idSuffix, expectedText) {
+  var $out = jQueryFrame("#page\\:mainForm\\:" + idSuffix);
+  assert.equal($out.text().trim(), expectedText);
+}
+
+QUnit.test("formatted values: out string", function (assert) {
+  test(assert, "outString", "simple string");
+});
+
+QUnit.test("formatted values: out string from method", function (assert) {
+  test(assert, "outStringFromMethod", "HELLO WORLD!");
+});
+
+QUnit.test("formatted values: out date", function (assert) {
+  test(assert, "outDate", "24.07.1969");
+});
+
+QUnit.test("formatted values: out date from method", function (assert) {
+  test(assert, "outDateFromMethod", "24.07.2019");
+});
+
+QUnit.test("formatted values: out currency", function (assert) {
+  test(assert, "outCurrency", "TTD");
+});
+
+QUnit.test("formatted values: out currency from method", function (assert) {
+  test(assert, "outCurrencyFromMethod", "ISK");
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/10-rendererBase-getCurrentValue/rendererBase-getCurrentValue.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/10-rendererBase-getCurrentValue/rendererBase-getCurrentValue.xhtml
new file mode 100644
index 0000000..61613cf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/10-rendererBase-getCurrentValue/rendererBase-getCurrentValue.xhtml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+
+  <ui:param name="title" value="Test: RendererBase.getCurrentValue()"/>
+
+  <tc:out id="outString" labelLayout="none" value="#{currentValueController.string}"/>
+
+  <tc:out id="outStringFromMethod" labelLayout="none" value="#{currentValueController.toUpperCase('Hello world!')}"/>
+
+  <tc:out id="outDate" labelLayout="none" value="#{currentValueController.date}">
+    <f:convertDateTime pattern="dd.MM.yyyy"/>
+  </tc:out>
+
+  <tc:out id="outDateFromMethod" labelLayout="none"
+          value="#{currentValueController.plus50(currentValueController.date)}">
+    <f:convertDateTime pattern="dd.MM.yyyy"/>
+  </tc:out>
+
+  <tc:out id="outCurrency" labelLayout="none" value="#{currentValueController.currency}"/>
+
+  <tc:out id="outCurrencyFromMethod" labelLayout="none" value="#{currentValueController.toCurrency('ISK')}"/>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/ajax-execute.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/ajax-execute.test.js
new file mode 100644
index 0000000..1675dc0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/ajax-execute.test.js
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("ajax excecute", function (assert) {
+  assert.expect(12);
+  var done = assert.async(3);
+  var step = 1;
+
+  var $in1 = jQueryFrame("#page\\:mainForm\\:in1\\:\\:field");
+  var $in2 = jQueryFrame("#page\\:mainForm\\:in2\\:\\:field");
+  var $in3 = jQueryFrame("#page\\:mainForm\\:in3\\:\\:field");
+  var $in4 = jQueryFrame("#page\\:mainForm\\:in4\\:\\:field");
+  var $clearButton = jQueryFrame("#page\\:mainForm\\:clear");
+  var $submitButton = jQueryFrame("#page\\:mainForm\\:submit");
+  var $reloadButton = jQueryFrame("#page\\:mainForm\\:reload");
+
+  $in1.val("a");
+  $in2.val("b");
+  $in3.val("c");
+  $in4.val("d");
+  $clearButton.click();
+
+  jQuery("#page\\:testframe").load(function () {
+    if (step == 1) {
+      $in1 = jQueryFrame($in1.selector);
+      $in2 = jQueryFrame($in2.selector);
+      $in3 = jQueryFrame($in3.selector);
+      $in4 = jQueryFrame($in4.selector);
+      $submitButton = jQueryFrame($submitButton.selector);
+
+      assert.equal($in1.val(), "");
+      assert.equal($in2.val(), "");
+      assert.equal($in3.val(), "");
+      assert.equal($in4.val(), "");
+
+      $in1.val("a");
+      $in2.val("b");
+      $in3.val("c");
+      $in4.val("d");
+
+      $submitButton.click();
+
+      step++;
+      done();
+
+      waitForAjax(function () {
+        $in1 = jQueryFrame($in1.selector);
+        $in2 = jQueryFrame($in2.selector);
+        $in3 = jQueryFrame($in3.selector);
+        $in4 = jQueryFrame($in4.selector);
+        return step == 2
+            && $in1.val() == "a"
+            && $in2.val() == "b"
+            && $in3.val() == "c"
+            && $in4.val() == "";
+      }, function () {
+        $in1 = jQueryFrame($in1.selector);
+        $in2 = jQueryFrame($in2.selector);
+        $in3 = jQueryFrame($in3.selector);
+        $in4 = jQueryFrame($in4.selector);
+        $reloadButton = jQueryFrame($reloadButton.selector);
+
+        assert.equal($in1.val(), "a");
+        assert.equal($in2.val(), "b");
+        assert.equal($in3.val(), "c");
+        assert.equal($in4.val(), "");
+
+        $reloadButton.click();
+
+        step++;
+        done();
+      });
+    } else if (step == 3) {
+      $in1 = jQueryFrame($in1.selector);
+      $in2 = jQueryFrame($in2.selector);
+      $in3 = jQueryFrame($in3.selector);
+      $in4 = jQueryFrame($in4.selector);
+
+      assert.equal($in1.val(), "a");
+      assert.equal($in2.val(), "");
+      assert.equal($in3.val(), "c");
+      assert.equal($in4.val(), "");
+
+      done();
+    }
+  });
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/ajax-execute.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/ajax-execute.xhtml
new file mode 100644
index 0000000..5181656
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/20-ajax-execute/ajax-execute.xhtml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+
+  <ui:param name="title" value="TODO"/>
+
+  This test is for
+  <tc:link
+      label="TOBAGO-1569: AJAX should be independent from Multi-Form concept"
+      link="https://issues.apache.org/jira/browse/TOBAGO-1569"/>.
+
+  <tc:in label="Field 1" id="in1" value="#{executeController.value1}"/>
+  <tc:in label="Field 2" id="in2" value="#{executeController.value2}"/>
+
+  <tc:box id="box" label="Box">
+    <tc:in label="Field 3" id="in3" value="#{executeController.value3}"/>
+    <tc:in label="Field 4" id="in4" value="#{executeController.value4}"/>
+  </tc:box>
+
+  <tc:segmentLayout medium="2;10">
+
+    <tc:button label="1. Clear" action="#{executeController.clear}" id="clear" immediate="true"/>
+    <tc:out value="Sets all 4 values to null"/>
+
+    <tc:button label="2. Manually" omit="true"/>
+    <tc:out value="Fill fields with some values, e.g. a, b, c, d."/>
+
+    <tc:button label="3. Submit" action="#{executeController.action}" id="submit">
+      <f:ajax execute="in1 in3" render="box"/>
+    </tc:button>
+    <tc:out value="Execute field 1 and 3 and render the box.
+      The result is, field 1, 2 and 3 are set and field 4 is cleared.
+      This is, because field 1 and 2 are not rendered (so they are untouched).
+      Field 3 and 4 are rerendered, but only filed 3 has a value, because it was executed
+      in contrast to field 4."/>
+
+    <tc:button label="4. Full Reload" id="reload" immediate="true">
+      <tc:resetInputActionListener/>
+    </tc:button>
+    <tc:out value="Shows values from server.
+      The result is, field 1 and 3 are set and field 2 and 4 is cleared."/>
+
+  </tc:segmentLayout>
+
+</ui:composition>
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/java.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/java.xhtml
new file mode 100644
index 0000000..eca91b5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/50000-java/java.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <ui:param name="title" value="TODO"/>
+
+Testing the Java API, more or less directly (if possible).
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/event.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/event.test.js
new file mode 100644
index 0000000..7ea7120
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/event.test.js
@@ -0,0 +1,364 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("tc:button tc:event - blur", function(assert) {
+  testButtonEvent(assert, "blur");
+});
+
+QUnit.test("tc:button tc:event - click", function(assert) {
+  testButtonEvent(assert, "click");
+});
+
+QUnit.test("tc:button tc:event - dblclick", function(assert) {
+  testButtonEvent(assert, "dblclick");
+});
+
+QUnit.test("tc:button tc:event - focus", function(assert) {
+  testButtonEvent(assert, "focus");
+});
+
+QUnit.test("tc:button f:ajax - blur", function(assert) {
+  testButtonAjax(assert, "blur");
+});
+
+QUnit.test("tc:button f:ajax - click", function(assert) {
+  testButtonAjax(assert, "click");
+});
+
+QUnit.test("tc:button f:ajax - dblclick", function(assert) {
+  testButtonAjax(assert, "dblclick");
+});
+
+QUnit.test("tc:button f:ajax - focus", function(assert) {
+  testButtonAjax(assert, "focus");
+});
+
+QUnit.test("tc:in tc:event - blur", function(assert) {
+  testInEvent(assert, "blur");
+});
+
+QUnit.test("tc:in tc:event - change", function(assert) {
+  testInEvent(assert, "change");
+});
+
+QUnit.test("tc:in tc:event - click", function(assert) {
+  testInEvent(assert, "click");
+});
+
+QUnit.test("tc:in tc:event - dblclick", function(assert) {
+  testInEvent(assert, "dblclick");
+});
+
+QUnit.test("tc:in tc:event - focus", function(assert) {
+  testInEvent(assert, "focus");
+});
+
+QUnit.test("tc:in f:ajax - blur", function(assert) {
+  testInAjax(assert, "blur");
+});
+
+QUnit.test("tc:in f:ajax - change", function(assert) {
+  testInAjax(assert, "change");
+});
+QUnit.test("tc:in f:ajax - click", function(assert) {
+  testInAjax(assert, "click");
+});
+QUnit.test("tc:in f:ajax - dblclick", function(assert) {
+  testInAjax(assert, "dblclick");
+});
+QUnit.test("tc:in f:ajax - focus", function(assert) {
+  testInAjax(assert, "focus");
+});
+
+QUnit.test("tc:row tc:event - click", function(assert) {
+  testRowEvent(assert, "click");
+});
+
+QUnit.test("tc:row tc:event - dblclick", function(assert) {
+  testRowEvent(assert, "dblclick");
+});
+
+QUnit.test("tc:row f:ajax - click", function(assert) {
+  testRowAjax(assert, "click");
+});
+
+QUnit.test("tc:row f:ajax - dblclick", function(assert) {
+  testRowAjax(assert, "dblclick");
+});
+
+function testButtonEvent(assert, eventName) {
+  testEvent(assert, "button", function() {
+    return jQueryFrame("#page\\:mainForm\\:buttonevent" + eventName + "\\:\\:command");
+  }, eventName, true, true, false, false, false);
+}
+
+function testButtonAjax(assert, eventName) {
+  testAjax(assert, "button", function() {
+    return jQueryFrame("#page\\:mainForm\\:buttonajax" + eventName);
+  }, eventName, false, false, true, false, false);
+}
+
+function testInEvent(assert, eventName) {
+  testEvent(assert, "in", function() {
+    var $inputField = jQueryFrame("#page\\:mainForm\\:inevent" + eventName + "\\:\\:field");
+    var newValue = "hello";
+    if (newValue == $inputField.val()) {
+      newValue = "hi there";
+    }
+    $inputField.val(newValue);
+    return $inputField;
+  }, eventName, true, true, false, true, false);
+}
+
+function testInAjax(assert, eventName) {
+  testAjax(assert, "in", function() {
+    var $inputField = jQueryFrame("#page\\:mainForm\\:inajax" + eventName + "\\:\\:field");
+    var newValue = "hello";
+    if (newValue == $inputField.val()) {
+      newValue = "hi there";
+    }
+    $inputField.val(newValue);
+    return $inputField;
+  }, eventName, false, false, true, true, false);
+}
+
+function testRowEvent(assert, eventName) {
+  var newSelectedPlanet = "Venus";
+  testEvent(assert, "row", function() {
+    var $row = jQueryFrame("#page\\:mainForm\\:sheetevent" + eventName + "\\:1\\:selectPlanet");
+    if (getSelectedPlanet() == newSelectedPlanet) {
+      $row = jQueryFrame("#page\\:mainForm\\:sheetevent" + eventName + "\\:4\\:selectPlanet");
+      newSelectedPlanet = "Jupiter";
+    }
+    return $row;
+  }, eventName, true, false, false, false, true);
+}
+
+function testRowAjax(assert, eventName) {
+  var newSelectedPlanet = "Venus";
+  testAjax(assert, "row", function() {
+    var $row = jQueryFrame("#page\\:mainForm\\:sheetajax" + eventName + "\\:1\\:selectPlanet");
+    if (getSelectedPlanet() == newSelectedPlanet) {
+      $row = jQueryFrame("#page\\:mainForm\\:sheetajax" + eventName + "\\:4\\:selectPlanet");
+      newSelectedPlanet = "Jupiter";
+    }
+    return $row;
+  }, eventName, false, false, false, false, true);
+}
+
+function testEvent(assert, componentName, componentFunc, event,
+                   incAction, incActionListener, incAjaxListener, incValueChangeListener, changePlanet) {
+  assert.expect(6);
+  var changeActiveComponent = jQueryFrame("#page\\:mainForm\\:compTestSection > div > h1 > span").text()
+      != "<tc:" + componentName + ">";
+  var done = assert.async(1 + changeActiveComponent);
+
+  var oldActionCount;
+  var oldActionListenerCount;
+  var oldAjaxListenerCount;
+  var oldValueChangeListenerCount;
+  var oldTimestamp;
+  var oldPlanet;
+
+  if (changeActiveComponent) {
+    activateComponent(componentName);
+    var step = 1;
+
+    jQuery("#page\\:testframe").load(function() {
+      if (step == 1) {
+        oldActionCount = getActionCount();
+        oldActionListenerCount = getActionListenerCount();
+        oldAjaxListenerCount = getAjaxListenerCount();
+        oldValueChangeListenerCount = getValueChangeListenerCount();
+        oldTimestamp = getTimestamp();
+        oldPlanet = getSelectedPlanet();
+
+        componentFunc().trigger(event);
+      } else if (step == 2) {
+        validateEvent(assert, oldActionCount, oldActionListenerCount, oldAjaxListenerCount,
+            oldValueChangeListenerCount, oldTimestamp, oldPlanet, incAction, incActionListener, incAjaxListener,
+            incValueChangeListener, changePlanet);
+      }
+      step++;
+      done();
+    });
+  } else {
+    oldActionCount = getActionCount();
+    oldActionListenerCount = getActionListenerCount();
+    oldAjaxListenerCount = getAjaxListenerCount();
+    oldValueChangeListenerCount = getValueChangeListenerCount();
+    oldTimestamp = getTimestamp();
+    oldPlanet = getSelectedPlanet();
+
+    componentFunc().trigger(event);
+
+    jQuery("#page\\:testframe").load(function() {
+      validateEvent(assert, oldActionCount, oldActionListenerCount, oldAjaxListenerCount, oldValueChangeListenerCount,
+          oldTimestamp, oldPlanet, incAction, incActionListener, incAjaxListener, incValueChangeListener, changePlanet);
+
+      done();
+    });
+  }
+}
+
+function validateEvent(assert, oldActionCount, oldActionListenerCount, oldAjaxListenerCount,
+                       oldValueChangeListenerCount, oldTimestamp, oldPlanet, incAction, incActionListener,
+                       incAjaxListener, incValueChangeListener, changePlanet) {
+  var newActionCount = getActionCount();
+  var newActionListenerCount = getActionListenerCount();
+  var newAjaxListenerCount = getAjaxListenerCount();
+  var newValueChangeListenerCount = getValueChangeListenerCount();
+  var newTimestamp = getTimestamp();
+  var newPlanet = getSelectedPlanet();
+
+  assert.equal(newActionCount, oldActionCount + incAction, "action");
+  assert.equal(newActionListenerCount, oldActionListenerCount + incActionListener, "actionListener");
+  assert.equal(newAjaxListenerCount, oldAjaxListenerCount + incAjaxListener, "ajaxListener");
+  assert.equal(newValueChangeListenerCount, oldValueChangeListenerCount + incValueChangeListener,
+      "valueChangeListener");
+  assert.ok(newTimestamp > oldTimestamp, "timestamp");
+  if (changePlanet) {
+    assert.notEqual(newPlanet, oldPlanet, "selectedPlanet");
+  } else {
+    assert.equal(newPlanet, oldPlanet, "selectedPlanet");
+  }
+}
+
+function testAjax(assert, componentName, componentFunc, event,
+                  incAction, incActionListener, incAjaxListener, incValueChangeListener, changePlanet) {
+  assert.expect(6);
+  var changeActiveComponent = jQueryFrame("#page\\:mainForm\\:compTestSection > div > h1 > span").text()
+      != "<tc:" + componentName + ">";
+  var done = assert.async(1 + changeActiveComponent);
+
+  var oldActionCount;
+  var oldActionListenerCount;
+  var oldAjaxListenerCount;
+  var oldValueChangeListenerCount;
+  var oldTimestamp;
+  var oldPlanet;
+
+  if (changeActiveComponent) {
+    activateComponent(componentName);
+    var step = 1;
+
+    jQuery("#page\\:testframe").load(function() {
+      if (step == 1) {
+        oldActionCount = getActionCount();
+        oldActionListenerCount = getActionListenerCount();
+        oldAjaxListenerCount = getAjaxListenerCount();
+        oldValueChangeListenerCount = getValueChangeListenerCount();
+        oldTimestamp = getTimestamp();
+        oldPlanet = getSelectedPlanet();
+
+        componentFunc().trigger(event);
+
+        validateAjax(assert, done, oldActionCount, oldActionListenerCount, oldAjaxListenerCount,
+            oldValueChangeListenerCount, oldTimestamp, oldPlanet, incAction, incActionListener, incAjaxListener,
+            incValueChangeListener, changePlanet);
+      }
+      step++;
+      done();
+    });
+  } else {
+    oldActionCount = getActionCount();
+    oldActionListenerCount = getActionListenerCount();
+    oldAjaxListenerCount = getAjaxListenerCount();
+    oldValueChangeListenerCount = getValueChangeListenerCount();
+    oldTimestamp = getTimestamp();
+    oldPlanet = getSelectedPlanet();
+
+    componentFunc().trigger(event);
+
+    validateAjax(assert, done, oldActionCount, oldActionListenerCount, oldAjaxListenerCount,
+        oldValueChangeListenerCount, oldTimestamp, oldPlanet, incAction, incActionListener, incAjaxListener,
+        incValueChangeListener, changePlanet);
+  }
+}
+
+function validateAjax(assert, done, oldActionCount, oldActionListenerCount, oldAjaxListenerCount,
+                      oldValueChangeListenerCount, oldTimestamp, oldPlanet, incAction, incActionListener,
+                      incAjaxListener, incValueChangeListener, changePlanet) {
+  waitForAjax(function() {
+    var newActionCount = getActionCount();
+    var newActionListenerCount = getActionListenerCount();
+    var newAjaxListenerCount = getAjaxListenerCount();
+    var newValueChangeListenerCount = getValueChangeListenerCount();
+    var newTimestamp = getTimestamp();
+    var newPlanet = getSelectedPlanet();
+
+    return newActionCount == (oldActionCount + incAction)
+    && newActionListenerCount == (oldActionListenerCount + incActionListener)
+    && newAjaxListenerCount == (oldAjaxListenerCount + incAjaxListener)
+    && newValueChangeListenerCount == (oldValueChangeListenerCount + incValueChangeListener)
+    && newTimestamp > oldTimestamp
+    && changePlanet ? newPlanet != oldPlanet : newPlanet == oldPlanet;
+  }, function() {
+    var newActionCount = getActionCount();
+    var newActionListenerCount = getActionListenerCount();
+    var newAjaxListenerCount = getAjaxListenerCount();
+    var newValueChangeListenerCount = getValueChangeListenerCount();
+    var newTimestamp = getTimestamp();
+    var newPlanet = getSelectedPlanet();
+
+    assert.equal(newActionCount, oldActionCount + incAction, "action");
+    assert.equal(newActionListenerCount, oldActionListenerCount + incActionListener, "actionListener");
+    assert.equal(newAjaxListenerCount, oldAjaxListenerCount + incAjaxListener, "ajaxListener");
+    assert.equal(newValueChangeListenerCount, oldValueChangeListenerCount + incValueChangeListener,
+        "valueChangeListener");
+    assert.ok(newTimestamp > oldTimestamp, "timestamp");
+    if (changePlanet) {
+      assert.notEqual(newPlanet, oldPlanet, "selectedPlanet");
+    } else {
+      assert.equal(newPlanet, oldPlanet, "selectedPlanet");
+    }
+
+    done();
+  }, 3000);
+}
+
+function getActionCount() {
+  return parseInt(jQueryFrame("#page\\:mainForm\\:outAction span").text());
+}
+
+function getActionListenerCount() {
+  return parseInt(jQueryFrame("#page\\:mainForm\\:outActionListener span").text());
+}
+
+function getAjaxListenerCount() {
+  return parseInt(jQueryFrame("#page\\:mainForm\\:outAjaxListener span").text());
+}
+
+function getValueChangeListenerCount() {
+  return parseInt(jQueryFrame("#page\\:mainForm\\:outValueChangeListener span").text());
+}
+
+function getTimestamp() {
+  return parseInt(jQueryFrame("#page\\:mainForm\\:outTimestamp span").text());
+}
+
+function getSelectedPlanet() {
+  return jQueryFrame("#page\\:mainForm\\:inPlanet\\:\\:field").val()
+}
+
+function activateComponent(componentName) {
+  jQueryFrame("#page\\:mainForm\\:componentTable .tobago-sheet-row").each(function() {
+    if (jQuery(this).find("td").eq(0).find("span").text() == componentName) {
+      this.click();
+    }
+  });
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/event.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/event.xhtml
new file mode 100644
index 0000000..6608ce0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/event.xhtml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:c="http://java.sun.com/jsp/jstl/core">
+  <ui:param name="title" value="&lt;tc:event>"/>
+  <tc:box id="metrics" label="Metrics" rendered="#{eventController.selectedComponent != null}">
+    <f:facet name="bar">
+      <tc:button label="Reset" action="#{eventController.reset}"/>
+    </f:facet>
+    <tc:out id="outAction" label="Action" value="#{eventController.actionCount}"/>
+    <tc:out id="outActionListener" label="ActionListener" value="#{eventController.actionListenerCount}"/>
+    <tc:out id="outAjaxListener" label="AjaxListener" value="#{eventController.ajaxListenerCount}"/>
+    <tc:out id="outValueChangeListener" label="ValueChange-Listener"
+            value="#{eventController.valueChangeListenerCount}"/>
+    <tc:separator/>
+    <tc:out id="outTimestamp" label="Timestamp" value="#{eventController.currentTimestamp}"/>
+    <tc:in id="inPlanet" label="Selected planet" value="#{eventController.selectedPlanet}"/>
+  </tc:box>
+
+  <tc:section id="compTestSection" label="&lt;tc:#{eventController.selectedComponent.tagName}>"
+              rendered="#{eventController.selectedComponent != null}">
+    <tc:segmentLayout medium="6;6">
+      <tc:box label="&lt;tc:event>">
+        <c:forEach items="#{eventController.selectedComponent.eventNames}" var="event">
+          <ui:include src="#{'x-event-'.concat(eventController.selectedComponent.tagName).concat('.xhtml')}">
+            <ui:param name="type" value="event"/>
+            <ui:param name="event" value="#{event}"/>
+          </ui:include>
+        </c:forEach>
+      </tc:box>
+      <tc:box label="&lt;f:ajax>">
+        <c:forEach items="#{eventController.selectedComponent.eventNames}" var="event">
+          <ui:include src="#{'x-event-'.concat(eventController.selectedComponent.tagName).concat('.xhtml')}">
+            <ui:param name="type" value="ajax"/>
+            <ui:param name="event" value="#{event}"/>
+          </ui:include>
+        </c:forEach>
+      </tc:box>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:separator/>
+  <p>click events = click, dblclick<br/>
+    focus events = focus, blur<br/>
+    mouse events = mousedown, mousemove, mouseout, mouseover, mouseup<br/>
+    key events = keydown, keypress, keyup</p>
+  <tc:sheet id="componentTable" value="#{eventController.eventsOnComponents}" var="comp" markup="small">
+    <tc:column label="Tag Name">
+      <tc:out value="#{comp.tagName}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="change" align="center"
+               markup="#{comp.changeEvent == 'x' ? 'lightgreen' : comp.changeEvent == '-' ? 'lightred' : ''}">
+      <tc:out value="#{comp.changeEvent}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="click events" align="center"
+               markup="#{comp.clickEvents == 'x' ? 'lightgreen' : comp.clickEvents == '-' ? 'lightred' : ''}">
+      <tc:out value="#{comp.clickEvents}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="focus events" align="center"
+               markup="#{comp.focusEvents == 'x' ? 'lightgreen' : comp.focusEvents == '-' ? 'lightred' : ''}">
+      <tc:out value="#{comp.focusEvents}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="mouse events" align="center"
+               markup="#{comp.mouseEvents == 'x' ? 'lightgreen' : comp.mouseEvents == '-' ? 'lightred' : ''}">
+      <tc:out value="#{comp.mouseEvents}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="key events" align="center"
+               markup="#{comp.keyEvents == 'x' ? 'lightgreen' : comp.keyEvents == '-' ? 'lightred' : ''}">
+      <tc:out value="#{comp.keyEvents}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="select" align="center"
+               markup="#{comp.selectEvent == 'x' ? 'lightgreen' : comp.selectEvent == '-' ? 'lightred' : ''}">
+      <tc:out value="#{comp.selectEvent}" labelLayout="skip"/>
+    </tc:column>
+    <tc:column label="special events">
+      <tc:out value="#{comp.specialEvents}" labelLayout="skip"/>
+    </tc:column>
+    <tc:row id="selectComponent">
+      <tc:event event="click" actionListener="#{eventController.selectComponent}"/>
+    </tc:row>
+  </tc:sheet>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-bar.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-bar.xhtml
new file mode 100644
index 0000000..dfbff88
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-bar.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <tc:section label="#{event}">
+    <tc:bar id="bar#{type}#{event}"></tc:bar>
+    <p>Not implemented yet!</p>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-button.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-button.xhtml
new file mode 100644
index 0000000..657b54d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-button.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <tc:section label="#{event}">
+    <tc:button id="button#{type}#{event}" label="Button">
+      <ui:include src="x-event-component-content.xhtml">
+        <ui:param name="type" value="#{type}"/>
+        <ui:param name="event" value="#{event}"/>
+      </ui:include>
+    </tc:button>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-component-content.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-component-content.xhtml
new file mode 100644
index 0000000..c363e86
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-component-content.xhtml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:c="http://java.sun.com/jsp/jstl/core">
+  <c:if test="#{type=='event'}">
+    <c:if test="#{event=='blur'}">
+      <tc:event event="blur" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='change'}">
+      <tc:event event="change" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='click'}">
+      <tc:event event="click" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='complete'}">
+      <tc:event event="complete" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='dblclick'}">
+      <tc:event event="dblclick" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='focus'}">
+      <tc:event event="focus" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='keydown'}">
+      <tc:event event="keydown" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='keypress'}">
+      <tc:event event="keypress" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='keyup'}">
+      <tc:event event="keyup" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='load'}">
+      <tc:event event="load" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='mousedown'}">
+      <tc:event event="mousedown" action="#{eventController.action}"
+                actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='mousemove'}">
+      <tc:event event="mousemove" action="#{eventController.action}"
+                actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='mouseout'}">
+      <tc:event event="mouseout" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='mouseover'}">
+      <tc:event event="mouseover" action="#{eventController.action}"
+                actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='mouseup'}">
+      <tc:event event="mouseup" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='resize'}">
+      <tc:event event="resize" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+    <c:if test="#{event=='select'}">
+      <tc:event event="select" action="#{eventController.action}" actionListener="#{eventController.actionListener}"/>
+    </c:if>
+  </c:if>
+  <c:if test="#{type=='ajax'}">
+    <c:if test="#{event=='blur'}">
+      <f:ajax event="blur" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='change'}">
+      <f:ajax event="change" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='click'}">
+      <f:ajax event="click" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='complete'}">
+      <f:ajax event="complete" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='dblclick'}">
+      <f:ajax event="dblclick" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='focus'}">
+      <f:ajax event="focus" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='keydown'}">
+      <f:ajax event="keydown" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='keypress'}">
+      <f:ajax event="keypress" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='keyup'}">
+      <f:ajax event="keyup" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='load'}">
+      <f:ajax event="load" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='mousedown'}">
+      <f:ajax event="mousedown" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='mousemove'}">
+      <f:ajax event="mousemove" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='mouseout'}">
+      <f:ajax event="mouseout" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='mouseover'}">
+      <f:ajax event="mouseover" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='mouseup'}">
+      <f:ajax event="mouseup" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='resize'}">
+      <f:ajax event="resize" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+    <c:if test="#{event=='select'}">
+      <f:ajax event="select" render="metrics" listener="#{eventController.ajaxListener}"/>
+    </c:if>
+  </c:if>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-in.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-in.xhtml
new file mode 100644
index 0000000..f4b7db4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-in.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <tc:section label="#{event}">
+    <tc:in id="in#{type}#{event}" valueChangeListener="#{eventController.valueChangeListener}">
+      <ui:include src="x-event-component-content.xhtml">
+        <ui:param name="type" value="#{type}"/>
+        <ui:param name="event" value="#{event}"/>
+      </ui:include>
+    </tc:in>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-row.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-row.xhtml
new file mode 100644
index 0000000..385dda0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-row.xhtml
@@ -0,0 +1,156 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:c="http://java.sun.com/jsp/jstl/core"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <tc:section label="#{event}">
+    <tc:sheet id="sheet#{type}#{event}" value="#{eventController.planets}" var="planet" markup="small">
+      <tc:style maxHeight="200px"/>
+      <tc:column label="Planet">
+        <tc:out value="#{planet.name}" labelLayout="skip"/>
+      </tc:column>
+      <tc:row id="selectPlanet">
+        <c:if test="#{type=='event'}">
+          <c:if test="#{event=='blur'}">
+            <tc:event event="blur" action="#{eventController.action}" actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='change'}">
+            <tc:event event="change" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='click'}">
+            <tc:event event="click" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='complete'}">
+            <tc:event event="complete" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='dblclick'}">
+            <tc:event event="dblclick" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='focus'}">
+            <tc:event event="focus" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='keydown'}">
+            <tc:event event="keydown" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='keypress'}">
+            <tc:event event="keypress" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='keyup'}">
+            <tc:event event="keyup" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='load'}">
+            <tc:event event="load" action="#{eventController.action}" actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mousedown'}">
+            <tc:event event="mousedown" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mousemove'}">
+            <tc:event event="mousemove" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mouseout'}">
+            <tc:event event="mouseout" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mouseover'}">
+            <tc:event event="mouseover" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mouseup'}">
+            <tc:event event="mouseup" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='resize'}">
+            <tc:event event="resize" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='select'}">
+            <tc:event event="select" action="#{eventController.action}"
+                      actionListener="#{eventController.selectPlanet}"/>
+          </c:if>
+        </c:if>
+        <c:if test="#{type=='ajax'}">
+          <c:if test="#{event=='blur'}">
+            <f:ajax event="blur" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='change'}">
+            <f:ajax event="change" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='click'}">
+            <f:ajax event="click" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='complete'}">
+            <f:ajax event="complete" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='dblclick'}">
+            <f:ajax event="dblclick" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='focus'}">
+            <f:ajax event="focus" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='keydown'}">
+            <f:ajax event="keydown" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='keypress'}">
+            <f:ajax event="keypress" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='keyup'}">
+            <f:ajax event="keyup" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='load'}">
+            <f:ajax event="load" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mousedown'}">
+            <f:ajax event="mousedown" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mousemove'}">
+            <f:ajax event="mousemove" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mouseout'}">
+            <f:ajax event="mouseout" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mouseover'}">
+            <f:ajax event="mouseover" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='mouseup'}">
+            <f:ajax event="mouseup" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='resize'}">
+            <f:ajax event="resize" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+          <c:if test="#{event=='select'}">
+            <f:ajax event="select" render=":page:mainForm:metrics" listener="#{eventController.selectPlanet}"/>
+          </c:if>
+        </c:if>
+      </tc:row>
+    </tc:sheet>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-textarea.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-textarea.xhtml
new file mode 100644
index 0000000..76f3be5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/6000-event/x-event-textarea.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <tc:section label="#{event}">
+    <tc:textarea id="textarea#{type}#{event}" valueChangeListener="#{eventController.valueChangeListener}">
+      <ui:include src="x-event-component-content.xhtml">
+        <ui:param name="type" value="#{type}"/>
+        <ui:param name="event" value="#{event}"/>
+      </ui:include>
+    </tc:textarea>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/4000-button+link/button+link.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/4000-button+link/button+link.xhtml
new file mode 100644
index 0000000..bf50ca8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/4000-button+link/button+link.xhtml
@@ -0,0 +1,73 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.button_link} &lt;tc:link> &lt;tc:button>"/>
+  <tc:section label="&lt;button> - &lt;a>">
+    <p>The left link is rendered as a <code>&lt;button></code>, the right side is rendered as an <code>&lt;a></code>.
+      Both representations have to be similar.</p>
+    <tc:segmentLayout extraSmall="6;6">
+      <tc:flexLayout columns="auto;auto" id="fl1">
+        <tc:in id="action"/>
+        <tc:link label="actionLink" action="#{buttonLinkController.linkToComponentsRoot}"/>
+      </tc:flexLayout>
+
+      <tc:flexLayout columns="auto;auto" id="fl2">
+        <tc:out label="label" value="value"/>
+        <tc:in id="href"/>
+        <tc:link label="hrefLink" link="https://www.apache.com/"/>
+      </tc:flexLayout>
+    </tc:segmentLayout>
+  </tc:section>
+
+  <tc:section label="New Tab">
+    <p>Open a new tab on each link. Make sure you test the confirmation-link with "OK" and "Cancel".</p>
+    <ul>
+      <li>Right-click -> New Tab</li>
+      <li>Middle-click</li>
+      <li>CMD/CTRL + Left-click</li>
+    </ul>
+
+    <tc:buttons>
+      <tc:button id="standardButton" label="Standard" link="https://www.apache.org/"/>
+      <tc:button id="confirmationButton" label="Confirmation" link="https://www.apache.org/"
+                 confirmation="Are you sure?"/>
+      <tc:button id="targetFrameButton" label="Target: Frame" link="https://www.apache.org/" target="targetFrame"/>
+      <tc:button id="targetBlankButton" label="Target: _blank" link="https://www.apache.org/" target="_blank"/>
+    </tc:buttons>
+    <tc:links>
+      <tc:link id="standardLink" label="Standard" link="https://www.apache.org/"/>
+      <tc:link id="confirmationLink" label="Confirmation" link="https://www.apache.org/"
+               confirmation="Are you sure?"/>
+      <tc:link id="targetFrameLink" label="Target: Frame" link="https://www.apache.org/" target="targetFrame"/>
+      <tc:link id="targetBlankLink" label="Target: _blank" link="https://www.apache.org/" target="_blank"/>
+    </tc:links>
+    <br/>
+    <br/>
+    <tc:button id="resetTarget" label="Reset Target Frame">
+      <f:ajax render="targetFrame"/>
+    </tc:button>
+    <tc:object id="targetFrame" name="targetFrame">
+      <tc:style width="100%" height="300px"/>
+    </tc:object>
+  </tc:section>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/5000-lengthOfInputs/lengthOfInputs.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/5000-lengthOfInputs/lengthOfInputs.xhtml
new file mode 100644
index 0000000..359772a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/5000-lengthOfInputs/lengthOfInputs.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="#{demoBundle.date} &lt;tc:date&gt;"/>
+  <tc:in label="In"/>
+  <tc:textarea label="Text Area"/>
+  <tc:date label="Date"/>
+  <tc:file label="File"/>
+  <tc:in label="Input Group">
+    <f:facet name="after">
+      <tc:button label="Click" omit="true"/>
+    </f:facet>
+  </tc:in>
+
+  <!-- TODO: write a test -->
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/manual.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/manual.xhtml
new file mode 100644
index 0000000..f8e5344
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/60000-manual/manual.xhtml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.manual}"/>
+  <p>This section contain manual tests, which are not covered by QUnitTests.</p>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/7000-layout/markup-spread-flex.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/7000-layout/markup-spread-flex.xhtml
new file mode 100644
index 0000000..081d21e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/7000-layout/markup-spread-flex.xhtml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view locale="#{clientConfigController.locale}"
+        xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:ui="http://java.sun.com/jsf/facelets">
+  <tc:page markup="spread" label="Test" id="page">
+
+    <tc:flexLayout rows="1;1">
+      <tc:style height="100%"/>
+
+      <tc:box label="Box 1">
+
+        <tc:in label="Name" required="true">
+          <f:facet name="after">
+            <tc:button label="Submit" defaultCommand="true" />
+          </f:facet>
+        </tc:in>
+
+      </tc:box>
+
+      <tc:box label="Box 2">
+
+      </tc:box>
+
+    </tc:flexLayout>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/7000-layout/markup-spread-grid.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/7000-layout/markup-spread-grid.xhtml
new file mode 100644
index 0000000..45c39d6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/7000-layout/markup-spread-grid.xhtml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view locale="#{clientConfigController.locale}"
+        xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:ui="http://java.sun.com/jsf/facelets">
+  <tc:page markup="spread" label="Test" id="page">
+
+    <tc:gridLayout rows="1*;1*">
+      <tc:style height="100%"/>
+
+      <tc:box label="Box 1">
+
+        <tc:in label="Name" required="true">
+          <f:facet name="after">
+            <tc:button label="Submit" defaultCommand="true" />
+          </f:facet>
+        </tc:in>
+
+      </tc:box>
+
+      <tc:box label="Box 2">
+
+      </tc:box>
+
+    </tc:gridLayout>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/test.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/test.xhtml
new file mode 100644
index 0000000..6a0ab97
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/content/40-test/test.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <ui:param name="title" value="TODO"/>
+
+TODO
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/404.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/404.xhtml
new file mode 100644
index 0000000..1bbadc6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/404.xhtml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core">
+  <ui:param name="title" value="Error 404"/>
+  <tc:messages/>
+  <tc:out id="pageNotFoundMessage" value="The page was not found!"/>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/error.test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/error.test.js
new file mode 100644
index 0000000..2ec4c37
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/error.test.js
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+QUnit.test("has no exception", function (assert) {
+  var $error = jQueryFrame("#page\\:errorSection .tobago-section-header span");
+  assert.notEqual($error.text(), "An error has occurred!");
+});
+
+QUnit.test("has no 404", function (assert) {
+  var $error404 = jQueryFrame("#page\\:mainForm\\:pageNotFoundMessage span");
+  assert.notEqual($error404.text(), "The page was not found!");
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/exception.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/exception.xhtml
new file mode 100644
index 0000000..d7dde3c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/error/exception.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/plain.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="Sorry, an error has occured!"/>
+
+    <tc:messages/>
+    <tc:section id="errorSection" label="An error has occurred!">
+      <!-- TODO
+      <tc:out value="#{exceptionContext.exception}" escape="false"/>
+
+
+      <%!
+        public static String exceptionToString(Throwable exception) {
+          if (exception == null) {
+            return "No Exception available!";
+          }
+          StringBuilder builder = new StringBuilder();
+          builder.append("<pre>");
+          StringWriter stringWriter = new StringWriter();
+          exception.printStackTrace(new PrintWriter(stringWriter));
+          builder.append(stringWriter.toString());
+          builder.append("</pre>");
+          return builder.toString();
+        }
+      %>
+      <%
+        request.setAttribute("exceptionText", exceptionToString(exception));
+      %>
+-->
+      <pre>
+        <tc:out value="#{exceptionController.stackTrace}"/>
+      </pre>
+    </tc:section>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/icon/favicon.ico b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/icon/favicon.ico
new file mode 100644
index 0000000..f0c22ad
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/icon/favicon.ico differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/alps.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/alps.png
new file mode 100644
index 0000000..25a1f8c
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/alps.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/charlotteville/theme-photo.jpg b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/charlotteville/theme-photo.jpg
new file mode 100755
index 0000000..253b804
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/charlotteville/theme-photo.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather-leaf.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather-leaf.png
new file mode 100644
index 0000000..f1208e0
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather-leaf.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather-open.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather-open.png
new file mode 100644
index 0000000..aa7b170
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather-open.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather.png
new file mode 100644
index 0000000..f9e3485
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/feather.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/richmond/theme-photo.jpg b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/richmond/theme-photo.jpg
new file mode 100755
index 0000000..8ff3ecb
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/richmond/theme-photo.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country.png
new file mode 100644
index 0000000..c2766a9
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_AT.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_AT.png
new file mode 100644
index 0000000..43f5d2a
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_AT.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_CH.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_CH.png
new file mode 100644
index 0000000..b244b58
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_CH.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_DE.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_DE.png
new file mode 100644
index 0000000..c5533c7
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_de_DE.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_en_GB.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_en_GB.png
new file mode 100644
index 0000000..67a72d1
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_en_GB.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_en_US.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_en_US.png
new file mode 100644
index 0000000..653a963
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_en_US.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_ja_JP.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_ja_JP.png
new file mode 100644
index 0000000..9335bae
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_ja_JP.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_ru_RU.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_ru_RU.png
new file mode 100644
index 0000000..7a9ad9b
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/country_ru_RU.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/theme-photo.jpg b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/theme-photo.jpg
new file mode 100755
index 0000000..bd51b72
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/scarborough/theme-photo.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/speyside/theme-photo.jpg b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/speyside/theme-photo.jpg
new file mode 100755
index 0000000..3254826
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/speyside/theme-photo.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/standard/theme-photo.jpg b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/standard/theme-photo.jpg
new file mode 100644
index 0000000..31f2523
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/standard/theme-photo.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/tobago_head.png b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/tobago_head.png
new file mode 100644
index 0000000..5eca56f
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/image/tobago_head.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/index.html b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/index.html
new file mode 100644
index 0000000..88f0d50
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html>
+<head>
+  <meta http-equiv="Cache-Control" content="no-cache">
+  <meta http-equiv="Refresh" content="0; URL=faces/init.xhtml">
+</head>
+<body>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/init.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/init.xhtml
new file mode 100644
index 0000000..6f2e308
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/init.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view locale="#{clientConfigController.locale}"
+        xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component">
+  <tc:page applicationIcon="#{request.contextPath}/icon/favicon.ico" label="#{demoBundle.pageTitle}" id="page">
+
+    <!-- this event will forward to the first node of the navitation menu after loading -->
+    <tc:event event="load" action="#{navigationState.gotoFirst}"/>
+
+    <!-- todo: justifyContent -->
+    <tc:flexLayout rows="auto;auto" alignItems="center" justifyContent="center">
+
+      <tc:image value="#{request.contextPath}/image/tobago_head.png">
+        <tc:style width="150px" height="83px"/>
+      </tc:image>
+
+      <tc:out value="Initializing ..."/>
+    </tc:flexLayout>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/logging-info.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/logging-info.xhtml
new file mode 100644
index 0000000..085cc63
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/logging-info.xhtml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:f="http://java.sun.com/jsf/core"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <ui:param name="title" value="Logging Info"/>
+
+  <tc:gridLayout rows="auto;auto;auto;*" rendered="#{info.enabled}">
+
+    <tc:in label="Test Category" value="#{universalLoggingInfo.testCategory}"/>
+    <tc:button label="Update" action="#{universalLoggingInfo.update}"/>
+
+    <tc:separator/>
+
+    <tc:gridLayout columns="auto;120px;auto;*">
+
+      <tc:label value="JUL" tip="Java Util Logging"/>
+      <tc:selectBooleanCheckbox value="#{universalLoggingInfo.jul.available}" readonly="true"
+                                label="available" labelLayout="skip"/>
+      <tc:button label="Log" tip="Log some stuff in every level" action="#{universalLoggingInfo.jul.logDemo}"
+                 disabled="#{not universalLoggingInfo.jul.available}"/>
+      <tc:out value="#{universalLoggingInfo.jul.activeLevels}"/>
+
+      <tc:label value="SLF4J" tip="Simple Logging Facade"/>
+      <tc:selectBooleanCheckbox value="#{universalLoggingInfo.slf4j.available}" readonly="true"
+                                label="available" labelLayout="skip"/>
+      <tc:button label="Log" tip="Log some stuff in every level" action="#{universalLoggingInfo.slf4j.logDemo}"
+                 disabled="#{not universalLoggingInfo.slf4j.available}"/>
+      <tc:out value="#{universalLoggingInfo.slf4j.activeLevels}"/>
+
+      <tc:label value="LOG4J"/>
+      <tc:selectBooleanCheckbox value="#{universalLoggingInfo.log4j.available}" readonly="true"
+                                label="available" labelLayout="skip"/>
+      <tc:button label="Log" tip="Log some stuff in every level" action="#{universalLoggingInfo.log4j.logDemo}"
+                 disabled="#{not universalLoggingInfo.log4j.available}"/>
+      <tc:out value="#{universalLoggingInfo.log4j.activeLevels}"/>
+
+      <tc:label value="LOG4J2"/>
+      <tc:selectBooleanCheckbox value="#{universalLoggingInfo.log4j2.available}" readonly="true"
+                                label="available" labelLayout="skip"/>
+      <tc:button label="Log" tip="Log some stuff in every level" action="#{universalLoggingInfo.log4j2.logDemo}"
+                 disabled="#{not universalLoggingInfo.log4j2.available}"/>
+      <tc:out value="#{universalLoggingInfo.log4j2.activeLevels}"/>
+
+      <tc:label value="JCL" tip="Commons Logging"/>
+      <tc:selectBooleanCheckbox value="#{universalLoggingInfo.commonsLogging.available}" readonly="true"
+                                label="available" labelLayout="skip"/>
+      <tc:button label="Log" tip="Log some stuff in every level" action="#{universalLoggingInfo.commonsLogging.logDemo}"
+                 disabled="#{not universalLoggingInfo.commonsLogging.available}"/>
+      <tc:out value="#{universalLoggingInfo.commonsLogging.activeLevels}"/>
+    </tc:gridLayout>
+
+    <tc:flowLayout>
+
+      <h3>This is a test page to check if all logging libraries are working well in the used container.</h3>
+
+      <ul>
+        <li>Change the category to check different categories and press "update" to see if the category is enabled.</li>
+        <li>Press "Log some stuff in every level" to log in that category.</li>
+        <li>Consult your log file (or anywhere you are logging) to check the result</li>
+      </ul>
+
+    </tc:flowLayout>
+  </tc:gridLayout>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/login.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/login.xhtml
new file mode 100644
index 0000000..b89c7ae
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/login.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns="http://www.w3.org/1999/xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+  <ui:param name="title" value="#{demoBundle.login}"/>
+  <p>This login site is only to demonstrate roles.
+    After login, you will be redirected to the roles page.</p>
+
+  <tc:section label="Login">
+    <p>Use one of the following users to login (Shortcuts:
+      <tc:link label="guest/guest" omit="true">
+        <tc:dataAttribute name="login" value='{"username": "guest", "password": "guest"}'/>
+      </tc:link>
+      or
+      <tc:link label="admin/admin" omit="true">
+        <tc:dataAttribute name="login" value='{"username": "admin", "password": "admin"}'/>
+      </tc:link>).</p>
+    <tc:in id="username" value="#{login.username}" label="User" focus="true"/>
+    <tc:in id="password" value="#{login.password}" password="true" label="Password"/>
+    <tc:button id="login" action="#{login.login}" label="Login" defaultCommand="true"/>
+  </tc:section>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/main.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/main.xhtml
new file mode 100644
index 0000000..300414a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/main.xhtml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- main template for this demo application, you may also use plain.xhtml for test purpose -->
+
+<ui:composition xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <f:view locale="#{clientConfigController.locale}">
+    <tc:page applicationIcon="#{request.contextPath}/icon/favicon.ico" label="#{demoBundle.pageTitle} - #{title}" id="page">
+
+      <!--
+            <tc:dataAttribute name="tobago-log-level" value="DEBUG"/>
+      -->
+
+      <tc:script file="#{request.contextPath}/script/demo.js"/>
+      <tc:script file="#{request.contextPath}/script/prism.js"/>
+      <tc:style file="#{request.contextPath}/style/demo.css"/>
+      <tc:style file="#{request.contextPath}/style/prism.css"/>
+
+      <ui:include src="/menu.xhtml"/>
+
+      <tc:segmentLayout large="#{tc:columnPartition(navigationState.viewSource ? '8;4' : '12')}">
+
+        <tc:flexLayout columns="*;4*">
+
+          <tc:panel>
+            <ui:include src="/navigation.xhtml"/>
+          </tc:panel>
+
+          <tc:flexLayout rows="auto;*">
+
+            <tc:panel id="messages">
+              <tc:messages orderBy="severity" rendered="#{!navigationTree.outputPage and !navigationTree.messagesPage}"/>
+            </tc:panel>
+
+            <tc:box label="#{title}" id="content">
+              <tc:form id="mainForm">
+                <ui:insert/>
+              </tc:form>
+            </tc:box>
+
+          </tc:flexLayout>
+
+        </tc:flexLayout>
+
+        <tc:panel rendered="#{navigationState.viewSource}">
+          <pre><code class="language-markup" id="demo-view-source">
+            <tc:out value="#{navigationTree.source}"/>
+          </code></pre>
+        </tc:panel>
+
+      </tc:segmentLayout>
+
+      <tc:footer fixed="true">
+        © 2017 Apache Software Foundation, Licensed under the <a
+          href="http://www.apache.org/licenses/LICENSE-2.0">Apache License, Version 2.0</a>.
+      </tc:footer>
+
+    </tc:page>
+  </f:view>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/menu.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/menu.xhtml
new file mode 100644
index 0000000..2688735
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/menu.xhtml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tc:header fixed="true"
+           xmlns:tc="http://myfaces.apache.org/tobago/component"
+           xmlns:f="http://java.sun.com/jsf/core">
+
+  <!-- tbd: how to solve this? -->
+  <tc:style customClass="bg-inverse"/>
+
+<!--
+  <tc:flexLayout columns="auto;*" alignItems="center">
+
+    <tc:image value="image/feather-leaf.png"/>
+-->
+
+    <tc:bar id="bar">
+      <f:facet name="brand">
+        <tc:link image="#{request.contextPath}/image/feather-leaf.png" label="Tobago Demo" id="brand" link="/"/>
+      </f:facet>
+
+      <tc:form id="header" inline="true">
+
+        <tc:links id="commands">
+
+          <tc:link id="config" label="#{demoBundle.menu_config}" omit="true">
+            <tc:link label="#{demoBundle.menu_themes}" omit="true">
+              <tc:selectOneRadio value="#{clientConfigController.theme}">
+                <tc:event action="#{clientConfigController.submit}"/>
+                <tc:selectItems value="#{clientConfigController.themeItems}"/>
+              </tc:selectOneRadio>
+            </tc:link>
+            <!--<tc:link action="#{clientConfigController.resetTheme}" label="Reset Theme"/>-->
+            <tc:link label="#{demoBundle.menu_locale}">
+              <tc:selectOneRadio value="#{clientConfigController.locale}">
+                <tc:event action="#{clientConfigController.submit}"/>
+                <tc:selectItems value="#{clientConfigController.localeItems}"/>
+              </tc:selectOneRadio>
+            </tc:link>
+            <tc:link action="#{login.resetSession}" label="Reset Session"/>
+          </tc:link>
+
+          <tc:link label="#{demoBundle.menu_help}" omit="true">
+            <tc:link label="#{demoBundle.menu_about}" omit="true">
+              <tc:dataAttribute name="alert-text"
+                                value="#{demoBundle.pageTitle} - #{info.version} - #{demoBundle.tobago_url}"/>
+            </tc:link>
+            <tc:link link="http://myfaces.apache.org/tobago" label="Tobago in the Web"/>
+            <tc:link action="/server-info.xhtml" immediate="true" label="Server Info" disabled="#{! info.enabled}"/>
+            <tc:link action="/logging-info.xhtml" immediate="true" label="Logging Info"
+                        disabled="#{! info.enabled}"/>
+            <tc:separator/>
+            <tc:link label="Sub-Menu" omit="true">
+              <tc:link label="Sub 1" omit="true"/>
+              <tc:link label="Sub 2" omit="true"/>
+              <tc:link label="Sub 3" omit="true"/>
+              <tc:link action="doit" label="Sub 4 ich kann auch selber was" omit="true">
+                <tc:link label="Sub 4 1" omit="true"/>
+                <tc:link label="Sub 4 2" omit="true"/>
+              </tc:link>
+              <tc:link label="Sub 5" omit="true">
+                <tc:link label="Sub 5 1" omit="true"/>
+                <tc:link label="Sub 5 2" omit="true"/>
+              </tc:link>
+            </tc:link>
+          </tc:link>
+
+          <!-- TBD: this is not nice: can we put tc:out or tc:label into the menu?
+          or we do that with a popup, oder a lighter variant of a popup -->
+          <tc:link omit="true" label="Info" id="headerInfo">
+            <tc:link omit="true" label="Theme: #{clientConfigController.localizedTheme}" disabled="true"/>
+            <tc:link omit="true" label="Locale: #{clientConfigController.localizedLocale}"/>
+            <tc:link omit="true" label="Project Stage: #{tobagoContext.tobagoConfig.projectStage}"/>
+            <tc:link omit="true" label="CSP mode: #{tobagoContext.tobagoConfig.contentSecurityPolicy.mode}"/>
+            <tc:link omit="true"
+                        label="Requests: #{activityList.values[0].jsfRequest} / AJAX: #{activityList.values[0].ajaxRequest}"/>
+          </tc:link>
+
+        </tc:links>
+      </tc:form>
+
+      <tc:flowLayout textAlign="right">
+        <tc:form inline="true">
+          <tc:in placeholder="Search"/>
+          <tc:button defaultCommand="true" omit="true" label="go">
+            <tc:dataAttribute name="alert-text"
+                              value="Sorry: Search not implemented"/>
+
+          </tc:button>
+        </tc:form>
+        <tc:form id="navbtns" inline="true">
+          <tc:button immediate="true" id="previous"
+                     image="fa-angle-left"
+                     action="#{navigationState.gotoPrevious}"
+                     disabled="#{navigationState.first}"
+                     tip="#{demoBundle.footer_previous}"/>
+          <tc:button immediate="true" id="next"
+                     image="fa-angle-right"
+                     action="#{navigationState.gotoNext}"
+                     disabled="#{navigationState.last}"
+                     tip="#{demoBundle.footer_next}"/>
+          <tc:button action="#{navigationState.toggleViewSource}"
+                     image="fa-code"
+                     immediate="true" tip="#{demoBundle.footer_viewSource}"/>
+          <tc:button id="runtest"
+                     link="/faces/test.xhtml"
+                     label="Run Test"
+                     immediate="true" tip="Run Test"
+                     rendered="#{testController.testBase != null}">
+            <f:param name="page" value="#{request.contextPath}/faces#{testController.testBase}.xhtml"/>
+            <f:param name="testjs" value="#{request.contextPath}#{testController.testBase}.test.js"/>
+          </tc:button>
+          <tc:button id="closetest" label="Close Test"
+                     immediate="true" tip="Close test window"/>
+        </tc:form>
+      </tc:flowLayout>
+
+    </tc:bar>
+
+<!--
+  </tc:flexLayout>
+-->
+
+</tc:header>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/navigation.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/navigation.xhtml
new file mode 100644
index 0000000..bbec6e4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/navigation.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:subview id="navigator"
+           xmlns:f="http://java.sun.com/jsf/core"
+           xmlns:tc="http://myfaces.apache.org/tobago/component">
+  <tc:treeMenu id="nav" value="#{navigationTree.tree}" var="node" state="#{navigationState.state}">
+    <tc:treeNode id="node">
+      <tc:treeCommand
+          id="cmd"
+          label="#{node.title}"
+          link="/faces#{node.outcome}"
+          omit="true"/>
+    </tc:treeNode>
+  </tc:treeMenu>
+</f:subview>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/plain.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/plain.xhtml
new file mode 100644
index 0000000..2180222
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/plain.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:f="http://java.sun.com/jsf/core"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <f:view locale="#{clientConfigController.locale}">
+    <tc:page label="Test" id="page">
+
+      <ui:insert/>
+
+    </tc:page>
+  </f:view>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/demo.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/demo.js
new file mode 100644
index 0000000..8f4f251
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/demo.js
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function ($) {
+  $.widget("demo.alert", {
+    _create: function () {
+      this._on({
+        click: function (event) {
+          var text = this.element.data("alert-text");
+          alert(text);
+        }
+      });
+    }
+  });
+}(jQuery));
+
+var initAlert = function () {
+  jQuery("[data-alert-text]").alert();
+};
+
+Tobago.registerListener(initAlert, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(initAlert, Tobago.Phase.AFTER_UPDATE);
+
+var initInspect = function (elements) {
+
+  jQuery("code").find("br").replaceWith("\n");
+
+  // var tobagoElements = Tobago.Utils.selectWithJQuery(elements, ".tobago-in,.tobago-out,.tobago-date");
+  var tobagoElements = Tobago.Utils.selectWithJQuery(elements, ".tobago-flexLayout");
+
+  tobagoElements = tobagoElements.filter(function () {
+    return jQuery(this).parents("#page\\:content").length == 1;
+  });
+
+  tobagoElements.hover(function () {
+
+    // clear old selections:
+    jQuery(".demo-selected").removeClass("demo-selected");
+
+    var element = jQuery(this);
+    element.addClass("demo-selected");
+
+    var clientId = element.closest("[id]").attr("id");
+    var id = clientId.substr(clientId.lastIndexOf(":") + 1);
+
+    var source = jQuery("#demo-view-source");
+
+    var span = source.find("span.token.attr-value").filter(function () {
+      return jQuery(this).prev().text() + jQuery(this).text() == 'id=' + '"' + id + '"';
+    });
+    var tag = span.parent();
+    tag.addClass("demo-selected");
+  });
+};
+
+Tobago.registerListener(initInspect, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(initInspect, Tobago.Phase.AFTER_UPDATE);
+
+var initTestButtons = function () {
+  var $runButton = jQuery("#page\\:navbtns\\:runtest");
+  var $closeButton = jQuery("#page\\:navbtns\\:closetest");
+
+  if (jQuery(parent.document.getElementById("qunit")).length) {
+    $runButton.hide();
+    $closeButton.attr("onclick", "window.top.location.href = location.href");
+  } else {
+    $closeButton.hide();
+  }
+};
+
+Tobago.registerListener(initTestButtons, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(initTestButtons, Tobago.Phase.AFTER_UPDATE);
+
+var initTestframe = function () {
+  jQuery("#page\\:testframe").attr("onload", "this.height = this.contentWindow.jQuery('body').prop('scrollHeight');");
+};
+
+Tobago.registerListener(initTestframe, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(initTestframe, Tobago.Phase.AFTER_UPDATE);
+
+Demo = {};
+
+/**
+ * Copies the values from the data-login attribute to the username/password fields.
+ */
+Demo.prepareQuickLinks = function() {
+  jQuery("button[data-login]").click(function() {
+    var link = jQuery(this);
+    var login = link.data("login");
+    jQuery(Tobago.Utils.escapeClientId("page:mainForm:username::field")).val(login.username);
+    jQuery(Tobago.Utils.escapeClientId("page:mainForm:password::field")).val(login.password);
+    return false;
+  });
+};
+
+Tobago.registerListener(Demo.prepareQuickLinks, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/prism.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/prism.js
new file mode 100644
index 0000000..105ef92
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/prism.js
@@ -0,0 +1,682 @@
+/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+java+less */
+var _self = (typeof window !== 'undefined')
+	? window   // if in browser
+	: (
+		(typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope)
+		? self // if in worker
+		: {}   // if in node js
+	);
+
+/**
+ * Prism: Lightweight, robust, elegant syntax highlighting
+ * MIT license http://www.opensource.org/licenses/mit-license.php/
+ * @author Lea Verou
+ */
+
+var Prism = (function(){
+
+// Private helper vars
+var lang = /\blang(?:uage)?-(?!\*)(\w+)\b/i;
+
+var _ = _self.Prism = {
+	util: {
+		encode: function (tokens) {
+			if (tokens instanceof Token) {
+				return new Token(tokens.type, _.util.encode(tokens.content), tokens.alias);
+			} else if (_.util.type(tokens) === 'Array') {
+				return tokens.map(_.util.encode);
+			} else {
+				return tokens.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/\u00a0/g, ' ');
+			}
+		},
+
+		type: function (o) {
+			return Object.prototype.toString.call(o).match(/\[object (\w+)\]/)[1];
+		},
+
+		// Deep clone a language definition (e.g. to extend it)
+		clone: function (o) {
+			var type = _.util.type(o);
+
+			switch (type) {
+				case 'Object':
+					var clone = {};
+
+					for (var key in o) {
+						if (o.hasOwnProperty(key)) {
+							clone[key] = _.util.clone(o[key]);
+						}
+					}
+
+					return clone;
+
+				case 'Array':
+					// Check for existence for IE8
+					return o.map && o.map(function(v) { return _.util.clone(v); });
+			}
+
+			return o;
+		}
+	},
+
+	languages: {
+		extend: function (id, redef) {
+			var lang = _.util.clone(_.languages[id]);
+
+			for (var key in redef) {
+				lang[key] = redef[key];
+			}
+
+			return lang;
+		},
+
+		/**
+		 * Insert a token before another token in a language literal
+		 * As this needs to recreate the object (we cannot actually insert before keys in object literals),
+		 * we cannot just provide an object, we need anobject and a key.
+		 * @param inside The key (or language id) of the parent
+		 * @param before The key to insert before. If not provided, the function appends instead.
+		 * @param insert Object with the key/value pairs to insert
+		 * @param root The object that contains `inside`. If equal to Prism.languages, it can be omitted.
+		 */
+		insertBefore: function (inside, before, insert, root) {
+			root = root || _.languages;
+			var grammar = root[inside];
+			
+			if (arguments.length == 2) {
+				insert = arguments[1];
+				
+				for (var newToken in insert) {
+					if (insert.hasOwnProperty(newToken)) {
+						grammar[newToken] = insert[newToken];
+					}
+				}
+				
+				return grammar;
+			}
+			
+			var ret = {};
+
+			for (var token in grammar) {
+
+				if (grammar.hasOwnProperty(token)) {
+
+					if (token == before) {
+
+						for (var newToken in insert) {
+
+							if (insert.hasOwnProperty(newToken)) {
+								ret[newToken] = insert[newToken];
+							}
+						}
+					}
+
+					ret[token] = grammar[token];
+				}
+			}
+			
+			// Update references in other language definitions
+			_.languages.DFS(_.languages, function(key, value) {
+				if (value === root[inside] && key != inside) {
+					this[key] = ret;
+				}
+			});
+
+			return root[inside] = ret;
+		},
+
+		// Traverse a language definition with Depth First Search
+		DFS: function(o, callback, type) {
+			for (var i in o) {
+				if (o.hasOwnProperty(i)) {
+					callback.call(o, i, o[i], type || i);
+
+					if (_.util.type(o[i]) === 'Object') {
+						_.languages.DFS(o[i], callback);
+					}
+					else if (_.util.type(o[i]) === 'Array') {
+						_.languages.DFS(o[i], callback, i);
+					}
+				}
+			}
+		}
+	},
+	plugins: {},
+	
+	highlightAll: function(async, callback) {
+		var elements = document.querySelectorAll('code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code');
+
+		for (var i=0, element; element = elements[i++];) {
+			_.highlightElement(element, async === true, callback);
+		}
+	},
+
+	highlightElement: function(element, async, callback) {
+		// Find language
+		var language, grammar, parent = element;
+
+		while (parent && !lang.test(parent.className)) {
+			parent = parent.parentNode;
+		}
+
+		if (parent) {
+			language = (parent.className.match(lang) || [,''])[1];
+			grammar = _.languages[language];
+		}
+
+		// Set language on the element, if not present
+		element.className = element.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+
+		// Set language on the parent, for styling
+		parent = element.parentNode;
+
+		if (/pre/i.test(parent.nodeName)) {
+			parent.className = parent.className.replace(lang, '').replace(/\s+/g, ' ') + ' language-' + language;
+		}
+
+		var code = element.textContent;
+
+		var env = {
+			element: element,
+			language: language,
+			grammar: grammar,
+			code: code
+		};
+
+		if (!code || !grammar) {
+			_.hooks.run('complete', env);
+			return;
+		}
+
+		_.hooks.run('before-highlight', env);
+
+		if (async && _self.Worker) {
+			var worker = new Worker(_.filename);
+
+			worker.onmessage = function(evt) {
+				env.highlightedCode = evt.data;
+
+				_.hooks.run('before-insert', env);
+
+				env.element.innerHTML = env.highlightedCode;
+
+				callback && callback.call(env.element);
+				_.hooks.run('after-highlight', env);
+				_.hooks.run('complete', env);
+			};
+
+			worker.postMessage(JSON.stringify({
+				language: env.language,
+				code: env.code,
+				immediateClose: true
+			}));
+		}
+		else {
+			env.highlightedCode = _.highlight(env.code, env.grammar, env.language);
+
+			_.hooks.run('before-insert', env);
+
+			env.element.innerHTML = env.highlightedCode;
+
+			callback && callback.call(element);
+
+			_.hooks.run('after-highlight', env);
+			_.hooks.run('complete', env);
+		}
+	},
+
+	highlight: function (text, grammar, language) {
+		var tokens = _.tokenize(text, grammar);
+		return Token.stringify(_.util.encode(tokens), language);
+	},
+
+	tokenize: function(text, grammar, language) {
+		var Token = _.Token;
+
+		var strarr = [text];
+
+		var rest = grammar.rest;
+
+		if (rest) {
+			for (var token in rest) {
+				grammar[token] = rest[token];
+			}
+
+			delete grammar.rest;
+		}
+
+		tokenloop: for (var token in grammar) {
+			if(!grammar.hasOwnProperty(token) || !grammar[token]) {
+				continue;
+			}
+
+			var patterns = grammar[token];
+			patterns = (_.util.type(patterns) === "Array") ? patterns : [patterns];
+
+			for (var j = 0; j < patterns.length; ++j) {
+				var pattern = patterns[j],
+					inside = pattern.inside,
+					lookbehind = !!pattern.lookbehind,
+					lookbehindLength = 0,
+					alias = pattern.alias;
+
+				pattern = pattern.pattern || pattern;
+
+				for (var i=0; i<strarr.length; i++) { // Don’t cache length as it changes during the loop
+
+					var str = strarr[i];
+
+					if (strarr.length > text.length) {
+						// Something went terribly wrong, ABORT, ABORT!
+						break tokenloop;
+					}
+
+					if (str instanceof Token) {
+						continue;
+					}
+
+					pattern.lastIndex = 0;
+
+					var match = pattern.exec(str);
+
+					if (match) {
+						if(lookbehind) {
+							lookbehindLength = match[1].length;
+						}
+
+						var from = match.index - 1 + lookbehindLength,
+							match = match[0].slice(lookbehindLength),
+							len = match.length,
+							to = from + len,
+							before = str.slice(0, from + 1),
+							after = str.slice(to + 1);
+
+						var args = [i, 1];
+
+						if (before) {
+							args.push(before);
+						}
+
+						var wrapped = new Token(token, inside? _.tokenize(match, inside) : match, alias);
+
+						args.push(wrapped);
+
+						if (after) {
+							args.push(after);
+						}
+
+						Array.prototype.splice.apply(strarr, args);
+					}
+				}
+			}
+		}
+
+		return strarr;
+	},
+
+	hooks: {
+		all: {},
+
+		add: function (name, callback) {
+			var hooks = _.hooks.all;
+
+			hooks[name] = hooks[name] || [];
+
+			hooks[name].push(callback);
+		},
+
+		run: function (name, env) {
+			var callbacks = _.hooks.all[name];
+
+			if (!callbacks || !callbacks.length) {
+				return;
+			}
+
+			for (var i=0, callback; callback = callbacks[i++];) {
+				callback(env);
+			}
+		}
+	}
+};
+
+var Token = _.Token = function(type, content, alias) {
+	this.type = type;
+	this.content = content;
+	this.alias = alias;
+};
+
+Token.stringify = function(o, language, parent) {
+	if (typeof o == 'string') {
+		return o;
+	}
+
+	if (_.util.type(o) === 'Array') {
+		return o.map(function(element) {
+			return Token.stringify(element, language, o);
+		}).join('');
+	}
+
+	var env = {
+		type: o.type,
+		content: Token.stringify(o.content, language, parent),
+		tag: 'span',
+		classes: ['token', o.type],
+		attributes: {},
+		language: language,
+		parent: parent
+	};
+
+	if (env.type == 'comment') {
+		env.attributes['spellcheck'] = 'true';
+	}
+
+	if (o.alias) {
+		var aliases = _.util.type(o.alias) === 'Array' ? o.alias : [o.alias];
+		Array.prototype.push.apply(env.classes, aliases);
+	}
+
+	_.hooks.run('wrap', env);
+
+	var attributes = '';
+
+	for (var name in env.attributes) {
+		attributes += (attributes ? ' ' : '') + name + '="' + (env.attributes[name] || '') + '"';
+	}
+
+	return '<' + env.tag + ' class="' + env.classes.join(' ') + '" ' + attributes + '>' + env.content + '</' + env.tag + '>';
+
+};
+
+if (!_self.document) {
+	if (!_self.addEventListener) {
+		// in Node.js
+		return _self.Prism;
+	}
+ 	// In worker
+	_self.addEventListener('message', function(evt) {
+		var message = JSON.parse(evt.data),
+		    lang = message.language,
+		    code = message.code,
+		    immediateClose = message.immediateClose;
+
+		_self.postMessage(_.highlight(code, _.languages[lang], lang));
+		if (immediateClose) {
+			_self.close();
+		}
+	}, false);
+
+	return _self.Prism;
+}
+
+// Get current script and highlight
+var script = document.getElementsByTagName('script');
+
+script = script[script.length - 1];
+
+if (script) {
+	_.filename = script.src;
+
+	if (document.addEventListener && !script.hasAttribute('data-manual')) {
+		document.addEventListener('DOMContentLoaded', _.highlightAll);
+	}
+}
+
+return _self.Prism;
+
+})();
+
+if (typeof module !== 'undefined' && module.exports) {
+	module.exports = Prism;
+}
+
+// hack for components to work correctly in node.js
+if (typeof global !== 'undefined') {
+	global.Prism = Prism;
+}
+;
+Prism.languages.markup = {
+	'comment': /<!--[\w\W]*?-->/,
+	'prolog': /<\?[\w\W]+?\?>/,
+	'doctype': /<!DOCTYPE[\w\W]+?>/,
+	'cdata': /<!\[CDATA\[[\w\W]*?]]>/i,
+	'tag': {
+		pattern: /<\/?[^\s>\/=.]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\\1|\\?(?!\1)[\w\W])*\1|[^\s'">=]+))?)*\s*\/?>/i,
+		inside: {
+			'tag': {
+				pattern: /^<\/?[^\s>\/]+/i,
+				inside: {
+					'punctuation': /^<\/?/,
+					'namespace': /^[^\s>\/:]+:/
+				}
+			},
+			'attr-value': {
+				pattern: /=(?:('|")[\w\W]*?(\1)|[^\s>]+)/i,
+				inside: {
+					'punctuation': /[=>"']/
+				}
+			},
+			'punctuation': /\/?>/,
+			'attr-name': {
+				pattern: /[^\s>\/]+/,
+				inside: {
+					'namespace': /^[^\s>\/:]+:/
+				}
+			}
+
+		}
+	},
+	'entity': /&#?[\da-z]{1,8};/i
+};
+
+// Plugin to make entity title show the real entity, idea by Roman Komarov
+Prism.hooks.add('wrap', function(env) {
+
+	if (env.type === 'entity') {
+		env.attributes['title'] = env.content.replace(/&amp;/, '&');
+	}
+});
+
+Prism.languages.xml = Prism.languages.markup;
+Prism.languages.html = Prism.languages.markup;
+Prism.languages.mathml = Prism.languages.markup;
+Prism.languages.svg = Prism.languages.markup;
+
+Prism.languages.css = {
+	'comment': /\/\*[\w\W]*?\*\//,
+	'atrule': {
+		pattern: /@[\w-]+?.*?(;|(?=\s*\{))/i,
+		inside: {
+			'rule': /@[\w-]+/
+			// See rest below
+		}
+	},
+	'url': /url\((?:(["'])(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,
+	'selector': /[^\{\}\s][^\{\};]*?(?=\s*\{)/,
+	'string': /("|')(\\(?:\r\n|[\w\W])|(?!\1)[^\\\r\n])*\1/,
+	'property': /(\b|\B)[\w-]+(?=\s*:)/i,
+	'important': /\B!important\b/i,
+	'function': /[-a-z0-9]+(?=\()/i,
+	'punctuation': /[(){};:]/
+};
+
+Prism.languages.css['atrule'].inside.rest = Prism.util.clone(Prism.languages.css);
+
+if (Prism.languages.markup) {
+	Prism.languages.insertBefore('markup', 'tag', {
+		'style': {
+			pattern: /<style[\w\W]*?>[\w\W]*?<\/style>/i,
+			inside: {
+				'tag': {
+					pattern: /<style[\w\W]*?>|<\/style>/i,
+					inside: Prism.languages.markup.tag.inside
+				},
+				rest: Prism.languages.css
+			},
+			alias: 'language-css'
+		}
+	});
+	
+	Prism.languages.insertBefore('inside', 'attr-value', {
+		'style-attr': {
+			pattern: /\s*style=("|').*?\1/i,
+			inside: {
+				'attr-name': {
+					pattern: /^\s*style/i,
+					inside: Prism.languages.markup.tag.inside
+				},
+				'punctuation': /^\s*=\s*['"]|['"]\s*$/,
+				'attr-value': {
+					pattern: /.+/i,
+					inside: Prism.languages.css
+				}
+			},
+			alias: 'language-css'
+		}
+	}, Prism.languages.markup.tag);
+};
+Prism.languages.clike = {
+	'comment': [
+		{
+			pattern: /(^|[^\\])\/\*[\w\W]*?\*\//,
+			lookbehind: true
+		},
+		{
+			pattern: /(^|[^\\:])\/\/.*/,
+			lookbehind: true
+		}
+	],
+	'string': /(["'])(\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,
+	'class-name': {
+		pattern: /((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[a-z0-9_\.\\]+/i,
+		lookbehind: true,
+		inside: {
+			punctuation: /(\.|\\)/
+		}
+	},
+	'keyword': /\b(if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,
+	'boolean': /\b(true|false)\b/,
+	'function': /[a-z0-9_]+(?=\()/i,
+	'number': /\b-?(?:0x[\da-f]+|\d*\.?\d+(?:e[+-]?\d+)?)\b/i,
+	'operator': /--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,
+	'punctuation': /[{}[\];(),.:]/
+};
+
+Prism.languages.javascript = Prism.languages.extend('clike', {
+	'keyword': /\b(as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|false|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|true|try|typeof|var|void|while|with|yield)\b/,
+	'number': /\b-?(0x[\dA-Fa-f]+|0b[01]+|0o[0-7]+|\d*\.?\d+([Ee][+-]?\d+)?|NaN|Infinity)\b/,
+	// Allow for all non-ASCII characters (See http://stackoverflow.com/a/2008444)
+	'function': /[_$a-zA-Z\xA0-\uFFFF][_$a-zA-Z0-9\xA0-\uFFFF]*(?=\()/i
+});
+
+Prism.languages.insertBefore('javascript', 'keyword', {
+	'regex': {
+		pattern: /(^|[^/])\/(?!\/)(\[.+?]|\\.|[^/\\\r\n])+\/[gimyu]{0,5}(?=\s*($|[\r\n,.;})]))/,
+		lookbehind: true
+	}
+});
+
+Prism.languages.insertBefore('javascript', 'class-name', {
+	'template-string': {
+		pattern: /`(?:\\`|\\?[^`])*`/,
+		inside: {
+			'interpolation': {
+				pattern: /\$\{[^}]+\}/,
+				inside: {
+					'interpolation-punctuation': {
+						pattern: /^\$\{|\}$/,
+						alias: 'punctuation'
+					},
+					rest: Prism.languages.javascript
+				}
+			},
+			'string': /[\s\S]+/
+		}
+	}
+});
+
+if (Prism.languages.markup) {
+	Prism.languages.insertBefore('markup', 'tag', {
+		'script': {
+			pattern: /<script[\w\W]*?>[\w\W]*?<\/script>/i,
+			inside: {
+				'tag': {
+					pattern: /<script[\w\W]*?>|<\/script>/i,
+					inside: Prism.languages.markup.tag.inside
+				},
+				rest: Prism.languages.javascript
+			},
+			alias: 'language-javascript'
+		}
+	});
+}
+
+Prism.languages.js = Prism.languages.javascript;
+Prism.languages.java = Prism.languages.extend('clike', {
+	'keyword': /\b(abstract|continue|for|new|switch|assert|default|goto|package|synchronized|boolean|do|if|private|this|break|double|implements|protected|throw|byte|else|import|public|throws|case|enum|instanceof|return|transient|catch|extends|int|short|try|char|final|interface|static|void|class|finally|long|strictfp|volatile|const|float|native|super|while)\b/,
+	'number': /\b0b[01]+\b|\b0x[\da-f]*\.?[\da-fp\-]+\b|\b\d*\.?\d+(?:e[+-]?\d+)?[df]?\b/i,
+	'operator': {
+		pattern: /(^|[^.])(?:\+[+=]?|-[-=]?|!=?|<<?=?|>>?>?=?|==?|&[&=]?|\|[|=]?|\*=?|\/=?|%=?|\^=?|[?:~])/m,
+		lookbehind: true
+	}
+});
+/* FIXME :
+ :extend() is not handled specifically : its highlighting is buggy.
+ Mixin usage must be inside a ruleset to be highlighted.
+ At-rules (e.g. import) containing interpolations are buggy.
+ Detached rulesets are highlighted as at-rules.
+ A comment before a mixin usage prevents the latter to be properly highlighted.
+ */
+
+Prism.languages.less = Prism.languages.extend('css', {
+	'comment': [
+		/\/\*[\w\W]*?\*\//,
+		{
+			pattern: /(^|[^\\])\/\/.*/,
+			lookbehind: true
+		}
+	],
+	'atrule': {
+		pattern: /@[\w-]+?(?:\([^{}]+\)|[^(){};])*?(?=\s*\{)/i,
+		inside: {
+			'punctuation': /[:()]/
+		}
+	},
+	// selectors and mixins are considered the same
+	'selector': {
+		pattern: /(?:@\{[\w-]+\}|[^{};\s@])(?:@\{[\w-]+\}|\([^{}]*\)|[^{};@])*?(?=\s*\{)/,
+		inside: {
+			// mixin parameters
+			'variable': /@+[\w-]+/
+		}
+	},
+
+	'property': /(?:@\{[\w-]+\}|[\w-])+(?:\+_?)?(?=\s*:)/i,
+	'punctuation': /[{}();:,]/,
+	'operator': /[+\-*\/]/
+});
+
+// Invert function and punctuation positions
+Prism.languages.insertBefore('less', 'punctuation', {
+	'function': Prism.languages.less.function
+});
+
+Prism.languages.insertBefore('less', 'property', {
+	'variable': [
+		// Variable declaration (the colon must be consumed!)
+		{
+			pattern: /@[\w-]+\s*:/,
+			inside: {
+				"punctuation": /:/
+			}
+		},
+
+		// Variable usage
+		/@@?[\w-]+/
+	],
+	'mixin-usage': {
+		pattern: /([{;]\s*)[.#](?!\d)[\w-]+.*?(?=[(;])/,
+		lookbehind: true,
+		alias: 'function'
+	}
+});
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/qunit-1.23.1.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/qunit-1.23.1.js
new file mode 100644
index 0000000..5df0822
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/qunit-1.23.1.js
@@ -0,0 +1,4334 @@
+/*!
+ * QUnit 1.23.1
+ * https://qunitjs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2016-04-12T17:29Z
+ */
+
+( function( global ) {
+
+var QUnit = {};
+
+var Date = global.Date;
+var now = Date.now || function() {
+	return new Date().getTime();
+};
+
+var setTimeout = global.setTimeout;
+var clearTimeout = global.clearTimeout;
+
+// Store a local window from the global to allow direct references.
+var window = global.window;
+
+var defined = {
+	document: window && window.document !== undefined,
+	setTimeout: setTimeout !== undefined,
+	sessionStorage: ( function() {
+		var x = "qunit-test-string";
+		try {
+			sessionStorage.setItem( x, x );
+			sessionStorage.removeItem( x );
+			return true;
+		} catch ( e ) {
+			return false;
+		}
+	}() )
+};
+
+var fileName = ( sourceFromStacktrace( 0 ) || "" ).replace( /(:\d+)+\)?/, "" ).replace( /.+\//, "" );
+var globalStartCalled = false;
+var runStarted = false;
+
+var toString = Object.prototype.toString,
+	hasOwn = Object.prototype.hasOwnProperty;
+
+// Returns a new Array with the elements that are in a but not in b
+function diff( a, b ) {
+	var i, j,
+		result = a.slice();
+
+	for ( i = 0; i < result.length; i++ ) {
+		for ( j = 0; j < b.length; j++ ) {
+			if ( result[ i ] === b[ j ] ) {
+				result.splice( i, 1 );
+				i--;
+				break;
+			}
+		}
+	}
+	return result;
+}
+
+// From jquery.js
+function inArray( elem, array ) {
+	if ( array.indexOf ) {
+		return array.indexOf( elem );
+	}
+
+	for ( var i = 0, length = array.length; i < length; i++ ) {
+		if ( array[ i ] === elem ) {
+			return i;
+		}
+	}
+
+	return -1;
+}
+
+/**
+ * Makes a clone of an object using only Array or Object as base,
+ * and copies over the own enumerable properties.
+ *
+ * @param {Object} obj
+ * @return {Object} New object with only the own properties (recursively).
+ */
+function objectValues ( obj ) {
+	var key, val,
+		vals = QUnit.is( "array", obj ) ? [] : {};
+	for ( key in obj ) {
+		if ( hasOwn.call( obj, key ) ) {
+			val = obj[ key ];
+			vals[ key ] = val === Object( val ) ? objectValues( val ) : val;
+		}
+	}
+	return vals;
+}
+
+function extend( a, b, undefOnly ) {
+	for ( var prop in b ) {
+		if ( hasOwn.call( b, prop ) ) {
+
+			// Avoid "Member not found" error in IE8 caused by messing with window.constructor
+			// This block runs on every environment, so `global` is being used instead of `window`
+			// to avoid errors on node.
+			if ( prop !== "constructor" || a !== global ) {
+				if ( b[ prop ] === undefined ) {
+					delete a[ prop ];
+				} else if ( !( undefOnly && typeof a[ prop ] !== "undefined" ) ) {
+					a[ prop ] = b[ prop ];
+				}
+			}
+		}
+	}
+
+	return a;
+}
+
+function objectType( obj ) {
+	if ( typeof obj === "undefined" ) {
+		return "undefined";
+	}
+
+	// Consider: typeof null === object
+	if ( obj === null ) {
+		return "null";
+	}
+
+	var match = toString.call( obj ).match( /^\[object\s(.*)\]$/ ),
+		type = match && match[ 1 ];
+
+	switch ( type ) {
+		case "Number":
+			if ( isNaN( obj ) ) {
+				return "nan";
+			}
+			return "number";
+		case "String":
+		case "Boolean":
+		case "Array":
+		case "Set":
+		case "Map":
+		case "Date":
+		case "RegExp":
+		case "Function":
+		case "Symbol":
+			return type.toLowerCase();
+	}
+	if ( typeof obj === "object" ) {
+		return "object";
+	}
+}
+
+// Safe object type checking
+function is( type, obj ) {
+	return QUnit.objectType( obj ) === type;
+}
+
+// Doesn't support IE6 to IE9, it will return undefined on these browsers
+// See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
+function extractStacktrace( e, offset ) {
+	offset = offset === undefined ? 4 : offset;
+
+	var stack, include, i;
+
+	if ( e.stack ) {
+		stack = e.stack.split( "\n" );
+		if ( /^error$/i.test( stack[ 0 ] ) ) {
+			stack.shift();
+		}
+		if ( fileName ) {
+			include = [];
+			for ( i = offset; i < stack.length; i++ ) {
+				if ( stack[ i ].indexOf( fileName ) !== -1 ) {
+					break;
+				}
+				include.push( stack[ i ] );
+			}
+			if ( include.length ) {
+				return include.join( "\n" );
+			}
+		}
+		return stack[ offset ];
+
+	// Support: Safari <=6 only
+	} else if ( e.sourceURL ) {
+
+		// Exclude useless self-reference for generated Error objects
+		if ( /qunit.js$/.test( e.sourceURL ) ) {
+			return;
+		}
+
+		// For actual exceptions, this is useful
+		return e.sourceURL + ":" + e.line;
+	}
+}
+
+function sourceFromStacktrace( offset ) {
+	var error = new Error();
+
+	// Support: Safari <=7 only, IE <=10 - 11 only
+	// Not all browsers generate the `stack` property for `new Error()`, see also #636
+	if ( !error.stack ) {
+		try {
+			throw error;
+		} catch ( err ) {
+			error = err;
+		}
+	}
+
+	return extractStacktrace( error, offset );
+}
+
+/**
+ * Config object: Maintain internal state
+ * Later exposed as QUnit.config
+ * `config` initialized at top of scope
+ */
+var config = {
+
+	// The queue of tests to run
+	queue: [],
+
+	// Block until document ready
+	blocking: true,
+
+	// By default, run previously failed tests first
+	// very useful in combination with "Hide passed tests" checked
+	reorder: true,
+
+	// By default, modify document.title when suite is done
+	altertitle: true,
+
+	// HTML Reporter: collapse every test except the first failing test
+	// If false, all failing tests will be expanded
+	collapse: true,
+
+	// By default, scroll to top of the page when suite is done
+	scrolltop: true,
+
+	// Depth up-to which object will be dumped
+	maxDepth: 5,
+
+	// When enabled, all tests must call expect()
+	requireExpects: false,
+
+	// Placeholder for user-configurable form-exposed URL parameters
+	urlConfig: [],
+
+	// Set of all modules.
+	modules: [],
+
+	// Stack of nested modules
+	moduleStack: [],
+
+	// The first unnamed module
+	currentModule: {
+		name: "",
+		tests: []
+	},
+
+	callbacks: {}
+};
+
+// Push a loose unnamed module to the modules collection
+config.modules.push( config.currentModule );
+
+var loggingCallbacks = {};
+
+// Register logging callbacks
+function registerLoggingCallbacks( obj ) {
+	var i, l, key,
+		callbackNames = [ "begin", "done", "log", "testStart", "testDone",
+			"moduleStart", "moduleDone" ];
+
+	function registerLoggingCallback( key ) {
+		var loggingCallback = function( callback ) {
+			if ( objectType( callback ) !== "function" ) {
+				throw new Error(
+					"QUnit logging methods require a callback function as their first parameters."
+				);
+			}
+
+			config.callbacks[ key ].push( callback );
+		};
+
+		// DEPRECATED: This will be removed on QUnit 2.0.0+
+		// Stores the registered functions allowing restoring
+		// at verifyLoggingCallbacks() if modified
+		loggingCallbacks[ key ] = loggingCallback;
+
+		return loggingCallback;
+	}
+
+	for ( i = 0, l = callbackNames.length; i < l; i++ ) {
+		key = callbackNames[ i ];
+
+		// Initialize key collection of logging callback
+		if ( objectType( config.callbacks[ key ] ) === "undefined" ) {
+			config.callbacks[ key ] = [];
+		}
+
+		obj[ key ] = registerLoggingCallback( key );
+	}
+}
+
+function runLoggingCallbacks( key, args ) {
+	var i, l, callbacks;
+
+	callbacks = config.callbacks[ key ];
+	for ( i = 0, l = callbacks.length; i < l; i++ ) {
+		callbacks[ i ]( args );
+	}
+}
+
+// DEPRECATED: This will be removed on 2.0.0+
+// This function verifies if the loggingCallbacks were modified by the user
+// If so, it will restore it, assign the given callback and print a console warning
+function verifyLoggingCallbacks() {
+	var loggingCallback, userCallback;
+
+	for ( loggingCallback in loggingCallbacks ) {
+		if ( QUnit[ loggingCallback ] !== loggingCallbacks[ loggingCallback ] ) {
+
+			userCallback = QUnit[ loggingCallback ];
+
+			// Restore the callback function
+			QUnit[ loggingCallback ] = loggingCallbacks[ loggingCallback ];
+
+			// Assign the deprecated given callback
+			QUnit[ loggingCallback ]( userCallback );
+
+			if ( global.console && global.console.warn ) {
+				global.console.warn(
+					"QUnit." + loggingCallback + " was replaced with a new value.\n" +
+					"Please, check out the documentation on how to apply logging callbacks.\n" +
+					"Reference: https://api.qunitjs.com/category/callbacks/"
+				);
+			}
+		}
+	}
+}
+
+( function() {
+	if ( !defined.document ) {
+		return;
+	}
+
+	// `onErrorFnPrev` initialized at top of scope
+	// Preserve other handlers
+	var onErrorFnPrev = window.onerror;
+
+	// Cover uncaught exceptions
+	// Returning true will suppress the default browser handler,
+	// returning false will let it run.
+	window.onerror = function( error, filePath, linerNr ) {
+		var ret = false;
+		if ( onErrorFnPrev ) {
+			ret = onErrorFnPrev( error, filePath, linerNr );
+		}
+
+		// Treat return value as window.onerror itself does,
+		// Only do our handling if not suppressed.
+		if ( ret !== true ) {
+			if ( QUnit.config.current ) {
+				if ( QUnit.config.current.ignoreGlobalErrors ) {
+					return true;
+				}
+				QUnit.pushFailure( error, filePath + ":" + linerNr );
+			} else {
+				QUnit.test( "global failure", extend( function() {
+					QUnit.pushFailure( error, filePath + ":" + linerNr );
+				}, { validTest: true } ) );
+			}
+			return false;
+		}
+
+		return ret;
+	};
+}() );
+
+// Figure out if we're running the tests from a server or not
+QUnit.isLocal = !( defined.document && window.location.protocol !== "file:" );
+
+// Expose the current QUnit version
+QUnit.version = "1.23.1";
+
+extend( QUnit, {
+
+	// Call on start of module test to prepend name to all tests
+	module: function( name, testEnvironment, executeNow ) {
+		var module, moduleFns;
+		var currentModule = config.currentModule;
+
+		if ( arguments.length === 2 ) {
+			if ( objectType( testEnvironment ) === "function" ) {
+				executeNow = testEnvironment;
+				testEnvironment = undefined;
+			}
+		}
+
+		// DEPRECATED: handles setup/teardown functions,
+		// beforeEach and afterEach should be used instead
+		if ( testEnvironment && testEnvironment.setup ) {
+			testEnvironment.beforeEach = testEnvironment.setup;
+			delete testEnvironment.setup;
+		}
+		if ( testEnvironment && testEnvironment.teardown ) {
+			testEnvironment.afterEach = testEnvironment.teardown;
+			delete testEnvironment.teardown;
+		}
+
+		module = createModule();
+
+		moduleFns = {
+			beforeEach: setHook( module, "beforeEach" ),
+			afterEach: setHook( module, "afterEach" )
+		};
+
+		if ( objectType( executeNow ) === "function" ) {
+			config.moduleStack.push( module );
+			setCurrentModule( module );
+			executeNow.call( module.testEnvironment, moduleFns );
+			config.moduleStack.pop();
+			module = module.parentModule || currentModule;
+		}
+
+		setCurrentModule( module );
+
+		function createModule() {
+			var parentModule = config.moduleStack.length ?
+				config.moduleStack.slice( -1 )[ 0 ] : null;
+			var moduleName = parentModule !== null ?
+				[ parentModule.name, name ].join( " > " ) : name;
+			var module = {
+				name: moduleName,
+				parentModule: parentModule,
+				tests: [],
+				moduleId: generateHash( moduleName )
+			};
+
+			var env = {};
+			if ( parentModule ) {
+				extend( env, parentModule.testEnvironment );
+				delete env.beforeEach;
+				delete env.afterEach;
+			}
+			extend( env, testEnvironment );
+			module.testEnvironment = env;
+
+			config.modules.push( module );
+			return module;
+		}
+
+		function setCurrentModule( module ) {
+			config.currentModule = module;
+		}
+
+	},
+
+	// DEPRECATED: QUnit.asyncTest() will be removed in QUnit 2.0.
+	asyncTest: asyncTest,
+
+	test: test,
+
+	skip: skip,
+
+	only: only,
+
+	// DEPRECATED: The functionality of QUnit.start() will be altered in QUnit 2.0.
+	// In QUnit 2.0, invoking it will ONLY affect the `QUnit.config.autostart` blocking behavior.
+	start: function( count ) {
+		var globalStartAlreadyCalled = globalStartCalled;
+
+		if ( !config.current ) {
+			globalStartCalled = true;
+
+			if ( runStarted ) {
+				throw new Error( "Called start() outside of a test context while already started" );
+			} else if ( globalStartAlreadyCalled || count > 1 ) {
+				throw new Error( "Called start() outside of a test context too many times" );
+			} else if ( config.autostart ) {
+				throw new Error( "Called start() outside of a test context when " +
+					"QUnit.config.autostart was true" );
+			} else if ( !config.pageLoaded ) {
+
+				// The page isn't completely loaded yet, so bail out and let `QUnit.load` handle it
+				config.autostart = true;
+				return;
+			}
+		} else {
+
+			// If a test is running, adjust its semaphore
+			config.current.semaphore -= count || 1;
+
+			// If semaphore is non-numeric, throw error
+			if ( isNaN( config.current.semaphore ) ) {
+				config.current.semaphore = 0;
+
+				QUnit.pushFailure(
+					"Called start() with a non-numeric decrement.",
+					sourceFromStacktrace( 2 )
+				);
+				return;
+			}
+
+			// Don't start until equal number of stop-calls
+			if ( config.current.semaphore > 0 ) {
+				return;
+			}
+
+			// Throw an Error if start is called more often than stop
+			if ( config.current.semaphore < 0 ) {
+				config.current.semaphore = 0;
+
+				QUnit.pushFailure(
+					"Called start() while already started (test's semaphore was 0 already)",
+					sourceFromStacktrace( 2 )
+				);
+				return;
+			}
+		}
+
+		resumeProcessing();
+	},
+
+	// DEPRECATED: QUnit.stop() will be removed in QUnit 2.0.
+	stop: function( count ) {
+
+		// If there isn't a test running, don't allow QUnit.stop() to be called
+		if ( !config.current ) {
+			throw new Error( "Called stop() outside of a test context" );
+		}
+
+		// If a test is running, adjust its semaphore
+		config.current.semaphore += count || 1;
+
+		pauseProcessing();
+	},
+
+	config: config,
+
+	is: is,
+
+	objectType: objectType,
+
+	extend: extend,
+
+	load: function() {
+		config.pageLoaded = true;
+
+		// Initialize the configuration options
+		extend( config, {
+			stats: { all: 0, bad: 0 },
+			moduleStats: { all: 0, bad: 0 },
+			started: 0,
+			updateRate: 1000,
+			autostart: true,
+			filter: ""
+		}, true );
+
+		config.blocking = false;
+
+		if ( config.autostart ) {
+			resumeProcessing();
+		}
+	},
+
+	stack: function( offset ) {
+		offset = ( offset || 0 ) + 2;
+		return sourceFromStacktrace( offset );
+	}
+} );
+
+registerLoggingCallbacks( QUnit );
+
+function begin() {
+	var i, l,
+		modulesLog = [];
+
+	// If the test run hasn't officially begun yet
+	if ( !config.started ) {
+
+		// Record the time of the test run's beginning
+		config.started = now();
+
+		verifyLoggingCallbacks();
+
+		// Delete the loose unnamed module if unused.
+		if ( config.modules[ 0 ].name === "" && config.modules[ 0 ].tests.length === 0 ) {
+			config.modules.shift();
+		}
+
+		// Avoid unnecessary information by not logging modules' test environments
+		for ( i = 0, l = config.modules.length; i < l; i++ ) {
+			modulesLog.push( {
+				name: config.modules[ i ].name,
+				tests: config.modules[ i ].tests
+			} );
+		}
+
+		// The test run is officially beginning now
+		runLoggingCallbacks( "begin", {
+			totalTests: Test.count,
+			modules: modulesLog
+		} );
+	}
+
+	config.blocking = false;
+	process( true );
+}
+
+function process( last ) {
+	function next() {
+		process( last );
+	}
+	var start = now();
+	config.depth = ( config.depth || 0 ) + 1;
+
+	while ( config.queue.length && !config.blocking ) {
+		if ( !defined.setTimeout || config.updateRate <= 0 ||
+				( ( now() - start ) < config.updateRate ) ) {
+			if ( config.current ) {
+
+				// Reset async tracking for each phase of the Test lifecycle
+				config.current.usedAsync = false;
+			}
+			config.queue.shift()();
+		} else {
+			setTimeout( next, 13 );
+			break;
+		}
+	}
+	config.depth--;
+	if ( last && !config.blocking && !config.queue.length && config.depth === 0 ) {
+		done();
+	}
+}
+
+function pauseProcessing() {
+	config.blocking = true;
+
+	if ( config.testTimeout && defined.setTimeout ) {
+		clearTimeout( config.timeout );
+		config.timeout = setTimeout( function() {
+			if ( config.current ) {
+				config.current.semaphore = 0;
+				QUnit.pushFailure( "Test timed out", sourceFromStacktrace( 2 ) );
+			} else {
+				throw new Error( "Test timed out" );
+			}
+			resumeProcessing();
+		}, config.testTimeout );
+	}
+}
+
+function resumeProcessing() {
+	runStarted = true;
+
+	// A slight delay to allow this iteration of the event loop to finish (more assertions, etc.)
+	if ( defined.setTimeout ) {
+		setTimeout( function() {
+			if ( config.current && config.current.semaphore > 0 ) {
+				return;
+			}
+			if ( config.timeout ) {
+				clearTimeout( config.timeout );
+			}
+
+			begin();
+		}, 13 );
+	} else {
+		begin();
+	}
+}
+
+function done() {
+	var runtime, passed;
+
+	config.autorun = true;
+
+	// Log the last module results
+	if ( config.previousModule ) {
+		runLoggingCallbacks( "moduleDone", {
+			name: config.previousModule.name,
+			tests: config.previousModule.tests,
+			failed: config.moduleStats.bad,
+			passed: config.moduleStats.all - config.moduleStats.bad,
+			total: config.moduleStats.all,
+			runtime: now() - config.moduleStats.started
+		} );
+	}
+	delete config.previousModule;
+
+	runtime = now() - config.started;
+	passed = config.stats.all - config.stats.bad;
+
+	runLoggingCallbacks( "done", {
+		failed: config.stats.bad,
+		passed: passed,
+		total: config.stats.all,
+		runtime: runtime
+	} );
+}
+
+function setHook( module, hookName ) {
+	if ( module.testEnvironment === undefined ) {
+		module.testEnvironment = {};
+	}
+
+	return function( callback ) {
+		module.testEnvironment[ hookName ] = callback;
+	};
+}
+
+var focused = false;
+var priorityCount = 0;
+var unitSampler;
+
+function Test( settings ) {
+	var i, l;
+
+	++Test.count;
+
+	extend( this, settings );
+	this.assertions = [];
+	this.semaphore = 0;
+	this.usedAsync = false;
+	this.module = config.currentModule;
+	this.stack = sourceFromStacktrace( 3 );
+
+	// Register unique strings
+	for ( i = 0, l = this.module.tests; i < l.length; i++ ) {
+		if ( this.module.tests[ i ].name === this.testName ) {
+			this.testName += " ";
+		}
+	}
+
+	this.testId = generateHash( this.module.name, this.testName );
+
+	this.module.tests.push( {
+		name: this.testName,
+		testId: this.testId
+	} );
+
+	if ( settings.skip ) {
+
+		// Skipped tests will fully ignore any sent callback
+		this.callback = function() {};
+		this.async = false;
+		this.expected = 0;
+	} else {
+		this.assert = new Assert( this );
+	}
+}
+
+Test.count = 0;
+
+Test.prototype = {
+	before: function() {
+		if (
+
+			// Emit moduleStart when we're switching from one module to another
+			this.module !== config.previousModule ||
+
+				// They could be equal (both undefined) but if the previousModule property doesn't
+				// yet exist it means this is the first test in a suite that isn't wrapped in a
+				// module, in which case we'll just emit a moduleStart event for 'undefined'.
+				// Without this, reporters can get testStart before moduleStart  which is a problem.
+				!hasOwn.call( config, "previousModule" )
+		) {
+			if ( hasOwn.call( config, "previousModule" ) ) {
+				runLoggingCallbacks( "moduleDone", {
+					name: config.previousModule.name,
+					tests: config.previousModule.tests,
+					failed: config.moduleStats.bad,
+					passed: config.moduleStats.all - config.moduleStats.bad,
+					total: config.moduleStats.all,
+					runtime: now() - config.moduleStats.started
+				} );
+			}
+			config.previousModule = this.module;
+			config.moduleStats = { all: 0, bad: 0, started: now() };
+			runLoggingCallbacks( "moduleStart", {
+				name: this.module.name,
+				tests: this.module.tests
+			} );
+		}
+
+		config.current = this;
+
+		if ( this.module.testEnvironment ) {
+			delete this.module.testEnvironment.beforeEach;
+			delete this.module.testEnvironment.afterEach;
+		}
+		this.testEnvironment = extend( {}, this.module.testEnvironment );
+
+		this.started = now();
+		runLoggingCallbacks( "testStart", {
+			name: this.testName,
+			module: this.module.name,
+			testId: this.testId
+		} );
+
+		if ( !config.pollution ) {
+			saveGlobal();
+		}
+	},
+
+	run: function() {
+		var promise;
+
+		config.current = this;
+
+		if ( this.async ) {
+			QUnit.stop();
+		}
+
+		this.callbackStarted = now();
+
+		if ( config.notrycatch ) {
+			runTest( this );
+			return;
+		}
+
+		try {
+			runTest( this );
+		} catch ( e ) {
+			this.pushFailure( "Died on test #" + ( this.assertions.length + 1 ) + " " +
+				this.stack + ": " + ( e.message || e ), extractStacktrace( e, 0 ) );
+
+			// Else next test will carry the responsibility
+			saveGlobal();
+
+			// Restart the tests if they're blocking
+			if ( config.blocking ) {
+				QUnit.start();
+			}
+		}
+
+		function runTest( test ) {
+			promise = test.callback.call( test.testEnvironment, test.assert );
+			test.resolvePromise( promise );
+		}
+	},
+
+	after: function() {
+		checkPollution();
+	},
+
+	queueHook: function( hook, hookName ) {
+		var promise,
+			test = this;
+		return function runHook() {
+			config.current = test;
+			if ( config.notrycatch ) {
+				callHook();
+				return;
+			}
+			try {
+				callHook();
+			} catch ( error ) {
+				test.pushFailure( hookName + " failed on " + test.testName + ": " +
+				( error.message || error ), extractStacktrace( error, 0 ) );
+			}
+
+			function callHook() {
+				promise = hook.call( test.testEnvironment, test.assert );
+				test.resolvePromise( promise, hookName );
+			}
+		};
+	},
+
+	// Currently only used for module level hooks, can be used to add global level ones
+	hooks: function( handler ) {
+		var hooks = [];
+
+		function processHooks( test, module ) {
+			if ( module.parentModule ) {
+				processHooks( test, module.parentModule );
+			}
+			if ( module.testEnvironment &&
+				QUnit.objectType( module.testEnvironment[ handler ] ) === "function" ) {
+				hooks.push( test.queueHook( module.testEnvironment[ handler ], handler ) );
+			}
+		}
+
+		// Hooks are ignored on skipped tests
+		if ( !this.skip ) {
+			processHooks( this, this.module );
+		}
+		return hooks;
+	},
+
+	finish: function() {
+		config.current = this;
+		if ( config.requireExpects && this.expected === null ) {
+			this.pushFailure( "Expected number of assertions to be defined, but expect() was " +
+				"not called.", this.stack );
+		} else if ( this.expected !== null && this.expected !== this.assertions.length ) {
+			this.pushFailure( "Expected " + this.expected + " assertions, but " +
+				this.assertions.length + " were run", this.stack );
+		} else if ( this.expected === null && !this.assertions.length ) {
+			this.pushFailure( "Expected at least one assertion, but none were run - call " +
+				"expect(0) to accept zero assertions.", this.stack );
+		}
+
+		var i,
+			bad = 0;
+
+		this.runtime = now() - this.started;
+		config.stats.all += this.assertions.length;
+		config.moduleStats.all += this.assertions.length;
+
+		for ( i = 0; i < this.assertions.length; i++ ) {
+			if ( !this.assertions[ i ].result ) {
+				bad++;
+				config.stats.bad++;
+				config.moduleStats.bad++;
+			}
+		}
+
+		runLoggingCallbacks( "testDone", {
+			name: this.testName,
+			module: this.module.name,
+			skipped: !!this.skip,
+			failed: bad,
+			passed: this.assertions.length - bad,
+			total: this.assertions.length,
+			runtime: this.runtime,
+
+			// HTML Reporter use
+			assertions: this.assertions,
+			testId: this.testId,
+
+			// Source of Test
+			source: this.stack,
+
+			// DEPRECATED: this property will be removed in 2.0.0, use runtime instead
+			duration: this.runtime
+		} );
+
+		// QUnit.reset() is deprecated and will be replaced for a new
+		// fixture reset function on QUnit 2.0/2.1.
+		// It's still called here for backwards compatibility handling
+		QUnit.reset();
+
+		config.current = undefined;
+	},
+
+	queue: function() {
+		var priority,
+			test = this;
+
+		if ( !this.valid() ) {
+			return;
+		}
+
+		function run() {
+
+			// Each of these can by async
+			synchronize( [
+				function() {
+					test.before();
+				},
+
+				test.hooks( "beforeEach" ),
+				function() {
+					test.run();
+				},
+
+				test.hooks( "afterEach" ).reverse(),
+
+				function() {
+					test.after();
+				},
+				function() {
+					test.finish();
+				}
+			] );
+		}
+
+		// Prioritize previously failed tests, detected from sessionStorage
+		priority = QUnit.config.reorder && defined.sessionStorage &&
+				+sessionStorage.getItem( "qunit-test-" + this.module.name + "-" + this.testName );
+
+		return synchronize( run, priority, config.seed );
+	},
+
+	pushResult: function( resultInfo ) {
+
+		// Destructure of resultInfo = { result, actual, expected, message, negative }
+		var source,
+			details = {
+				module: this.module.name,
+				name: this.testName,
+				result: resultInfo.result,
+				message: resultInfo.message,
+				actual: resultInfo.actual,
+				expected: resultInfo.expected,
+				testId: this.testId,
+				negative: resultInfo.negative || false,
+				runtime: now() - this.started
+			};
+
+		if ( !resultInfo.result ) {
+			source = sourceFromStacktrace();
+
+			if ( source ) {
+				details.source = source;
+			}
+		}
+
+		runLoggingCallbacks( "log", details );
+
+		this.assertions.push( {
+			result: !!resultInfo.result,
+			message: resultInfo.message
+		} );
+	},
+
+	pushFailure: function( message, source, actual ) {
+		if ( !( this instanceof Test ) ) {
+			throw new Error( "pushFailure() assertion outside test context, was " +
+				sourceFromStacktrace( 2 ) );
+		}
+
+		var details = {
+				module: this.module.name,
+				name: this.testName,
+				result: false,
+				message: message || "error",
+				actual: actual || null,
+				testId: this.testId,
+				runtime: now() - this.started
+			};
+
+		if ( source ) {
+			details.source = source;
+		}
+
+		runLoggingCallbacks( "log", details );
+
+		this.assertions.push( {
+			result: false,
+			message: message
+		} );
+	},
+
+	resolvePromise: function( promise, phase ) {
+		var then, message,
+			test = this;
+		if ( promise != null ) {
+			then = promise.then;
+			if ( QUnit.objectType( then ) === "function" ) {
+				QUnit.stop();
+				then.call(
+					promise,
+					function() { QUnit.start(); },
+					function( error ) {
+						message = "Promise rejected " +
+							( !phase ? "during" : phase.replace( /Each$/, "" ) ) +
+							" " + test.testName + ": " + ( error.message || error );
+						test.pushFailure( message, extractStacktrace( error, 0 ) );
+
+						// Else next test will carry the responsibility
+						saveGlobal();
+
+						// Unblock
+						QUnit.start();
+					}
+				);
+			}
+		}
+	},
+
+	valid: function() {
+		var filter = config.filter,
+			regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec( filter ),
+			module = config.module && config.module.toLowerCase(),
+			fullName = ( this.module.name + ": " + this.testName );
+
+		function moduleChainNameMatch( testModule ) {
+			var testModuleName = testModule.name ? testModule.name.toLowerCase() : null;
+			if ( testModuleName === module ) {
+				return true;
+			} else if ( testModule.parentModule ) {
+				return moduleChainNameMatch( testModule.parentModule );
+			} else {
+				return false;
+			}
+		}
+
+		function moduleChainIdMatch( testModule ) {
+			return inArray( testModule.moduleId, config.moduleId ) > -1 ||
+				testModule.parentModule && moduleChainIdMatch( testModule.parentModule );
+		}
+
+		// Internally-generated tests are always valid
+		if ( this.callback && this.callback.validTest ) {
+			return true;
+		}
+
+		if ( config.moduleId && config.moduleId.length > 0 &&
+			!moduleChainIdMatch( this.module ) ) {
+
+			return false;
+		}
+
+		if ( config.testId && config.testId.length > 0 &&
+			inArray( this.testId, config.testId ) < 0 ) {
+
+			return false;
+		}
+
+		if ( module && !moduleChainNameMatch( this.module ) ) {
+			return false;
+		}
+
+		if ( !filter ) {
+			return true;
+		}
+
+		return regexFilter ?
+			this.regexFilter( !!regexFilter[ 1 ], regexFilter[ 2 ], regexFilter[ 3 ], fullName ) :
+			this.stringFilter( filter, fullName );
+	},
+
+	regexFilter: function( exclude, pattern, flags, fullName ) {
+		var regex = new RegExp( pattern, flags );
+		var match = regex.test( fullName );
+
+		return match !== exclude;
+	},
+
+	stringFilter: function( filter, fullName ) {
+		filter = filter.toLowerCase();
+		fullName = fullName.toLowerCase();
+
+		var include = filter.charAt( 0 ) !== "!";
+		if ( !include ) {
+			filter = filter.slice( 1 );
+		}
+
+		// If the filter matches, we need to honour include
+		if ( fullName.indexOf( filter ) !== -1 ) {
+			return include;
+		}
+
+		// Otherwise, do the opposite
+		return !include;
+	}
+};
+
+// Resets the test setup. Useful for tests that modify the DOM.
+/*
+DEPRECATED: Use multiple tests instead of resetting inside a test.
+Use testStart or testDone for custom cleanup.
+This method will throw an error in 2.0, and will be removed in 2.1
+*/
+QUnit.reset = function() {
+
+	// Return on non-browser environments
+	// This is necessary to not break on node tests
+	if ( !defined.document ) {
+		return;
+	}
+
+	var fixture = defined.document && document.getElementById &&
+			document.getElementById( "qunit-fixture" );
+
+	if ( fixture ) {
+		fixture.innerHTML = config.fixture;
+	}
+};
+
+QUnit.pushFailure = function() {
+	if ( !QUnit.config.current ) {
+		throw new Error( "pushFailure() assertion outside test context, in " +
+			sourceFromStacktrace( 2 ) );
+	}
+
+	// Gets current test obj
+	var currentTest = QUnit.config.current;
+
+	return currentTest.pushFailure.apply( currentTest, arguments );
+};
+
+// Based on Java's String.hashCode, a simple but not
+// rigorously collision resistant hashing function
+function generateHash( module, testName ) {
+	var hex,
+		i = 0,
+		hash = 0,
+		str = module + "\x1C" + testName,
+		len = str.length;
+
+	for ( ; i < len; i++ ) {
+		hash  = ( ( hash << 5 ) - hash ) + str.charCodeAt( i );
+		hash |= 0;
+	}
+
+	// Convert the possibly negative integer hash code into an 8 character hex string, which isn't
+	// strictly necessary but increases user understanding that the id is a SHA-like hash
+	hex = ( 0x100000000 + hash ).toString( 16 );
+	if ( hex.length < 8 ) {
+		hex = "0000000" + hex;
+	}
+
+	return hex.slice( -8 );
+}
+
+function synchronize( callback, priority, seed ) {
+	var last = !priority,
+		index;
+
+	if ( QUnit.objectType( callback ) === "array" ) {
+		while ( callback.length ) {
+			synchronize( callback.shift() );
+		}
+		return;
+	}
+
+	if ( priority ) {
+		config.queue.splice( priorityCount++, 0, callback );
+	} else if ( seed ) {
+		if ( !unitSampler ) {
+			unitSampler = unitSamplerGenerator( seed );
+		}
+
+		// Insert into a random position after all priority items
+		index = Math.floor( unitSampler() * ( config.queue.length - priorityCount + 1 ) );
+		config.queue.splice( priorityCount + index, 0, callback );
+	} else {
+		config.queue.push( callback );
+	}
+
+	if ( config.autorun && !config.blocking ) {
+		process( last );
+	}
+}
+
+function unitSamplerGenerator( seed ) {
+
+	// 32-bit xorshift, requires only a nonzero seed
+	// http://excamera.com/sphinx/article-xorshift.html
+	var sample = parseInt( generateHash( seed ), 16 ) || -1;
+	return function() {
+		sample ^= sample << 13;
+		sample ^= sample >>> 17;
+		sample ^= sample << 5;
+
+		// ECMAScript has no unsigned number type
+		if ( sample < 0 ) {
+			sample += 0x100000000;
+		}
+
+		return sample / 0x100000000;
+	};
+}
+
+function saveGlobal() {
+	config.pollution = [];
+
+	if ( config.noglobals ) {
+		for ( var key in global ) {
+			if ( hasOwn.call( global, key ) ) {
+
+				// In Opera sometimes DOM element ids show up here, ignore them
+				if ( /^qunit-test-output/.test( key ) ) {
+					continue;
+				}
+				config.pollution.push( key );
+			}
+		}
+	}
+}
+
+function checkPollution() {
+	var newGlobals,
+		deletedGlobals,
+		old = config.pollution;
+
+	saveGlobal();
+
+	newGlobals = diff( config.pollution, old );
+	if ( newGlobals.length > 0 ) {
+		QUnit.pushFailure( "Introduced global variable(s): " + newGlobals.join( ", " ) );
+	}
+
+	deletedGlobals = diff( old, config.pollution );
+	if ( deletedGlobals.length > 0 ) {
+		QUnit.pushFailure( "Deleted global variable(s): " + deletedGlobals.join( ", " ) );
+	}
+}
+
+// Will be exposed as QUnit.asyncTest
+function asyncTest( testName, expected, callback ) {
+	if ( arguments.length === 2 ) {
+		callback = expected;
+		expected = null;
+	}
+
+	QUnit.test( testName, expected, callback, true );
+}
+
+// Will be exposed as QUnit.test
+function test( testName, expected, callback, async ) {
+	if ( focused )  { return; }
+
+	var newTest;
+
+	if ( arguments.length === 2 ) {
+		callback = expected;
+		expected = null;
+	}
+
+	newTest = new Test( {
+		testName: testName,
+		expected: expected,
+		async: async,
+		callback: callback
+	} );
+
+	newTest.queue();
+}
+
+// Will be exposed as QUnit.skip
+function skip( testName ) {
+	if ( focused )  { return; }
+
+	var test = new Test( {
+		testName: testName,
+		skip: true
+	} );
+
+	test.queue();
+}
+
+// Will be exposed as QUnit.only
+function only( testName, expected, callback, async ) {
+	var newTest;
+
+	if ( focused )  { return; }
+
+	QUnit.config.queue.length = 0;
+	focused = true;
+
+	if ( arguments.length === 2 ) {
+		callback = expected;
+		expected = null;
+	}
+
+	newTest = new Test( {
+		testName: testName,
+		expected: expected,
+		async: async,
+		callback: callback
+	} );
+
+	newTest.queue();
+}
+
+function Assert( testContext ) {
+	this.test = testContext;
+}
+
+// Assert helpers
+QUnit.assert = Assert.prototype = {
+
+	// Specify the number of expected assertions to guarantee that failed test
+	// (no assertions are run at all) don't slip through.
+	expect: function( asserts ) {
+		if ( arguments.length === 1 ) {
+			this.test.expected = asserts;
+		} else {
+			return this.test.expected;
+		}
+	},
+
+	// Increment this Test's semaphore counter, then return a function that
+	// decrements that counter a maximum of once.
+	async: function( count ) {
+		var test = this.test,
+			popped = false,
+			acceptCallCount = count;
+
+		if ( typeof acceptCallCount === "undefined" ) {
+			acceptCallCount = 1;
+		}
+
+		test.semaphore += 1;
+		test.usedAsync = true;
+		pauseProcessing();
+
+		return function done() {
+
+			if ( popped ) {
+				test.pushFailure( "Too many calls to the `assert.async` callback",
+					sourceFromStacktrace( 2 ) );
+				return;
+			}
+			acceptCallCount -= 1;
+			if ( acceptCallCount > 0 ) {
+				return;
+			}
+
+			test.semaphore -= 1;
+			popped = true;
+			resumeProcessing();
+		};
+	},
+
+	// Exports test.push() to the user API
+	// Alias of pushResult.
+	push: function( result, actual, expected, message, negative ) {
+		var currentAssert = this instanceof Assert ? this : QUnit.config.current.assert;
+		return currentAssert.pushResult( {
+			result: result,
+			actual: actual,
+			expected: expected,
+			message: message,
+			negative: negative
+		} );
+	},
+
+	pushResult: function( resultInfo ) {
+
+		// Destructure of resultInfo = { result, actual, expected, message, negative }
+		var assert = this,
+			currentTest = ( assert instanceof Assert && assert.test ) || QUnit.config.current;
+
+		// Backwards compatibility fix.
+		// Allows the direct use of global exported assertions and QUnit.assert.*
+		// Although, it's use is not recommended as it can leak assertions
+		// to other tests from async tests, because we only get a reference to the current test,
+		// not exactly the test where assertion were intended to be called.
+		if ( !currentTest ) {
+			throw new Error( "assertion outside test context, in " + sourceFromStacktrace( 2 ) );
+		}
+
+		if ( currentTest.usedAsync === true && currentTest.semaphore === 0 ) {
+			currentTest.pushFailure( "Assertion after the final `assert.async` was resolved",
+				sourceFromStacktrace( 2 ) );
+
+			// Allow this assertion to continue running anyway...
+		}
+
+		if ( !( assert instanceof Assert ) ) {
+			assert = currentTest.assert;
+		}
+
+		return assert.test.pushResult( resultInfo );
+	},
+
+	ok: function( result, message ) {
+		message = message || ( result ? "okay" : "failed, expected argument to be truthy, was: " +
+			QUnit.dump.parse( result ) );
+		this.pushResult( {
+			result: !!result,
+			actual: result,
+			expected: true,
+			message: message
+		} );
+	},
+
+	notOk: function( result, message ) {
+		message = message || ( !result ? "okay" : "failed, expected argument to be falsy, was: " +
+			QUnit.dump.parse( result ) );
+		this.pushResult( {
+			result: !result,
+			actual: result,
+			expected: false,
+			message: message
+		} );
+	},
+
+	equal: function( actual, expected, message ) {
+		/*jshint eqeqeq:false */
+		this.pushResult( {
+			result: expected == actual,
+			actual: actual,
+			expected: expected,
+			message: message
+		} );
+	},
+
+	notEqual: function( actual, expected, message ) {
+		/*jshint eqeqeq:false */
+		this.pushResult( {
+			result: expected != actual,
+			actual: actual,
+			expected: expected,
+			message: message,
+			negative: true
+		} );
+	},
+
+	propEqual: function( actual, expected, message ) {
+		actual = objectValues( actual );
+		expected = objectValues( expected );
+		this.pushResult( {
+			result: QUnit.equiv( actual, expected ),
+			actual: actual,
+			expected: expected,
+			message: message
+		} );
+	},
+
+	notPropEqual: function( actual, expected, message ) {
+		actual = objectValues( actual );
+		expected = objectValues( expected );
+		this.pushResult( {
+			result: !QUnit.equiv( actual, expected ),
+			actual: actual,
+			expected: expected,
+			message: message,
+			negative: true
+		} );
+	},
+
+	deepEqual: function( actual, expected, message ) {
+		this.pushResult( {
+			result: QUnit.equiv( actual, expected ),
+			actual: actual,
+			expected: expected,
+			message: message
+		} );
+	},
+
+	notDeepEqual: function( actual, expected, message ) {
+		this.pushResult( {
+			result: !QUnit.equiv( actual, expected ),
+			actual: actual,
+			expected: expected,
+			message: message,
+			negative: true
+		} );
+	},
+
+	strictEqual: function( actual, expected, message ) {
+		this.pushResult( {
+			result: expected === actual,
+			actual: actual,
+			expected: expected,
+			message: message
+		} );
+	},
+
+	notStrictEqual: function( actual, expected, message ) {
+		this.pushResult( {
+			result: expected !== actual,
+			actual: actual,
+			expected: expected,
+			message: message,
+			negative: true
+		} );
+	},
+
+	"throws": function( block, expected, message ) {
+		var actual, expectedType,
+			expectedOutput = expected,
+			ok = false,
+			currentTest = ( this instanceof Assert && this.test ) || QUnit.config.current;
+
+		// 'expected' is optional unless doing string comparison
+		if ( message == null && typeof expected === "string" ) {
+			message = expected;
+			expected = null;
+		}
+
+		currentTest.ignoreGlobalErrors = true;
+		try {
+			block.call( currentTest.testEnvironment );
+		} catch ( e ) {
+			actual = e;
+		}
+		currentTest.ignoreGlobalErrors = false;
+
+		if ( actual ) {
+			expectedType = QUnit.objectType( expected );
+
+			// We don't want to validate thrown error
+			if ( !expected ) {
+				ok = true;
+				expectedOutput = null;
+
+			// Expected is a regexp
+			} else if ( expectedType === "regexp" ) {
+				ok = expected.test( errorString( actual ) );
+
+			// Expected is a string
+			} else if ( expectedType === "string" ) {
+				ok = expected === errorString( actual );
+
+			// Expected is a constructor, maybe an Error constructor
+			} else if ( expectedType === "function" && actual instanceof expected ) {
+				ok = true;
+
+			// Expected is an Error object
+			} else if ( expectedType === "object" ) {
+				ok = actual instanceof expected.constructor &&
+					actual.name === expected.name &&
+					actual.message === expected.message;
+
+			// Expected is a validation function which returns true if validation passed
+			} else if ( expectedType === "function" && expected.call( {}, actual ) === true ) {
+				expectedOutput = null;
+				ok = true;
+			}
+		}
+
+		currentTest.assert.pushResult( {
+			result: ok,
+			actual: actual,
+			expected: expectedOutput,
+			message: message
+		} );
+	}
+};
+
+// Provide an alternative to assert.throws(), for environments that consider throws a reserved word
+// Known to us are: Closure Compiler, Narwhal
+( function() {
+	/*jshint sub:true */
+	Assert.prototype.raises = Assert.prototype [ "throws" ]; //jscs:ignore requireDotNotation
+}() );
+
+function errorString( error ) {
+	var name, message,
+		resultErrorString = error.toString();
+	if ( resultErrorString.substring( 0, 7 ) === "[object" ) {
+		name = error.name ? error.name.toString() : "Error";
+		message = error.message ? error.message.toString() : "";
+		if ( name && message ) {
+			return name + ": " + message;
+		} else if ( name ) {
+			return name;
+		} else if ( message ) {
+			return message;
+		} else {
+			return "Error";
+		}
+	} else {
+		return resultErrorString;
+	}
+}
+
+// Test for equality any JavaScript type.
+// Author: Philippe Rathé <pr...@gmail.com>
+QUnit.equiv = ( function() {
+
+	// Stack to decide between skip/abort functions
+	var callers = [];
+
+	// Stack to avoiding loops from circular referencing
+	var parents = [];
+	var parentsB = [];
+
+	var getProto = Object.getPrototypeOf || function( obj ) {
+
+		/*jshint proto: true */
+		return obj.__proto__;
+	};
+
+	function useStrictEquality( b, a ) {
+
+		// To catch short annotation VS 'new' annotation of a declaration. e.g.:
+		// `var i = 1;`
+		// `var j = new Number(1);`
+		if ( typeof a === "object" ) {
+			a = a.valueOf();
+		}
+		if ( typeof b === "object" ) {
+			b = b.valueOf();
+		}
+
+		return a === b;
+	}
+
+	function compareConstructors( a, b ) {
+		var protoA = getProto( a );
+		var protoB = getProto( b );
+
+		// Comparing constructors is more strict than using `instanceof`
+		if ( a.constructor === b.constructor ) {
+			return true;
+		}
+
+		// Ref #851
+		// If the obj prototype descends from a null constructor, treat it
+		// as a null prototype.
+		if ( protoA && protoA.constructor === null ) {
+			protoA = null;
+		}
+		if ( protoB && protoB.constructor === null ) {
+			protoB = null;
+		}
+
+		// Allow objects with no prototype to be equivalent to
+		// objects with Object as their constructor.
+		if ( ( protoA === null && protoB === Object.prototype ) ||
+				( protoB === null && protoA === Object.prototype ) ) {
+			return true;
+		}
+
+		return false;
+	}
+
+	function getRegExpFlags( regexp ) {
+		return "flags" in regexp ? regexp.flags : regexp.toString().match( /[gimuy]*$/ )[ 0 ];
+	}
+
+	var callbacks = {
+		"string": useStrictEquality,
+		"boolean": useStrictEquality,
+		"number": useStrictEquality,
+		"null": useStrictEquality,
+		"undefined": useStrictEquality,
+		"symbol": useStrictEquality,
+		"date": useStrictEquality,
+
+		"nan": function() {
+			return true;
+		},
+
+		"regexp": function( b, a ) {
+			return a.source === b.source &&
+
+				// Include flags in the comparison
+				getRegExpFlags( a ) === getRegExpFlags( b );
+		},
+
+		// - skip when the property is a method of an instance (OOP)
+		// - abort otherwise,
+		// initial === would have catch identical references anyway
+		"function": function() {
+			var caller = callers[ callers.length - 1 ];
+			return caller !== Object && typeof caller !== "undefined";
+		},
+
+		"array": function( b, a ) {
+			var i, j, len, loop, aCircular, bCircular;
+
+			len = a.length;
+			if ( len !== b.length ) {
+
+				// Safe and faster
+				return false;
+			}
+
+			// Track reference to avoid circular references
+			parents.push( a );
+			parentsB.push( b );
+			for ( i = 0; i < len; i++ ) {
+				loop = false;
+				for ( j = 0; j < parents.length; j++ ) {
+					aCircular = parents[ j ] === a[ i ];
+					bCircular = parentsB[ j ] === b[ i ];
+					if ( aCircular || bCircular ) {
+						if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
+							loop = true;
+						} else {
+							parents.pop();
+							parentsB.pop();
+							return false;
+						}
+					}
+				}
+				if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
+					parents.pop();
+					parentsB.pop();
+					return false;
+				}
+			}
+			parents.pop();
+			parentsB.pop();
+			return true;
+		},
+
+		"set": function( b, a ) {
+			var innerEq,
+				outerEq = true;
+
+			if ( a.size !== b.size ) {
+				return false;
+			}
+
+			a.forEach( function( aVal ) {
+				innerEq = false;
+
+				b.forEach( function( bVal ) {
+					if ( innerEquiv( bVal, aVal ) ) {
+						innerEq = true;
+					}
+				} );
+
+				if ( !innerEq ) {
+					outerEq = false;
+				}
+			} );
+
+			return outerEq;
+		},
+
+		"map": function( b, a ) {
+			var innerEq,
+				outerEq = true;
+
+			if ( a.size !== b.size ) {
+				return false;
+			}
+
+			a.forEach( function( aVal, aKey ) {
+				innerEq = false;
+
+				b.forEach( function( bVal, bKey ) {
+					if ( innerEquiv( [ bVal, bKey ], [ aVal, aKey ] ) ) {
+						innerEq = true;
+					}
+				} );
+
+				if ( !innerEq ) {
+					outerEq = false;
+				}
+			} );
+
+			return outerEq;
+		},
+
+		"object": function( b, a ) {
+			var i, j, loop, aCircular, bCircular;
+
+			// Default to true
+			var eq = true;
+			var aProperties = [];
+			var bProperties = [];
+
+			if ( compareConstructors( a, b ) === false ) {
+				return false;
+			}
+
+			// Stack constructor before traversing properties
+			callers.push( a.constructor );
+
+			// Track reference to avoid circular references
+			parents.push( a );
+			parentsB.push( b );
+
+			// Be strict: don't ensure hasOwnProperty and go deep
+			for ( i in a ) {
+				loop = false;
+				for ( j = 0; j < parents.length; j++ ) {
+					aCircular = parents[ j ] === a[ i ];
+					bCircular = parentsB[ j ] === b[ i ];
+					if ( aCircular || bCircular ) {
+						if ( a[ i ] === b[ i ] || aCircular && bCircular ) {
+							loop = true;
+						} else {
+							eq = false;
+							break;
+						}
+					}
+				}
+				aProperties.push( i );
+				if ( !loop && !innerEquiv( a[ i ], b[ i ] ) ) {
+					eq = false;
+					break;
+				}
+			}
+
+			parents.pop();
+			parentsB.pop();
+
+			// Unstack, we are done
+			callers.pop();
+
+			for ( i in b ) {
+
+				// Collect b's properties
+				bProperties.push( i );
+			}
+
+			// Ensures identical properties name
+			return eq && innerEquiv( aProperties.sort(), bProperties.sort() );
+		}
+	};
+
+	function typeEquiv( a, b ) {
+		var type = QUnit.objectType( a );
+		return QUnit.objectType( b ) === type && callbacks[ type ]( b, a );
+	}
+
+	// The real equiv function
+	function innerEquiv( a, b ) {
+
+		// We're done when there's nothing more to compare
+		if ( arguments.length < 2 ) {
+			return true;
+		}
+
+		// Require type-specific equality
+		return ( a === b || typeEquiv( a, b ) ) &&
+
+			// ...across all consecutive argument pairs
+			( arguments.length === 2 || innerEquiv.apply( this, [].slice.call( arguments, 1 ) ) );
+	}
+
+	return innerEquiv;
+}() );
+
+// Based on jsDump by Ariel Flesler
+// http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
+QUnit.dump = ( function() {
+	function quote( str ) {
+		return "\"" + str.toString().replace( /\\/g, "\\\\" ).replace( /"/g, "\\\"" ) + "\"";
+	}
+	function literal( o ) {
+		return o + "";
+	}
+	function join( pre, arr, post ) {
+		var s = dump.separator(),
+			base = dump.indent(),
+			inner = dump.indent( 1 );
+		if ( arr.join ) {
+			arr = arr.join( "," + s + inner );
+		}
+		if ( !arr ) {
+			return pre + post;
+		}
+		return [ pre, inner + arr, base + post ].join( s );
+	}
+	function array( arr, stack ) {
+		var i = arr.length,
+			ret = new Array( i );
+
+		if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
+			return "[object Array]";
+		}
+
+		this.up();
+		while ( i-- ) {
+			ret[ i ] = this.parse( arr[ i ], undefined, stack );
+		}
+		this.down();
+		return join( "[", ret, "]" );
+	}
+
+	var reName = /^function (\w+)/,
+		dump = {
+
+			// The objType is used mostly internally, you can fix a (custom) type in advance
+			parse: function( obj, objType, stack ) {
+				stack = stack || [];
+				var res, parser, parserType,
+					inStack = inArray( obj, stack );
+
+				if ( inStack !== -1 ) {
+					return "recursion(" + ( inStack - stack.length ) + ")";
+				}
+
+				objType = objType || this.typeOf( obj  );
+				parser = this.parsers[ objType ];
+				parserType = typeof parser;
+
+				if ( parserType === "function" ) {
+					stack.push( obj );
+					res = parser.call( this, obj, stack );
+					stack.pop();
+					return res;
+				}
+				return ( parserType === "string" ) ? parser : this.parsers.error;
+			},
+			typeOf: function( obj ) {
+				var type;
+				if ( obj === null ) {
+					type = "null";
+				} else if ( typeof obj === "undefined" ) {
+					type = "undefined";
+				} else if ( QUnit.is( "regexp", obj ) ) {
+					type = "regexp";
+				} else if ( QUnit.is( "date", obj ) ) {
+					type = "date";
+				} else if ( QUnit.is( "function", obj ) ) {
+					type = "function";
+				} else if ( obj.setInterval !== undefined &&
+						obj.document !== undefined &&
+						obj.nodeType === undefined ) {
+					type = "window";
+				} else if ( obj.nodeType === 9 ) {
+					type = "document";
+				} else if ( obj.nodeType ) {
+					type = "node";
+				} else if (
+
+					// Native arrays
+					toString.call( obj ) === "[object Array]" ||
+
+					// NodeList objects
+					( typeof obj.length === "number" && obj.item !== undefined &&
+					( obj.length ? obj.item( 0 ) === obj[ 0 ] : ( obj.item( 0 ) === null &&
+					obj[ 0 ] === undefined ) ) )
+				) {
+					type = "array";
+				} else if ( obj.constructor === Error.prototype.constructor ) {
+					type = "error";
+				} else {
+					type = typeof obj;
+				}
+				return type;
+			},
+
+			separator: function() {
+				return this.multiline ? this.HTML ? "<br />" : "\n" : this.HTML ? "&#160;" : " ";
+			},
+
+			// Extra can be a number, shortcut for increasing-calling-decreasing
+			indent: function( extra ) {
+				if ( !this.multiline ) {
+					return "";
+				}
+				var chr = this.indentChar;
+				if ( this.HTML ) {
+					chr = chr.replace( /\t/g, "   " ).replace( / /g, "&#160;" );
+				}
+				return new Array( this.depth + ( extra || 0 ) ).join( chr );
+			},
+			up: function( a ) {
+				this.depth += a || 1;
+			},
+			down: function( a ) {
+				this.depth -= a || 1;
+			},
+			setParser: function( name, parser ) {
+				this.parsers[ name ] = parser;
+			},
+
+			// The next 3 are exposed so you can use them
+			quote: quote,
+			literal: literal,
+			join: join,
+			depth: 1,
+			maxDepth: QUnit.config.maxDepth,
+
+			// This is the list of parsers, to modify them, use dump.setParser
+			parsers: {
+				window: "[Window]",
+				document: "[Document]",
+				error: function( error ) {
+					return "Error(\"" + error.message + "\")";
+				},
+				unknown: "[Unknown]",
+				"null": "null",
+				"undefined": "undefined",
+				"function": function( fn ) {
+					var ret = "function",
+
+						// Functions never have name in IE
+						name = "name" in fn ? fn.name : ( reName.exec( fn ) || [] )[ 1 ];
+
+					if ( name ) {
+						ret += " " + name;
+					}
+					ret += "(";
+
+					ret = [ ret, dump.parse( fn, "functionArgs" ), "){" ].join( "" );
+					return join( ret, dump.parse( fn, "functionCode" ), "}" );
+				},
+				array: array,
+				nodelist: array,
+				"arguments": array,
+				object: function( map, stack ) {
+					var keys, key, val, i, nonEnumerableProperties,
+						ret = [];
+
+					if ( dump.maxDepth && dump.depth > dump.maxDepth ) {
+						return "[object Object]";
+					}
+
+					dump.up();
+					keys = [];
+					for ( key in map ) {
+						keys.push( key );
+					}
+
+					// Some properties are not always enumerable on Error objects.
+					nonEnumerableProperties = [ "message", "name" ];
+					for ( i in nonEnumerableProperties ) {
+						key = nonEnumerableProperties[ i ];
+						if ( key in map && inArray( key, keys ) < 0 ) {
+							keys.push( key );
+						}
+					}
+					keys.sort();
+					for ( i = 0; i < keys.length; i++ ) {
+						key = keys[ i ];
+						val = map[ key ];
+						ret.push( dump.parse( key, "key" ) + ": " +
+							dump.parse( val, undefined, stack ) );
+					}
+					dump.down();
+					return join( "{", ret, "}" );
+				},
+				node: function( node ) {
+					var len, i, val,
+						open = dump.HTML ? "&lt;" : "<",
+						close = dump.HTML ? "&gt;" : ">",
+						tag = node.nodeName.toLowerCase(),
+						ret = open + tag,
+						attrs = node.attributes;
+
+					if ( attrs ) {
+						for ( i = 0, len = attrs.length; i < len; i++ ) {
+							val = attrs[ i ].nodeValue;
+
+							// IE6 includes all attributes in .attributes, even ones not explicitly
+							// set. Those have values like undefined, null, 0, false, "" or
+							// "inherit".
+							if ( val && val !== "inherit" ) {
+								ret += " " + attrs[ i ].nodeName + "=" +
+									dump.parse( val, "attribute" );
+							}
+						}
+					}
+					ret += close;
+
+					// Show content of TextNode or CDATASection
+					if ( node.nodeType === 3 || node.nodeType === 4 ) {
+						ret += node.nodeValue;
+					}
+
+					return ret + open + "/" + tag + close;
+				},
+
+				// Function calls it internally, it's the arguments part of the function
+				functionArgs: function( fn ) {
+					var args,
+						l = fn.length;
+
+					if ( !l ) {
+						return "";
+					}
+
+					args = new Array( l );
+					while ( l-- ) {
+
+						// 97 is 'a'
+						args[ l ] = String.fromCharCode( 97 + l );
+					}
+					return " " + args.join( ", " ) + " ";
+				},
+
+				// Object calls it internally, the key part of an item in a map
+				key: quote,
+
+				// Function calls it internally, it's the content of the function
+				functionCode: "[code]",
+
+				// Node calls it internally, it's a html attribute value
+				attribute: quote,
+				string: quote,
+				date: quote,
+				regexp: literal,
+				number: literal,
+				"boolean": literal
+			},
+
+			// If true, entities are escaped ( <, >, \t, space and \n )
+			HTML: false,
+
+			// Indentation unit
+			indentChar: "  ",
+
+			// If true, items in a collection, are separated by a \n, else just a space.
+			multiline: true
+		};
+
+	return dump;
+}() );
+
+// Back compat
+QUnit.jsDump = QUnit.dump;
+
+// Deprecated
+// Extend assert methods to QUnit for Backwards compatibility
+( function() {
+	var i,
+		assertions = Assert.prototype;
+
+	function applyCurrent( current ) {
+		return function() {
+			var assert = new Assert( QUnit.config.current );
+			current.apply( assert, arguments );
+		};
+	}
+
+	for ( i in assertions ) {
+		QUnit[ i ] = applyCurrent( assertions[ i ] );
+	}
+}() );
+
+// For browser, export only select globals
+if ( defined.document ) {
+
+	( function() {
+		var i, l,
+			keys = [
+				"test",
+				"module",
+				"expect",
+				"asyncTest",
+				"start",
+				"stop",
+				"ok",
+				"notOk",
+				"equal",
+				"notEqual",
+				"propEqual",
+				"notPropEqual",
+				"deepEqual",
+				"notDeepEqual",
+				"strictEqual",
+				"notStrictEqual",
+				"throws",
+				"raises"
+			];
+
+		for ( i = 0, l = keys.length; i < l; i++ ) {
+			window[ keys[ i ] ] = QUnit[ keys[ i ] ];
+		}
+	}() );
+
+	window.QUnit = QUnit;
+}
+
+// For nodejs
+if ( typeof module !== "undefined" && module && module.exports ) {
+	module.exports = QUnit;
+
+	// For consistency with CommonJS environments' exports
+	module.exports.QUnit = QUnit;
+}
+
+// For CommonJS with exports, but without module.exports, like Rhino
+if ( typeof exports !== "undefined" && exports ) {
+	exports.QUnit = QUnit;
+}
+
+if ( typeof define === "function" && define.amd ) {
+	define( function() {
+		return QUnit;
+	} );
+	QUnit.config.autostart = false;
+}
+
+// Get a reference to the global object, like window in browsers
+}( ( function() {
+	return this;
+}() ) ) );
+
+( function() {
+
+// Only interact with URLs via window.location
+var location = typeof window !== "undefined" && window.location;
+if ( !location ) {
+	return;
+}
+
+var urlParams = getUrlParams();
+
+QUnit.urlParams = urlParams;
+
+// Match module/test by inclusion in an array
+QUnit.config.moduleId = [].concat( urlParams.moduleId || [] );
+QUnit.config.testId = [].concat( urlParams.testId || [] );
+
+// Exact case-insensitive match of the module name
+QUnit.config.module = urlParams.module;
+
+// Regular expression or case-insenstive substring match against "moduleName: testName"
+QUnit.config.filter = urlParams.filter;
+
+// Test order randomization
+if ( urlParams.seed === true ) {
+
+	// Generate a random seed if the option is specified without a value
+	QUnit.config.seed = Math.random().toString( 36 ).slice( 2 );
+} else if ( urlParams.seed ) {
+	QUnit.config.seed = urlParams.seed;
+}
+
+// Add URL-parameter-mapped config values with UI form rendering data
+QUnit.config.urlConfig.push(
+	{
+		id: "hidepassed",
+		label: "Hide passed tests",
+		tooltip: "Only show tests and assertions that fail. Stored as query-strings."
+	},
+	{
+		id: "noglobals",
+		label: "Check for Globals",
+		tooltip: "Enabling this will test if any test introduces new properties on the " +
+			"global object (`window` in Browsers). Stored as query-strings."
+	},
+	{
+		id: "notrycatch",
+		label: "No try-catch",
+		tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " +
+			"exceptions in IE reasonable. Stored as query-strings."
+	}
+);
+
+QUnit.begin( function() {
+	var i, option,
+		urlConfig = QUnit.config.urlConfig;
+
+	for ( i = 0; i < urlConfig.length; i++ ) {
+
+		// Options can be either strings or objects with nonempty "id" properties
+		option = QUnit.config.urlConfig[ i ];
+		if ( typeof option !== "string" ) {
+			option = option.id;
+		}
+
+		if ( QUnit.config[ option ] === undefined ) {
+			QUnit.config[ option ] = urlParams[ option ];
+		}
+	}
+} );
+
+function getUrlParams() {
+	var i, param, name, value;
+	var urlParams = {};
+	var params = location.search.slice( 1 ).split( "&" );
+	var length = params.length;
+
+	for ( i = 0; i < length; i++ ) {
+		if ( params[ i ] ) {
+			param = params[ i ].split( "=" );
+			name = decodeURIComponent( param[ 0 ] );
+
+			// Allow just a key to turn on a flag, e.g., test.html?noglobals
+			value = param.length === 1 ||
+				decodeURIComponent( param.slice( 1 ).join( "=" ) ) ;
+			if ( urlParams[ name ] ) {
+				urlParams[ name ] = [].concat( urlParams[ name ], value );
+			} else {
+				urlParams[ name ] = value;
+			}
+		}
+	}
+
+	return urlParams;
+}
+
+// Don't load the HTML Reporter on non-browser environments
+if ( typeof window === "undefined" || !window.document ) {
+	return;
+}
+
+// Deprecated QUnit.init - Ref #530
+// Re-initialize the configuration options
+QUnit.init = function() {
+	var config = QUnit.config;
+
+	config.stats = { all: 0, bad: 0 };
+	config.moduleStats = { all: 0, bad: 0 };
+	config.started = 0;
+	config.updateRate = 1000;
+	config.blocking = false;
+	config.autostart = true;
+	config.autorun = false;
+	config.filter = "";
+	config.queue = [];
+
+	appendInterface();
+};
+
+var config = QUnit.config,
+	document = window.document,
+	collapseNext = false,
+	hasOwn = Object.prototype.hasOwnProperty,
+	unfilteredUrl = setUrl( { filter: undefined, module: undefined,
+		moduleId: undefined, testId: undefined } ),
+	defined = {
+		sessionStorage: ( function() {
+			var x = "qunit-test-string";
+			try {
+				sessionStorage.setItem( x, x );
+				sessionStorage.removeItem( x );
+				return true;
+			} catch ( e ) {
+				return false;
+			}
+		}() )
+	},
+	modulesList = [];
+
+/**
+* Escape text for attribute or text content.
+*/
+function escapeText( s ) {
+	if ( !s ) {
+		return "";
+	}
+	s = s + "";
+
+	// Both single quotes and double quotes (for attributes)
+	return s.replace( /['"<>&]/g, function( s ) {
+		switch ( s ) {
+		case "'":
+			return "&#039;";
+		case "\"":
+			return "&quot;";
+		case "<":
+			return "&lt;";
+		case ">":
+			return "&gt;";
+		case "&":
+			return "&amp;";
+		}
+	} );
+}
+
+/**
+ * @param {HTMLElement} elem
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvent( elem, type, fn ) {
+	if ( elem.addEventListener ) {
+
+		// Standards-based browsers
+		elem.addEventListener( type, fn, false );
+	} else if ( elem.attachEvent ) {
+
+		// Support: IE <9
+		elem.attachEvent( "on" + type, function() {
+			var event = window.event;
+			if ( !event.target ) {
+				event.target = event.srcElement || document;
+			}
+
+			fn.call( elem, event );
+		} );
+	}
+}
+
+/**
+ * @param {Array|NodeList} elems
+ * @param {string} type
+ * @param {Function} fn
+ */
+function addEvents( elems, type, fn ) {
+	var i = elems.length;
+	while ( i-- ) {
+		addEvent( elems[ i ], type, fn );
+	}
+}
+
+function hasClass( elem, name ) {
+	return ( " " + elem.className + " " ).indexOf( " " + name + " " ) >= 0;
+}
+
+function addClass( elem, name ) {
+	if ( !hasClass( elem, name ) ) {
+		elem.className += ( elem.className ? " " : "" ) + name;
+	}
+}
+
+function toggleClass( elem, name, force ) {
+	if ( force || typeof force === "undefined" && !hasClass( elem, name ) ) {
+		addClass( elem, name );
+	} else {
+		removeClass( elem, name );
+	}
+}
+
+function removeClass( elem, name ) {
+	var set = " " + elem.className + " ";
+
+	// Class name may appear multiple times
+	while ( set.indexOf( " " + name + " " ) >= 0 ) {
+		set = set.replace( " " + name + " ", " " );
+	}
+
+	// Trim for prettiness
+	elem.className = typeof set.trim === "function" ? set.trim() : set.replace( /^\s+|\s+$/g, "" );
+}
+
+function id( name ) {
+	return document.getElementById && document.getElementById( name );
+}
+
+function getUrlConfigHtml() {
+	var i, j, val,
+		escaped, escapedTooltip,
+		selection = false,
+		urlConfig = config.urlConfig,
+		urlConfigHtml = "";
+
+	for ( i = 0; i < urlConfig.length; i++ ) {
+
+		// Options can be either strings or objects with nonempty "id" properties
+		val = config.urlConfig[ i ];
+		if ( typeof val === "string" ) {
+			val = {
+				id: val,
+				label: val
+			};
+		}
+
+		escaped = escapeText( val.id );
+		escapedTooltip = escapeText( val.tooltip );
+
+		if ( !val.value || typeof val.value === "string" ) {
+			urlConfigHtml += "<input id='qunit-urlconfig-" + escaped +
+				"' name='" + escaped + "' type='checkbox'" +
+				( val.value ? " value='" + escapeText( val.value ) + "'" : "" ) +
+				( config[ val.id ] ? " checked='checked'" : "" ) +
+				" title='" + escapedTooltip + "' /><label for='qunit-urlconfig-" + escaped +
+				"' title='" + escapedTooltip + "'>" + val.label + "</label>";
+		} else {
+			urlConfigHtml += "<label for='qunit-urlconfig-" + escaped +
+				"' title='" + escapedTooltip + "'>" + val.label +
+				": </label><select id='qunit-urlconfig-" + escaped +
+				"' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
+
+			if ( QUnit.is( "array", val.value ) ) {
+				for ( j = 0; j < val.value.length; j++ ) {
+					escaped = escapeText( val.value[ j ] );
+					urlConfigHtml += "<option value='" + escaped + "'" +
+						( config[ val.id ] === val.value[ j ] ?
+							( selection = true ) && " selected='selected'" : "" ) +
+						">" + escaped + "</option>";
+				}
+			} else {
+				for ( j in val.value ) {
+					if ( hasOwn.call( val.value, j ) ) {
+						urlConfigHtml += "<option value='" + escapeText( j ) + "'" +
+							( config[ val.id ] === j ?
+								( selection = true ) && " selected='selected'" : "" ) +
+							">" + escapeText( val.value[ j ] ) + "</option>";
+					}
+				}
+			}
+			if ( config[ val.id ] && !selection ) {
+				escaped = escapeText( config[ val.id ] );
+				urlConfigHtml += "<option value='" + escaped +
+					"' selected='selected' disabled='disabled'>" + escaped + "</option>";
+			}
+			urlConfigHtml += "</select>";
+		}
+	}
+
+	return urlConfigHtml;
+}
+
+// Handle "click" events on toolbar checkboxes and "change" for select menus.
+// Updates the URL with the new state of `config.urlConfig` values.
+function toolbarChanged() {
+	var updatedUrl, value, tests,
+		field = this,
+		params = {};
+
+	// Detect if field is a select menu or a checkbox
+	if ( "selectedIndex" in field ) {
+		value = field.options[ field.selectedIndex ].value || undefined;
+	} else {
+		value = field.checked ? ( field.defaultValue || true ) : undefined;
+	}
+
+	params[ field.name ] = value;
+	updatedUrl = setUrl( params );
+
+	// Check if we can apply the change without a page refresh
+	if ( "hidepassed" === field.name && "replaceState" in window.history ) {
+		QUnit.urlParams[ field.name ] = value;
+		config[ field.name ] = value || false;
+		tests = id( "qunit-tests" );
+		if ( tests ) {
+			toggleClass( tests, "hidepass", value || false );
+		}
+		window.history.replaceState( null, "", updatedUrl );
+	} else {
+		window.location = updatedUrl;
+	}
+}
+
+function setUrl( params ) {
+	var key, arrValue, i,
+		querystring = "?",
+		location = window.location;
+
+	params = QUnit.extend( QUnit.extend( {}, QUnit.urlParams ), params );
+
+	for ( key in params ) {
+
+		// Skip inherited or undefined properties
+		if ( hasOwn.call( params, key ) && params[ key ] !== undefined ) {
+
+			// Output a parameter for each value of this key (but usually just one)
+			arrValue = [].concat( params[ key ] );
+			for ( i = 0; i < arrValue.length; i++ ) {
+				querystring += encodeURIComponent( key );
+				if ( arrValue[ i ] !== true ) {
+					querystring += "=" + encodeURIComponent( arrValue[ i ] );
+				}
+				querystring += "&";
+			}
+		}
+	}
+	return location.protocol + "//" + location.host +
+		location.pathname + querystring.slice( 0, -1 );
+}
+
+function applyUrlParams() {
+	var selectedModule,
+		modulesList = id( "qunit-modulefilter" ),
+		filter = id( "qunit-filter-input" ).value;
+
+	selectedModule = modulesList ?
+		decodeURIComponent( modulesList.options[ modulesList.selectedIndex ].value ) :
+		undefined;
+
+	window.location = setUrl( {
+		module: ( selectedModule === "" ) ? undefined : selectedModule,
+		filter: ( filter === "" ) ? undefined : filter,
+
+		// Remove moduleId and testId filters
+		moduleId: undefined,
+		testId: undefined
+	} );
+}
+
+function toolbarUrlConfigContainer() {
+	var urlConfigContainer = document.createElement( "span" );
+
+	urlConfigContainer.innerHTML = getUrlConfigHtml();
+	addClass( urlConfigContainer, "qunit-url-config" );
+
+	// For oldIE support:
+	// * Add handlers to the individual elements instead of the container
+	// * Use "click" instead of "change" for checkboxes
+	addEvents( urlConfigContainer.getElementsByTagName( "input" ), "click", toolbarChanged );
+	addEvents( urlConfigContainer.getElementsByTagName( "select" ), "change", toolbarChanged );
+
+	return urlConfigContainer;
+}
+
+function toolbarLooseFilter() {
+	var filter = document.createElement( "form" ),
+		label = document.createElement( "label" ),
+		input = document.createElement( "input" ),
+		button = document.createElement( "button" );
+
+	addClass( filter, "qunit-filter" );
+
+	label.innerHTML = "Filter: ";
+
+	input.type = "text";
+	input.value = config.filter || "";
+	input.name = "filter";
+	input.id = "qunit-filter-input";
+
+	button.innerHTML = "Go";
+
+	label.appendChild( input );
+
+	filter.appendChild( label );
+	filter.appendChild( button );
+	addEvent( filter, "submit", function( ev ) {
+		applyUrlParams();
+
+		if ( ev && ev.preventDefault ) {
+			ev.preventDefault();
+		}
+
+		return false;
+	} );
+
+	return filter;
+}
+
+function toolbarModuleFilterHtml() {
+	var i,
+		moduleFilterHtml = "";
+
+	if ( !modulesList.length ) {
+		return false;
+	}
+
+	moduleFilterHtml += "<label for='qunit-modulefilter'>Module: </label>" +
+		"<select id='qunit-modulefilter' name='modulefilter'><option value='' " +
+		( QUnit.urlParams.module === undefined ? "selected='selected'" : "" ) +
+		">< All Modules ></option>";
+
+	for ( i = 0; i < modulesList.length; i++ ) {
+		moduleFilterHtml += "<option value='" +
+			escapeText( encodeURIComponent( modulesList[ i ] ) ) + "' " +
+			( QUnit.urlParams.module === modulesList[ i ] ? "selected='selected'" : "" ) +
+			">" + escapeText( modulesList[ i ] ) + "</option>";
+	}
+	moduleFilterHtml += "</select>";
+
+	return moduleFilterHtml;
+}
+
+function toolbarModuleFilter() {
+	var toolbar = id( "qunit-testrunner-toolbar" ),
+		moduleFilter = document.createElement( "span" ),
+		moduleFilterHtml = toolbarModuleFilterHtml();
+
+	if ( !toolbar || !moduleFilterHtml ) {
+		return false;
+	}
+
+	moduleFilter.setAttribute( "id", "qunit-modulefilter-container" );
+	moduleFilter.innerHTML = moduleFilterHtml;
+
+	addEvent( moduleFilter.lastChild, "change", applyUrlParams );
+
+	toolbar.appendChild( moduleFilter );
+}
+
+function appendToolbar() {
+	var toolbar = id( "qunit-testrunner-toolbar" );
+
+	if ( toolbar ) {
+		toolbar.appendChild( toolbarUrlConfigContainer() );
+		toolbar.appendChild( toolbarLooseFilter() );
+		toolbarModuleFilter();
+	}
+}
+
+function appendHeader() {
+	var header = id( "qunit-header" );
+
+	if ( header ) {
+		header.innerHTML = "<a href='" + escapeText( unfilteredUrl ) + "'>" + header.innerHTML +
+			"</a> ";
+	}
+}
+
+function appendBanner() {
+	var banner = id( "qunit-banner" );
+
+	if ( banner ) {
+		banner.className = "";
+	}
+}
+
+function appendTestResults() {
+	var tests = id( "qunit-tests" ),
+		result = id( "qunit-testresult" );
+
+	if ( result ) {
+		result.parentNode.removeChild( result );
+	}
+
+	if ( tests ) {
+		tests.innerHTML = "";
+		result = document.createElement( "p" );
+		result.id = "qunit-testresult";
+		result.className = "result";
+		tests.parentNode.insertBefore( result, tests );
+		result.innerHTML = "Running...<br />&#160;";
+	}
+}
+
+function storeFixture() {
+	var fixture = id( "qunit-fixture" );
+	if ( fixture ) {
+		config.fixture = fixture.innerHTML;
+	}
+}
+
+function appendFilteredTest() {
+	var testId = QUnit.config.testId;
+	if ( !testId || testId.length <= 0 ) {
+		return "";
+	}
+	return "<div id='qunit-filteredTest'>Rerunning selected tests: " +
+		escapeText( testId.join( ", " ) ) +
+		" <a id='qunit-clearFilter' href='" +
+		escapeText( unfilteredUrl ) +
+		"'>Run all tests</a></div>";
+}
+
+function appendUserAgent() {
+	var userAgent = id( "qunit-userAgent" );
+
+	if ( userAgent ) {
+		userAgent.innerHTML = "";
+		userAgent.appendChild(
+			document.createTextNode(
+				"QUnit " + QUnit.version + "; " + navigator.userAgent
+			)
+		);
+	}
+}
+
+function appendInterface() {
+	var qunit = id( "qunit" );
+
+	if ( qunit ) {
+		qunit.innerHTML =
+			"<h1 id='qunit-header'>" + escapeText( document.title ) + "</h1>" +
+			"<h2 id='qunit-banner'></h2>" +
+			"<div id='qunit-testrunner-toolbar'></div>" +
+			appendFilteredTest() +
+			"<h2 id='qunit-userAgent'></h2>" +
+			"<ol id='qunit-tests'></ol>";
+	}
+
+	appendHeader();
+	appendBanner();
+	appendTestResults();
+	appendUserAgent();
+	appendToolbar();
+}
+
+function appendTestsList( modules ) {
+	var i, l, x, z, test, moduleObj;
+
+	for ( i = 0, l = modules.length; i < l; i++ ) {
+		moduleObj = modules[ i ];
+
+		for ( x = 0, z = moduleObj.tests.length; x < z; x++ ) {
+			test = moduleObj.tests[ x ];
+
+			appendTest( test.name, test.testId, moduleObj.name );
+		}
+	}
+}
+
+function appendTest( name, testId, moduleName ) {
+	var title, rerunTrigger, testBlock, assertList,
+		tests = id( "qunit-tests" );
+
+	if ( !tests ) {
+		return;
+	}
+
+	title = document.createElement( "strong" );
+	title.innerHTML = getNameHtml( name, moduleName );
+
+	rerunTrigger = document.createElement( "a" );
+	rerunTrigger.innerHTML = "Rerun";
+	rerunTrigger.href = setUrl( { testId: testId } );
+
+	testBlock = document.createElement( "li" );
+	testBlock.appendChild( title );
+	testBlock.appendChild( rerunTrigger );
+	testBlock.id = "qunit-test-output-" + testId;
+
+	assertList = document.createElement( "ol" );
+	assertList.className = "qunit-assert-list";
+
+	testBlock.appendChild( assertList );
+
+	tests.appendChild( testBlock );
+}
+
+// HTML Reporter initialization and load
+QUnit.begin( function( details ) {
+	var i, moduleObj, tests;
+
+	// Sort modules by name for the picker
+	for ( i = 0; i < details.modules.length; i++ ) {
+		moduleObj = details.modules[ i ];
+		if ( moduleObj.name ) {
+			modulesList.push( moduleObj.name );
+		}
+	}
+	modulesList.sort( function( a, b ) {
+		return a.localeCompare( b );
+	} );
+
+	// Capture fixture HTML from the page
+	storeFixture();
+
+	// Initialize QUnit elements
+	appendInterface();
+	appendTestsList( details.modules );
+	tests = id( "qunit-tests" );
+	if ( tests && config.hidepassed ) {
+		addClass( tests, "hidepass" );
+	}
+} );
+
+QUnit.done( function( details ) {
+	var i, key,
+		banner = id( "qunit-banner" ),
+		tests = id( "qunit-tests" ),
+		html = [
+			"Tests completed in ",
+			details.runtime,
+			" milliseconds.<br />",
+			"<span class='passed'>",
+			details.passed,
+			"</span> assertions of <span class='total'>",
+			details.total,
+			"</span> passed, <span class='failed'>",
+			details.failed,
+			"</span> failed."
+		].join( "" );
+
+	if ( banner ) {
+		banner.className = details.failed ? "qunit-fail" : "qunit-pass";
+	}
+
+	if ( tests ) {
+		id( "qunit-testresult" ).innerHTML = html;
+	}
+
+	if ( config.altertitle && document.title ) {
+
+		// Show ✖ for good, ✔ for bad suite result in title
+		// use escape sequences in case file gets loaded with non-utf-8-charset
+		document.title = [
+			( details.failed ? "\u2716" : "\u2714" ),
+			document.title.replace( /^[\u2714\u2716] /i, "" )
+		].join( " " );
+	}
+
+	// Clear own sessionStorage items if all tests passed
+	if ( config.reorder && defined.sessionStorage && details.failed === 0 ) {
+		for ( i = 0; i < sessionStorage.length; i++ ) {
+			key = sessionStorage.key( i++ );
+			if ( key.indexOf( "qunit-test-" ) === 0 ) {
+				sessionStorage.removeItem( key );
+			}
+		}
+	}
+
+	// Scroll back to top to show results
+	if ( config.scrolltop && window.scrollTo ) {
+		window.scrollTo( 0, 0 );
+	}
+} );
+
+function getNameHtml( name, module ) {
+	var nameHtml = "";
+
+	if ( module ) {
+		nameHtml = "<span class='module-name'>" + escapeText( module ) + "</span>: ";
+	}
+
+	nameHtml += "<span class='test-name'>" + escapeText( name ) + "</span>";
+
+	return nameHtml;
+}
+
+QUnit.testStart( function( details ) {
+	var running, testBlock, bad;
+
+	testBlock = id( "qunit-test-output-" + details.testId );
+	if ( testBlock ) {
+		testBlock.className = "running";
+	} else {
+
+		// Report later registered tests
+		appendTest( details.name, details.testId, details.module );
+	}
+
+	running = id( "qunit-testresult" );
+	if ( running ) {
+		bad = QUnit.config.reorder && defined.sessionStorage &&
+			+sessionStorage.getItem( "qunit-test-" + details.module + "-" + details.name );
+
+		running.innerHTML = ( bad ?
+			"Rerunning previously failed test: <br />" :
+			"Running: <br />" ) +
+			getNameHtml( details.name, details.module );
+	}
+
+} );
+
+function stripHtml( string ) {
+
+	// Strip tags, html entity and whitespaces
+	return string.replace( /<\/?[^>]+(>|$)/g, "" ).replace( /\&quot;/g, "" ).replace( /\s+/g, "" );
+}
+
+QUnit.log( function( details ) {
+	var assertList, assertLi,
+		message, expected, actual, diff,
+		showDiff = false,
+		testItem = id( "qunit-test-output-" + details.testId );
+
+	if ( !testItem ) {
+		return;
+	}
+
+	message = escapeText( details.message ) || ( details.result ? "okay" : "failed" );
+	message = "<span class='test-message'>" + message + "</span>";
+	message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
+
+	// The pushFailure doesn't provide details.expected
+	// when it calls, it's implicit to also not show expected and diff stuff
+	// Also, we need to check details.expected existence, as it can exist and be undefined
+	if ( !details.result && hasOwn.call( details, "expected" ) ) {
+		if ( details.negative ) {
+			expected = "NOT " + QUnit.dump.parse( details.expected );
+		} else {
+			expected = QUnit.dump.parse( details.expected );
+		}
+
+		actual = QUnit.dump.parse( details.actual );
+		message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" +
+			escapeText( expected ) +
+			"</pre></td></tr>";
+
+		if ( actual !== expected ) {
+
+			message += "<tr class='test-actual'><th>Result: </th><td><pre>" +
+				escapeText( actual ) + "</pre></td></tr>";
+
+			// Don't show diff if actual or expected are booleans
+			if ( !( /^(true|false)$/.test( actual ) ) &&
+					!( /^(true|false)$/.test( expected ) ) ) {
+				diff = QUnit.diff( expected, actual );
+				showDiff = stripHtml( diff ).length !==
+					stripHtml( expected ).length +
+					stripHtml( actual ).length;
+			}
+
+			// Don't show diff if expected and actual are totally different
+			if ( showDiff ) {
+				message += "<tr class='test-diff'><th>Diff: </th><td><pre>" +
+					diff + "</pre></td></tr>";
+			}
+		} else if ( expected.indexOf( "[object Array]" ) !== -1 ||
+				expected.indexOf( "[object Object]" ) !== -1 ) {
+			message += "<tr class='test-message'><th>Message: </th><td>" +
+				"Diff suppressed as the depth of object is more than current max depth (" +
+				QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " +
+				" run with a higher max depth or <a href='" +
+				escapeText( setUrl( { maxDepth: -1 } ) ) + "'>" +
+				"Rerun</a> without max depth.</p></td></tr>";
+		} else {
+			message += "<tr class='test-message'><th>Message: </th><td>" +
+				"Diff suppressed as the expected and actual results have an equivalent" +
+				" serialization</td></tr>";
+		}
+
+		if ( details.source ) {
+			message += "<tr class='test-source'><th>Source: </th><td><pre>" +
+				escapeText( details.source ) + "</pre></td></tr>";
+		}
+
+		message += "</table>";
+
+	// This occurs when pushFailure is set and we have an extracted stack trace
+	} else if ( !details.result && details.source ) {
+		message += "<table>" +
+			"<tr class='test-source'><th>Source: </th><td><pre>" +
+			escapeText( details.source ) + "</pre></td></tr>" +
+			"</table>";
+	}
+
+	assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+
+	assertLi = document.createElement( "li" );
+	assertLi.className = details.result ? "pass" : "fail";
+	assertLi.innerHTML = message;
+	assertList.appendChild( assertLi );
+} );
+
+QUnit.testDone( function( details ) {
+	var testTitle, time, testItem, assertList,
+		good, bad, testCounts, skipped, sourceName,
+		tests = id( "qunit-tests" );
+
+	if ( !tests ) {
+		return;
+	}
+
+	testItem = id( "qunit-test-output-" + details.testId );
+
+	assertList = testItem.getElementsByTagName( "ol" )[ 0 ];
+
+	good = details.passed;
+	bad = details.failed;
+
+	// Store result when possible
+	if ( config.reorder && defined.sessionStorage ) {
+		if ( bad ) {
+			sessionStorage.setItem( "qunit-test-" + details.module + "-" + details.name, bad );
+		} else {
+			sessionStorage.removeItem( "qunit-test-" + details.module + "-" + details.name );
+		}
+	}
+
+	if ( bad === 0 ) {
+
+		// Collapse the passing tests
+		addClass( assertList, "qunit-collapsed" );
+	} else if ( bad && config.collapse && !collapseNext ) {
+
+		// Skip collapsing the first failing test
+		collapseNext = true;
+	} else {
+
+		// Collapse remaining tests
+		addClass( assertList, "qunit-collapsed" );
+	}
+
+	// The testItem.firstChild is the test name
+	testTitle = testItem.firstChild;
+
+	testCounts = bad ?
+		"<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " :
+		"";
+
+	testTitle.innerHTML += " <b class='counts'>(" + testCounts +
+		details.assertions.length + ")</b>";
+
+	if ( details.skipped ) {
+		testItem.className = "skipped";
+		skipped = document.createElement( "em" );
+		skipped.className = "qunit-skipped-label";
+		skipped.innerHTML = "skipped";
+		testItem.insertBefore( skipped, testTitle );
+	} else {
+		addEvent( testTitle, "click", function() {
+			toggleClass( assertList, "qunit-collapsed" );
+		} );
+
+		testItem.className = bad ? "fail" : "pass";
+
+		time = document.createElement( "span" );
+		time.className = "runtime";
+		time.innerHTML = details.runtime + " ms";
+		testItem.insertBefore( time, assertList );
+	}
+
+	// Show the source of the test when showing assertions
+	if ( details.source ) {
+		sourceName = document.createElement( "p" );
+		sourceName.innerHTML = "<strong>Source: </strong>" + details.source;
+		addClass( sourceName, "qunit-source" );
+		if ( bad === 0 ) {
+			addClass( sourceName, "qunit-collapsed" );
+		}
+		addEvent( testTitle, "click", function() {
+			toggleClass( sourceName, "qunit-collapsed" );
+		} );
+		testItem.appendChild( sourceName );
+	}
+} );
+
+// Avoid readyState issue with phantomjs
+// Ref: #818
+var notPhantom = ( function( p ) {
+	return !( p && p.version && p.version.major > 0 );
+} )( window.phantom );
+
+if ( notPhantom && document.readyState === "complete" ) {
+	QUnit.load();
+} else {
+	addEvent( window, "load", QUnit.load );
+}
+
+/*
+ * This file is a modified version of google-diff-match-patch's JavaScript implementation
+ * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
+ * modifications are licensed as more fully set forth in LICENSE.txt.
+ *
+ * The original source of google-diff-match-patch is attributable and licensed as follows:
+ *
+ * Copyright 2006 Google Inc.
+ * https://code.google.com/p/google-diff-match-patch/
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * More Info:
+ *  https://code.google.com/p/google-diff-match-patch/
+ *
+ * Usage: QUnit.diff(expected, actual)
+ *
+ */
+QUnit.diff = ( function() {
+	function DiffMatchPatch() {
+	}
+
+	//  DIFF FUNCTIONS
+
+	/**
+	 * The data structure representing a diff is an array of tuples:
+	 * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
+	 * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
+	 */
+	var DIFF_DELETE = -1,
+		DIFF_INSERT = 1,
+		DIFF_EQUAL = 0;
+
+	/**
+	 * Find the differences between two texts.  Simplifies the problem by stripping
+	 * any common prefix or suffix off the texts before diffing.
+	 * @param {string} text1 Old string to be diffed.
+	 * @param {string} text2 New string to be diffed.
+	 * @param {boolean=} optChecklines Optional speedup flag. If present and false,
+	 *     then don't run a line-level diff first to identify the changed areas.
+	 *     Defaults to true, which does a faster, slightly less optimal diff.
+	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+	 */
+	DiffMatchPatch.prototype.DiffMain = function( text1, text2, optChecklines ) {
+		var deadline, checklines, commonlength,
+			commonprefix, commonsuffix, diffs;
+
+		// The diff must be complete in up to 1 second.
+		deadline = ( new Date() ).getTime() + 1000;
+
+		// Check for null inputs.
+		if ( text1 === null || text2 === null ) {
+			throw new Error( "Null input. (DiffMain)" );
+		}
+
+		// Check for equality (speedup).
+		if ( text1 === text2 ) {
+			if ( text1 ) {
+				return [
+					[ DIFF_EQUAL, text1 ]
+				];
+			}
+			return [];
+		}
+
+		if ( typeof optChecklines === "undefined" ) {
+			optChecklines = true;
+		}
+
+		checklines = optChecklines;
+
+		// Trim off common prefix (speedup).
+		commonlength = this.diffCommonPrefix( text1, text2 );
+		commonprefix = text1.substring( 0, commonlength );
+		text1 = text1.substring( commonlength );
+		text2 = text2.substring( commonlength );
+
+		// Trim off common suffix (speedup).
+		commonlength = this.diffCommonSuffix( text1, text2 );
+		commonsuffix = text1.substring( text1.length - commonlength );
+		text1 = text1.substring( 0, text1.length - commonlength );
+		text2 = text2.substring( 0, text2.length - commonlength );
+
+		// Compute the diff on the middle block.
+		diffs = this.diffCompute( text1, text2, checklines, deadline );
+
+		// Restore the prefix and suffix.
+		if ( commonprefix ) {
+			diffs.unshift( [ DIFF_EQUAL, commonprefix ] );
+		}
+		if ( commonsuffix ) {
+			diffs.push( [ DIFF_EQUAL, commonsuffix ] );
+		}
+		this.diffCleanupMerge( diffs );
+		return diffs;
+	};
+
+	/**
+	 * Reduce the number of edits by eliminating operationally trivial equalities.
+	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+	 */
+	DiffMatchPatch.prototype.diffCleanupEfficiency = function( diffs ) {
+		var changes, equalities, equalitiesLength, lastequality,
+			pointer, preIns, preDel, postIns, postDel;
+		changes = false;
+		equalities = []; // Stack of indices where equalities are found.
+		equalitiesLength = 0; // Keeping our own length var is faster in JS.
+		/** @type {?string} */
+		lastequality = null;
+
+		// Always equal to diffs[equalities[equalitiesLength - 1]][1]
+		pointer = 0; // Index of current position.
+
+		// Is there an insertion operation before the last equality.
+		preIns = false;
+
+		// Is there a deletion operation before the last equality.
+		preDel = false;
+
+		// Is there an insertion operation after the last equality.
+		postIns = false;
+
+		// Is there a deletion operation after the last equality.
+		postDel = false;
+		while ( pointer < diffs.length ) {
+
+			// Equality found.
+			if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) {
+				if ( diffs[ pointer ][ 1 ].length < 4 && ( postIns || postDel ) ) {
+
+					// Candidate found.
+					equalities[ equalitiesLength++ ] = pointer;
+					preIns = postIns;
+					preDel = postDel;
+					lastequality = diffs[ pointer ][ 1 ];
+				} else {
+
+					// Not a candidate, and can never become one.
+					equalitiesLength = 0;
+					lastequality = null;
+				}
+				postIns = postDel = false;
+
+			// An insertion or deletion.
+			} else {
+
+				if ( diffs[ pointer ][ 0 ] === DIFF_DELETE ) {
+					postDel = true;
+				} else {
+					postIns = true;
+				}
+
+				/*
+				 * Five types to be split:
+				 * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
+				 * <ins>A</ins>X<ins>C</ins><del>D</del>
+				 * <ins>A</ins><del>B</del>X<ins>C</ins>
+				 * <ins>A</del>X<ins>C</ins><del>D</del>
+				 * <ins>A</ins><del>B</del>X<del>C</del>
+				 */
+				if ( lastequality && ( ( preIns && preDel && postIns && postDel ) ||
+						( ( lastequality.length < 2 ) &&
+						( preIns + preDel + postIns + postDel ) === 3 ) ) ) {
+
+					// Duplicate record.
+					diffs.splice(
+						equalities[ equalitiesLength - 1 ],
+						0,
+						[ DIFF_DELETE, lastequality ]
+					);
+
+					// Change second copy to insert.
+					diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
+					equalitiesLength--; // Throw away the equality we just deleted;
+					lastequality = null;
+					if ( preIns && preDel ) {
+
+						// No changes made which could affect previous entry, keep going.
+						postIns = postDel = true;
+						equalitiesLength = 0;
+					} else {
+						equalitiesLength--; // Throw away the previous equality.
+						pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
+						postIns = postDel = false;
+					}
+					changes = true;
+				}
+			}
+			pointer++;
+		}
+
+		if ( changes ) {
+			this.diffCleanupMerge( diffs );
+		}
+	};
+
+	/**
+	 * Convert a diff array into a pretty HTML report.
+	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+	 * @param {integer} string to be beautified.
+	 * @return {string} HTML representation.
+	 */
+	DiffMatchPatch.prototype.diffPrettyHtml = function( diffs ) {
+		var op, data, x,
+			html = [];
+		for ( x = 0; x < diffs.length; x++ ) {
+			op = diffs[ x ][ 0 ]; // Operation (insert, delete, equal)
+			data = diffs[ x ][ 1 ]; // Text of change.
+			switch ( op ) {
+			case DIFF_INSERT:
+				html[ x ] = "<ins>" + escapeText( data ) + "</ins>";
+				break;
+			case DIFF_DELETE:
+				html[ x ] = "<del>" + escapeText( data ) + "</del>";
+				break;
+			case DIFF_EQUAL:
+				html[ x ] = "<span>" + escapeText( data ) + "</span>";
+				break;
+			}
+		}
+		return html.join( "" );
+	};
+
+	/**
+	 * Determine the common prefix of two strings.
+	 * @param {string} text1 First string.
+	 * @param {string} text2 Second string.
+	 * @return {number} The number of characters common to the start of each
+	 *     string.
+	 */
+	DiffMatchPatch.prototype.diffCommonPrefix = function( text1, text2 ) {
+		var pointermid, pointermax, pointermin, pointerstart;
+
+		// Quick check for common null cases.
+		if ( !text1 || !text2 || text1.charAt( 0 ) !== text2.charAt( 0 ) ) {
+			return 0;
+		}
+
+		// Binary search.
+		// Performance analysis: https://neil.fraser.name/news/2007/10/09/
+		pointermin = 0;
+		pointermax = Math.min( text1.length, text2.length );
+		pointermid = pointermax;
+		pointerstart = 0;
+		while ( pointermin < pointermid ) {
+			if ( text1.substring( pointerstart, pointermid ) ===
+					text2.substring( pointerstart, pointermid ) ) {
+				pointermin = pointermid;
+				pointerstart = pointermin;
+			} else {
+				pointermax = pointermid;
+			}
+			pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+		}
+		return pointermid;
+	};
+
+	/**
+	 * Determine the common suffix of two strings.
+	 * @param {string} text1 First string.
+	 * @param {string} text2 Second string.
+	 * @return {number} The number of characters common to the end of each string.
+	 */
+	DiffMatchPatch.prototype.diffCommonSuffix = function( text1, text2 ) {
+		var pointermid, pointermax, pointermin, pointerend;
+
+		// Quick check for common null cases.
+		if ( !text1 ||
+				!text2 ||
+				text1.charAt( text1.length - 1 ) !== text2.charAt( text2.length - 1 ) ) {
+			return 0;
+		}
+
+		// Binary search.
+		// Performance analysis: https://neil.fraser.name/news/2007/10/09/
+		pointermin = 0;
+		pointermax = Math.min( text1.length, text2.length );
+		pointermid = pointermax;
+		pointerend = 0;
+		while ( pointermin < pointermid ) {
+			if ( text1.substring( text1.length - pointermid, text1.length - pointerend ) ===
+					text2.substring( text2.length - pointermid, text2.length - pointerend ) ) {
+				pointermin = pointermid;
+				pointerend = pointermin;
+			} else {
+				pointermax = pointermid;
+			}
+			pointermid = Math.floor( ( pointermax - pointermin ) / 2 + pointermin );
+		}
+		return pointermid;
+	};
+
+	/**
+	 * Find the differences between two texts.  Assumes that the texts do not
+	 * have any common prefix or suffix.
+	 * @param {string} text1 Old string to be diffed.
+	 * @param {string} text2 New string to be diffed.
+	 * @param {boolean} checklines Speedup flag.  If false, then don't run a
+	 *     line-level diff first to identify the changed areas.
+	 *     If true, then run a faster, slightly less optimal diff.
+	 * @param {number} deadline Time when the diff should be complete by.
+	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffCompute = function( text1, text2, checklines, deadline ) {
+		var diffs, longtext, shorttext, i, hm,
+			text1A, text2A, text1B, text2B,
+			midCommon, diffsA, diffsB;
+
+		if ( !text1 ) {
+
+			// Just add some text (speedup).
+			return [
+				[ DIFF_INSERT, text2 ]
+			];
+		}
+
+		if ( !text2 ) {
+
+			// Just delete some text (speedup).
+			return [
+				[ DIFF_DELETE, text1 ]
+			];
+		}
+
+		longtext = text1.length > text2.length ? text1 : text2;
+		shorttext = text1.length > text2.length ? text2 : text1;
+		i = longtext.indexOf( shorttext );
+		if ( i !== -1 ) {
+
+			// Shorter text is inside the longer text (speedup).
+			diffs = [
+				[ DIFF_INSERT, longtext.substring( 0, i ) ],
+				[ DIFF_EQUAL, shorttext ],
+				[ DIFF_INSERT, longtext.substring( i + shorttext.length ) ]
+			];
+
+			// Swap insertions for deletions if diff is reversed.
+			if ( text1.length > text2.length ) {
+				diffs[ 0 ][ 0 ] = diffs[ 2 ][ 0 ] = DIFF_DELETE;
+			}
+			return diffs;
+		}
+
+		if ( shorttext.length === 1 ) {
+
+			// Single character string.
+			// After the previous speedup, the character can't be an equality.
+			return [
+				[ DIFF_DELETE, text1 ],
+				[ DIFF_INSERT, text2 ]
+			];
+		}
+
+		// Check to see if the problem can be split in two.
+		hm = this.diffHalfMatch( text1, text2 );
+		if ( hm ) {
+
+			// A half-match was found, sort out the return data.
+			text1A = hm[ 0 ];
+			text1B = hm[ 1 ];
+			text2A = hm[ 2 ];
+			text2B = hm[ 3 ];
+			midCommon = hm[ 4 ];
+
+			// Send both pairs off for separate processing.
+			diffsA = this.DiffMain( text1A, text2A, checklines, deadline );
+			diffsB = this.DiffMain( text1B, text2B, checklines, deadline );
+
+			// Merge the results.
+			return diffsA.concat( [
+				[ DIFF_EQUAL, midCommon ]
+			], diffsB );
+		}
+
+		if ( checklines && text1.length > 100 && text2.length > 100 ) {
+			return this.diffLineMode( text1, text2, deadline );
+		}
+
+		return this.diffBisect( text1, text2, deadline );
+	};
+
+	/**
+	 * Do the two texts share a substring which is at least half the length of the
+	 * longer text?
+	 * This speedup can produce non-minimal diffs.
+	 * @param {string} text1 First string.
+	 * @param {string} text2 Second string.
+	 * @return {Array.<string>} Five element Array, containing the prefix of
+	 *     text1, the suffix of text1, the prefix of text2, the suffix of
+	 *     text2 and the common middle.  Or null if there was no match.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffHalfMatch = function( text1, text2 ) {
+		var longtext, shorttext, dmp,
+			text1A, text2B, text2A, text1B, midCommon,
+			hm1, hm2, hm;
+
+		longtext = text1.length > text2.length ? text1 : text2;
+		shorttext = text1.length > text2.length ? text2 : text1;
+		if ( longtext.length < 4 || shorttext.length * 2 < longtext.length ) {
+			return null; // Pointless.
+		}
+		dmp = this; // 'this' becomes 'window' in a closure.
+
+		/**
+		 * Does a substring of shorttext exist within longtext such that the substring
+		 * is at least half the length of longtext?
+		 * Closure, but does not reference any external variables.
+		 * @param {string} longtext Longer string.
+		 * @param {string} shorttext Shorter string.
+		 * @param {number} i Start index of quarter length substring within longtext.
+		 * @return {Array.<string>} Five element Array, containing the prefix of
+		 *     longtext, the suffix of longtext, the prefix of shorttext, the suffix
+		 *     of shorttext and the common middle.  Or null if there was no match.
+		 * @private
+		 */
+		function diffHalfMatchI( longtext, shorttext, i ) {
+			var seed, j, bestCommon, prefixLength, suffixLength,
+				bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
+
+			// Start with a 1/4 length substring at position i as a seed.
+			seed = longtext.substring( i, i + Math.floor( longtext.length / 4 ) );
+			j = -1;
+			bestCommon = "";
+			while ( ( j = shorttext.indexOf( seed, j + 1 ) ) !== -1 ) {
+				prefixLength = dmp.diffCommonPrefix( longtext.substring( i ),
+					shorttext.substring( j ) );
+				suffixLength = dmp.diffCommonSuffix( longtext.substring( 0, i ),
+					shorttext.substring( 0, j ) );
+				if ( bestCommon.length < suffixLength + prefixLength ) {
+					bestCommon = shorttext.substring( j - suffixLength, j ) +
+						shorttext.substring( j, j + prefixLength );
+					bestLongtextA = longtext.substring( 0, i - suffixLength );
+					bestLongtextB = longtext.substring( i + prefixLength );
+					bestShorttextA = shorttext.substring( 0, j - suffixLength );
+					bestShorttextB = shorttext.substring( j + prefixLength );
+				}
+			}
+			if ( bestCommon.length * 2 >= longtext.length ) {
+				return [ bestLongtextA, bestLongtextB,
+					bestShorttextA, bestShorttextB, bestCommon
+				];
+			} else {
+				return null;
+			}
+		}
+
+		// First check if the second quarter is the seed for a half-match.
+		hm1 = diffHalfMatchI( longtext, shorttext,
+			Math.ceil( longtext.length / 4 ) );
+
+		// Check again based on the third quarter.
+		hm2 = diffHalfMatchI( longtext, shorttext,
+			Math.ceil( longtext.length / 2 ) );
+		if ( !hm1 && !hm2 ) {
+			return null;
+		} else if ( !hm2 ) {
+			hm = hm1;
+		} else if ( !hm1 ) {
+			hm = hm2;
+		} else {
+
+			// Both matched.  Select the longest.
+			hm = hm1[ 4 ].length > hm2[ 4 ].length ? hm1 : hm2;
+		}
+
+		// A half-match was found, sort out the return data.
+		text1A, text1B, text2A, text2B;
+		if ( text1.length > text2.length ) {
+			text1A = hm[ 0 ];
+			text1B = hm[ 1 ];
+			text2A = hm[ 2 ];
+			text2B = hm[ 3 ];
+		} else {
+			text2A = hm[ 0 ];
+			text2B = hm[ 1 ];
+			text1A = hm[ 2 ];
+			text1B = hm[ 3 ];
+		}
+		midCommon = hm[ 4 ];
+		return [ text1A, text1B, text2A, text2B, midCommon ];
+	};
+
+	/**
+	 * Do a quick line-level diff on both strings, then rediff the parts for
+	 * greater accuracy.
+	 * This speedup can produce non-minimal diffs.
+	 * @param {string} text1 Old string to be diffed.
+	 * @param {string} text2 New string to be diffed.
+	 * @param {number} deadline Time when the diff should be complete by.
+	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffLineMode = function( text1, text2, deadline ) {
+		var a, diffs, linearray, pointer, countInsert,
+			countDelete, textInsert, textDelete, j;
+
+		// Scan the text on a line-by-line basis first.
+		a = this.diffLinesToChars( text1, text2 );
+		text1 = a.chars1;
+		text2 = a.chars2;
+		linearray = a.lineArray;
+
+		diffs = this.DiffMain( text1, text2, false, deadline );
+
+		// Convert the diff back to original text.
+		this.diffCharsToLines( diffs, linearray );
+
+		// Eliminate freak matches (e.g. blank lines)
+		this.diffCleanupSemantic( diffs );
+
+		// Rediff any replacement blocks, this time character-by-character.
+		// Add a dummy entry at the end.
+		diffs.push( [ DIFF_EQUAL, "" ] );
+		pointer = 0;
+		countDelete = 0;
+		countInsert = 0;
+		textDelete = "";
+		textInsert = "";
+		while ( pointer < diffs.length ) {
+			switch ( diffs[ pointer ][ 0 ] ) {
+			case DIFF_INSERT:
+				countInsert++;
+				textInsert += diffs[ pointer ][ 1 ];
+				break;
+			case DIFF_DELETE:
+				countDelete++;
+				textDelete += diffs[ pointer ][ 1 ];
+				break;
+			case DIFF_EQUAL:
+
+				// Upon reaching an equality, check for prior redundancies.
+				if ( countDelete >= 1 && countInsert >= 1 ) {
+
+					// Delete the offending records and add the merged ones.
+					diffs.splice( pointer - countDelete - countInsert,
+						countDelete + countInsert );
+					pointer = pointer - countDelete - countInsert;
+					a = this.DiffMain( textDelete, textInsert, false, deadline );
+					for ( j = a.length - 1; j >= 0; j-- ) {
+						diffs.splice( pointer, 0, a[ j ] );
+					}
+					pointer = pointer + a.length;
+				}
+				countInsert = 0;
+				countDelete = 0;
+				textDelete = "";
+				textInsert = "";
+				break;
+			}
+			pointer++;
+		}
+		diffs.pop(); // Remove the dummy entry at the end.
+
+		return diffs;
+	};
+
+	/**
+	 * Find the 'middle snake' of a diff, split the problem in two
+	 * and return the recursively constructed diff.
+	 * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
+	 * @param {string} text1 Old string to be diffed.
+	 * @param {string} text2 New string to be diffed.
+	 * @param {number} deadline Time at which to bail if not yet complete.
+	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffBisect = function( text1, text2, deadline ) {
+		var text1Length, text2Length, maxD, vOffset, vLength,
+			v1, v2, x, delta, front, k1start, k1end, k2start,
+			k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
+
+		// Cache the text lengths to prevent multiple calls.
+		text1Length = text1.length;
+		text2Length = text2.length;
+		maxD = Math.ceil( ( text1Length + text2Length ) / 2 );
+		vOffset = maxD;
+		vLength = 2 * maxD;
+		v1 = new Array( vLength );
+		v2 = new Array( vLength );
+
+		// Setting all elements to -1 is faster in Chrome & Firefox than mixing
+		// integers and undefined.
+		for ( x = 0; x < vLength; x++ ) {
+			v1[ x ] = -1;
+			v2[ x ] = -1;
+		}
+		v1[ vOffset + 1 ] = 0;
+		v2[ vOffset + 1 ] = 0;
+		delta = text1Length - text2Length;
+
+		// If the total number of characters is odd, then the front path will collide
+		// with the reverse path.
+		front = ( delta % 2 !== 0 );
+
+		// Offsets for start and end of k loop.
+		// Prevents mapping of space beyond the grid.
+		k1start = 0;
+		k1end = 0;
+		k2start = 0;
+		k2end = 0;
+		for ( d = 0; d < maxD; d++ ) {
+
+			// Bail out if deadline is reached.
+			if ( ( new Date() ).getTime() > deadline ) {
+				break;
+			}
+
+			// Walk the front path one step.
+			for ( k1 = -d + k1start; k1 <= d - k1end; k1 += 2 ) {
+				k1Offset = vOffset + k1;
+				if ( k1 === -d || ( k1 !== d && v1[ k1Offset - 1 ] < v1[ k1Offset + 1 ] ) ) {
+					x1 = v1[ k1Offset + 1 ];
+				} else {
+					x1 = v1[ k1Offset - 1 ] + 1;
+				}
+				y1 = x1 - k1;
+				while ( x1 < text1Length && y1 < text2Length &&
+					text1.charAt( x1 ) === text2.charAt( y1 ) ) {
+					x1++;
+					y1++;
+				}
+				v1[ k1Offset ] = x1;
+				if ( x1 > text1Length ) {
+
+					// Ran off the right of the graph.
+					k1end += 2;
+				} else if ( y1 > text2Length ) {
+
+					// Ran off the bottom of the graph.
+					k1start += 2;
+				} else if ( front ) {
+					k2Offset = vOffset + delta - k1;
+					if ( k2Offset >= 0 && k2Offset < vLength && v2[ k2Offset ] !== -1 ) {
+
+						// Mirror x2 onto top-left coordinate system.
+						x2 = text1Length - v2[ k2Offset ];
+						if ( x1 >= x2 ) {
+
+							// Overlap detected.
+							return this.diffBisectSplit( text1, text2, x1, y1, deadline );
+						}
+					}
+				}
+			}
+
+			// Walk the reverse path one step.
+			for ( k2 = -d + k2start; k2 <= d - k2end; k2 += 2 ) {
+				k2Offset = vOffset + k2;
+				if ( k2 === -d || ( k2 !== d && v2[ k2Offset - 1 ] < v2[ k2Offset + 1 ] ) ) {
+					x2 = v2[ k2Offset + 1 ];
+				} else {
+					x2 = v2[ k2Offset - 1 ] + 1;
+				}
+				y2 = x2 - k2;
+				while ( x2 < text1Length && y2 < text2Length &&
+					text1.charAt( text1Length - x2 - 1 ) ===
+					text2.charAt( text2Length - y2 - 1 ) ) {
+					x2++;
+					y2++;
+				}
+				v2[ k2Offset ] = x2;
+				if ( x2 > text1Length ) {
+
+					// Ran off the left of the graph.
+					k2end += 2;
+				} else if ( y2 > text2Length ) {
+
+					// Ran off the top of the graph.
+					k2start += 2;
+				} else if ( !front ) {
+					k1Offset = vOffset + delta - k2;
+					if ( k1Offset >= 0 && k1Offset < vLength && v1[ k1Offset ] !== -1 ) {
+						x1 = v1[ k1Offset ];
+						y1 = vOffset + x1 - k1Offset;
+
+						// Mirror x2 onto top-left coordinate system.
+						x2 = text1Length - x2;
+						if ( x1 >= x2 ) {
+
+							// Overlap detected.
+							return this.diffBisectSplit( text1, text2, x1, y1, deadline );
+						}
+					}
+				}
+			}
+		}
+
+		// Diff took too long and hit the deadline or
+		// number of diffs equals number of characters, no commonality at all.
+		return [
+			[ DIFF_DELETE, text1 ],
+			[ DIFF_INSERT, text2 ]
+		];
+	};
+
+	/**
+	 * Given the location of the 'middle snake', split the diff in two parts
+	 * and recurse.
+	 * @param {string} text1 Old string to be diffed.
+	 * @param {string} text2 New string to be diffed.
+	 * @param {number} x Index of split point in text1.
+	 * @param {number} y Index of split point in text2.
+	 * @param {number} deadline Time at which to bail if not yet complete.
+	 * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffBisectSplit = function( text1, text2, x, y, deadline ) {
+		var text1a, text1b, text2a, text2b, diffs, diffsb;
+		text1a = text1.substring( 0, x );
+		text2a = text2.substring( 0, y );
+		text1b = text1.substring( x );
+		text2b = text2.substring( y );
+
+		// Compute both diffs serially.
+		diffs = this.DiffMain( text1a, text2a, false, deadline );
+		diffsb = this.DiffMain( text1b, text2b, false, deadline );
+
+		return diffs.concat( diffsb );
+	};
+
+	/**
+	 * Reduce the number of edits by eliminating semantically trivial equalities.
+	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+	 */
+	DiffMatchPatch.prototype.diffCleanupSemantic = function( diffs ) {
+		var changes, equalities, equalitiesLength, lastequality,
+			pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1,
+			lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
+		changes = false;
+		equalities = []; // Stack of indices where equalities are found.
+		equalitiesLength = 0; // Keeping our own length var is faster in JS.
+		/** @type {?string} */
+		lastequality = null;
+
+		// Always equal to diffs[equalities[equalitiesLength - 1]][1]
+		pointer = 0; // Index of current position.
+
+		// Number of characters that changed prior to the equality.
+		lengthInsertions1 = 0;
+		lengthDeletions1 = 0;
+
+		// Number of characters that changed after the equality.
+		lengthInsertions2 = 0;
+		lengthDeletions2 = 0;
+		while ( pointer < diffs.length ) {
+			if ( diffs[ pointer ][ 0 ] === DIFF_EQUAL ) { // Equality found.
+				equalities[ equalitiesLength++ ] = pointer;
+				lengthInsertions1 = lengthInsertions2;
+				lengthDeletions1 = lengthDeletions2;
+				lengthInsertions2 = 0;
+				lengthDeletions2 = 0;
+				lastequality = diffs[ pointer ][ 1 ];
+			} else { // An insertion or deletion.
+				if ( diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
+					lengthInsertions2 += diffs[ pointer ][ 1 ].length;
+				} else {
+					lengthDeletions2 += diffs[ pointer ][ 1 ].length;
+				}
+
+				// Eliminate an equality that is smaller or equal to the edits on both
+				// sides of it.
+				if ( lastequality && ( lastequality.length <=
+						Math.max( lengthInsertions1, lengthDeletions1 ) ) &&
+						( lastequality.length <= Math.max( lengthInsertions2,
+							lengthDeletions2 ) ) ) {
+
+					// Duplicate record.
+					diffs.splice(
+						equalities[ equalitiesLength - 1 ],
+						0,
+						[ DIFF_DELETE, lastequality ]
+					);
+
+					// Change second copy to insert.
+					diffs[ equalities[ equalitiesLength - 1 ] + 1 ][ 0 ] = DIFF_INSERT;
+
+					// Throw away the equality we just deleted.
+					equalitiesLength--;
+
+					// Throw away the previous equality (it needs to be reevaluated).
+					equalitiesLength--;
+					pointer = equalitiesLength > 0 ? equalities[ equalitiesLength - 1 ] : -1;
+
+					// Reset the counters.
+					lengthInsertions1 = 0;
+					lengthDeletions1 = 0;
+					lengthInsertions2 = 0;
+					lengthDeletions2 = 0;
+					lastequality = null;
+					changes = true;
+				}
+			}
+			pointer++;
+		}
+
+		// Normalize the diff.
+		if ( changes ) {
+			this.diffCleanupMerge( diffs );
+		}
+
+		// Find any overlaps between deletions and insertions.
+		// e.g: <del>abcxxx</del><ins>xxxdef</ins>
+		//   -> <del>abc</del>xxx<ins>def</ins>
+		// e.g: <del>xxxabc</del><ins>defxxx</ins>
+		//   -> <ins>def</ins>xxx<del>abc</del>
+		// Only extract an overlap if it is as big as the edit ahead or behind it.
+		pointer = 1;
+		while ( pointer < diffs.length ) {
+			if ( diffs[ pointer - 1 ][ 0 ] === DIFF_DELETE &&
+					diffs[ pointer ][ 0 ] === DIFF_INSERT ) {
+				deletion = diffs[ pointer - 1 ][ 1 ];
+				insertion = diffs[ pointer ][ 1 ];
+				overlapLength1 = this.diffCommonOverlap( deletion, insertion );
+				overlapLength2 = this.diffCommonOverlap( insertion, deletion );
+				if ( overlapLength1 >= overlapLength2 ) {
+					if ( overlapLength1 >= deletion.length / 2 ||
+							overlapLength1 >= insertion.length / 2 ) {
+
+						// Overlap found.  Insert an equality and trim the surrounding edits.
+						diffs.splice(
+							pointer,
+							0,
+							[ DIFF_EQUAL, insertion.substring( 0, overlapLength1 ) ]
+						);
+						diffs[ pointer - 1 ][ 1 ] =
+							deletion.substring( 0, deletion.length - overlapLength1 );
+						diffs[ pointer + 1 ][ 1 ] = insertion.substring( overlapLength1 );
+						pointer++;
+					}
+				} else {
+					if ( overlapLength2 >= deletion.length / 2 ||
+							overlapLength2 >= insertion.length / 2 ) {
+
+						// Reverse overlap found.
+						// Insert an equality and swap and trim the surrounding edits.
+						diffs.splice(
+							pointer,
+							0,
+							[ DIFF_EQUAL, deletion.substring( 0, overlapLength2 ) ]
+						);
+
+						diffs[ pointer - 1 ][ 0 ] = DIFF_INSERT;
+						diffs[ pointer - 1 ][ 1 ] =
+							insertion.substring( 0, insertion.length - overlapLength2 );
+						diffs[ pointer + 1 ][ 0 ] = DIFF_DELETE;
+						diffs[ pointer + 1 ][ 1 ] =
+							deletion.substring( overlapLength2 );
+						pointer++;
+					}
+				}
+				pointer++;
+			}
+			pointer++;
+		}
+	};
+
+	/**
+	 * Determine if the suffix of one string is the prefix of another.
+	 * @param {string} text1 First string.
+	 * @param {string} text2 Second string.
+	 * @return {number} The number of characters common to the end of the first
+	 *     string and the start of the second string.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffCommonOverlap = function( text1, text2 ) {
+		var text1Length, text2Length, textLength,
+			best, length, pattern, found;
+
+		// Cache the text lengths to prevent multiple calls.
+		text1Length = text1.length;
+		text2Length = text2.length;
+
+		// Eliminate the null case.
+		if ( text1Length === 0 || text2Length === 0 ) {
+			return 0;
+		}
+
+		// Truncate the longer string.
+		if ( text1Length > text2Length ) {
+			text1 = text1.substring( text1Length - text2Length );
+		} else if ( text1Length < text2Length ) {
+			text2 = text2.substring( 0, text1Length );
+		}
+		textLength = Math.min( text1Length, text2Length );
+
+		// Quick check for the worst case.
+		if ( text1 === text2 ) {
+			return textLength;
+		}
+
+		// Start by looking for a single character match
+		// and increase length until no match is found.
+		// Performance analysis: https://neil.fraser.name/news/2010/11/04/
+		best = 0;
+		length = 1;
+		while ( true ) {
+			pattern = text1.substring( textLength - length );
+			found = text2.indexOf( pattern );
+			if ( found === -1 ) {
+				return best;
+			}
+			length += found;
+			if ( found === 0 || text1.substring( textLength - length ) ===
+					text2.substring( 0, length ) ) {
+				best = length;
+				length++;
+			}
+		}
+	};
+
+	/**
+	 * Split two texts into an array of strings.  Reduce the texts to a string of
+	 * hashes where each Unicode character represents one line.
+	 * @param {string} text1 First string.
+	 * @param {string} text2 Second string.
+	 * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
+	 *     An object containing the encoded text1, the encoded text2 and
+	 *     the array of unique strings.
+	 *     The zeroth element of the array of unique strings is intentionally blank.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffLinesToChars = function( text1, text2 ) {
+		var lineArray, lineHash, chars1, chars2;
+		lineArray = []; // E.g. lineArray[4] === 'Hello\n'
+		lineHash = {};  // E.g. lineHash['Hello\n'] === 4
+
+		// '\x00' is a valid character, but various debuggers don't like it.
+		// So we'll insert a junk entry to avoid generating a null character.
+		lineArray[ 0 ] = "";
+
+		/**
+		 * Split a text into an array of strings.  Reduce the texts to a string of
+		 * hashes where each Unicode character represents one line.
+		 * Modifies linearray and linehash through being a closure.
+		 * @param {string} text String to encode.
+		 * @return {string} Encoded string.
+		 * @private
+		 */
+		function diffLinesToCharsMunge( text ) {
+			var chars, lineStart, lineEnd, lineArrayLength, line;
+			chars = "";
+
+			// Walk the text, pulling out a substring for each line.
+			// text.split('\n') would would temporarily double our memory footprint.
+			// Modifying text would create many large strings to garbage collect.
+			lineStart = 0;
+			lineEnd = -1;
+
+			// Keeping our own length variable is faster than looking it up.
+			lineArrayLength = lineArray.length;
+			while ( lineEnd < text.length - 1 ) {
+				lineEnd = text.indexOf( "\n", lineStart );
+				if ( lineEnd === -1 ) {
+					lineEnd = text.length - 1;
+				}
+				line = text.substring( lineStart, lineEnd + 1 );
+				lineStart = lineEnd + 1;
+
+				if ( lineHash.hasOwnProperty ? lineHash.hasOwnProperty( line ) :
+							( lineHash[ line ] !== undefined ) ) {
+					chars += String.fromCharCode( lineHash[ line ] );
+				} else {
+					chars += String.fromCharCode( lineArrayLength );
+					lineHash[ line ] = lineArrayLength;
+					lineArray[ lineArrayLength++ ] = line;
+				}
+			}
+			return chars;
+		}
+
+		chars1 = diffLinesToCharsMunge( text1 );
+		chars2 = diffLinesToCharsMunge( text2 );
+		return {
+			chars1: chars1,
+			chars2: chars2,
+			lineArray: lineArray
+		};
+	};
+
+	/**
+	 * Rehydrate the text in a diff from a string of line hashes to real lines of
+	 * text.
+	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+	 * @param {!Array.<string>} lineArray Array of unique strings.
+	 * @private
+	 */
+	DiffMatchPatch.prototype.diffCharsToLines = function( diffs, lineArray ) {
+		var x, chars, text, y;
+		for ( x = 0; x < diffs.length; x++ ) {
+			chars = diffs[ x ][ 1 ];
+			text = [];
+			for ( y = 0; y < chars.length; y++ ) {
+				text[ y ] = lineArray[ chars.charCodeAt( y ) ];
+			}
+			diffs[ x ][ 1 ] = text.join( "" );
+		}
+	};
+
+	/**
+	 * Reorder and merge like edit sections.  Merge equalities.
+	 * Any edit section can move as long as it doesn't cross an equality.
+	 * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+	 */
+	DiffMatchPatch.prototype.diffCleanupMerge = function( diffs ) {
+		var pointer, countDelete, countInsert, textInsert, textDelete,
+			commonlength, changes, diffPointer, position;
+		diffs.push( [ DIFF_EQUAL, "" ] ); // Add a dummy entry at the end.
+		pointer = 0;
+		countDelete = 0;
+		countInsert = 0;
+		textDelete = "";
+		textInsert = "";
+		commonlength;
+		while ( pointer < diffs.length ) {
+			switch ( diffs[ pointer ][ 0 ] ) {
+			case DIFF_INSERT:
+				countInsert++;
+				textInsert += diffs[ pointer ][ 1 ];
+				pointer++;
+				break;
+			case DIFF_DELETE:
+				countDelete++;
+				textDelete += diffs[ pointer ][ 1 ];
+				pointer++;
+				break;
+			case DIFF_EQUAL:
+
+				// Upon reaching an equality, check for prior redundancies.
+				if ( countDelete + countInsert > 1 ) {
+					if ( countDelete !== 0 && countInsert !== 0 ) {
+
+						// Factor out any common prefixes.
+						commonlength = this.diffCommonPrefix( textInsert, textDelete );
+						if ( commonlength !== 0 ) {
+							if ( ( pointer - countDelete - countInsert ) > 0 &&
+									diffs[ pointer - countDelete - countInsert - 1 ][ 0 ] ===
+									DIFF_EQUAL ) {
+								diffs[ pointer - countDelete - countInsert - 1 ][ 1 ] +=
+									textInsert.substring( 0, commonlength );
+							} else {
+								diffs.splice( 0, 0, [ DIFF_EQUAL,
+									textInsert.substring( 0, commonlength )
+								] );
+								pointer++;
+							}
+							textInsert = textInsert.substring( commonlength );
+							textDelete = textDelete.substring( commonlength );
+						}
+
+						// Factor out any common suffixies.
+						commonlength = this.diffCommonSuffix( textInsert, textDelete );
+						if ( commonlength !== 0 ) {
+							diffs[ pointer ][ 1 ] = textInsert.substring( textInsert.length -
+									commonlength ) + diffs[ pointer ][ 1 ];
+							textInsert = textInsert.substring( 0, textInsert.length -
+								commonlength );
+							textDelete = textDelete.substring( 0, textDelete.length -
+								commonlength );
+						}
+					}
+
+					// Delete the offending records and add the merged ones.
+					if ( countDelete === 0 ) {
+						diffs.splice( pointer - countInsert,
+							countDelete + countInsert, [ DIFF_INSERT, textInsert ] );
+					} else if ( countInsert === 0 ) {
+						diffs.splice( pointer - countDelete,
+							countDelete + countInsert, [ DIFF_DELETE, textDelete ] );
+					} else {
+						diffs.splice(
+							pointer - countDelete - countInsert,
+							countDelete + countInsert,
+							[ DIFF_DELETE, textDelete ], [ DIFF_INSERT, textInsert ]
+						);
+					}
+					pointer = pointer - countDelete - countInsert +
+						( countDelete ? 1 : 0 ) + ( countInsert ? 1 : 0 ) + 1;
+				} else if ( pointer !== 0 && diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL ) {
+
+					// Merge this equality with the previous one.
+					diffs[ pointer - 1 ][ 1 ] += diffs[ pointer ][ 1 ];
+					diffs.splice( pointer, 1 );
+				} else {
+					pointer++;
+				}
+				countInsert = 0;
+				countDelete = 0;
+				textDelete = "";
+				textInsert = "";
+				break;
+			}
+		}
+		if ( diffs[ diffs.length - 1 ][ 1 ] === "" ) {
+			diffs.pop(); // Remove the dummy entry at the end.
+		}
+
+		// Second pass: look for single edits surrounded on both sides by equalities
+		// which can be shifted sideways to eliminate an equality.
+		// e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
+		changes = false;
+		pointer = 1;
+
+		// Intentionally ignore the first and last element (don't need checking).
+		while ( pointer < diffs.length - 1 ) {
+			if ( diffs[ pointer - 1 ][ 0 ] === DIFF_EQUAL &&
+					diffs[ pointer + 1 ][ 0 ] === DIFF_EQUAL ) {
+
+				diffPointer = diffs[ pointer ][ 1 ];
+				position = diffPointer.substring(
+					diffPointer.length - diffs[ pointer - 1 ][ 1 ].length
+				);
+
+				// This is a single edit surrounded by equalities.
+				if ( position === diffs[ pointer - 1 ][ 1 ] ) {
+
+					// Shift the edit over the previous equality.
+					diffs[ pointer ][ 1 ] = diffs[ pointer - 1 ][ 1 ] +
+						diffs[ pointer ][ 1 ].substring( 0, diffs[ pointer ][ 1 ].length -
+							diffs[ pointer - 1 ][ 1 ].length );
+					diffs[ pointer + 1 ][ 1 ] =
+						diffs[ pointer - 1 ][ 1 ] + diffs[ pointer + 1 ][ 1 ];
+					diffs.splice( pointer - 1, 1 );
+					changes = true;
+				} else if ( diffPointer.substring( 0, diffs[ pointer + 1 ][ 1 ].length ) ===
+						diffs[ pointer + 1 ][ 1 ] ) {
+
+					// Shift the edit over the next equality.
+					diffs[ pointer - 1 ][ 1 ] += diffs[ pointer + 1 ][ 1 ];
+					diffs[ pointer ][ 1 ] =
+						diffs[ pointer ][ 1 ].substring( diffs[ pointer + 1 ][ 1 ].length ) +
+						diffs[ pointer + 1 ][ 1 ];
+					diffs.splice( pointer + 1, 1 );
+					changes = true;
+				}
+			}
+			pointer++;
+		}
+
+		// If shifts were made, the diff needs reordering and another shift sweep.
+		if ( changes ) {
+			this.diffCleanupMerge( diffs );
+		}
+	};
+
+	return function( o, n ) {
+		var diff, output, text;
+		diff = new DiffMatchPatch();
+		output = diff.DiffMain( o, n );
+		diff.diffCleanupEfficiency( output );
+		text = diff.diffPrettyHtml( output );
+
+		return text;
+	};
+}() );
+
+}() );
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/tobago-test.js b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/tobago-test.js
new file mode 100644
index 0000000..2836a67
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/script/tobago-test.js
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function jQueryFrame(expression) {
+  return document.getElementById("page:testframe").contentWindow.jQuery(expression);
+}
+
+/**
+ * Wait for ajax requests. Can be used with PhantomJs.
+ * @param waitingDone return false if still waiting, true if waiting done
+ * @param executeWhenDone is executed after waiting
+ * @param maxWait set the maximal waiting time in ms; default is 20000
+ */
+function waitForAjax(waitingDone, executeWhenDone, maxWait) {
+  var startTime = new Date().getTime();
+  maxWait = maxWait != null ? maxWait : 20000;
+  var stillWaiting = true;
+  var interval = setInterval(function() {
+    if (new Date().getTime() - startTime < maxWait && stillWaiting) {
+      stillWaiting = !waitingDone();
+    } else {
+      executeWhenDone();
+      clearInterval(interval);
+    }
+  }, 50);
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/server-info.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/server-info.xhtml
new file mode 100644
index 0000000..d5f6752
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/server-info.xhtml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/main.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets">
+
+  <ui:param name="title" value="Server Info"/>
+
+  <tc:panel rendered="#{info.enabled}">
+
+    <tc:section label="Main Properties">
+
+      <tc:in value="#{info.version}" readonly="true"
+             label="Tobago Version"/>
+
+      <tc:in value="#{info.jsfTitle}" readonly="true"
+             label="JSF Implementation"/>
+
+      <tc:in value="#{info.jsfVersion}" readonly="true"
+             label="JSF Version"/>
+
+      <tc:in value="#{info.serverInfo}" readonly="true"
+             label="Server Info"/>
+
+      <tc:in value="#{info.systemProperties['java.runtime.version']} - #{info.systemProperties['java.vm.vendor']}"
+             readonly="true"
+             label="Java"/>
+
+      <tc:in
+          value="#{info.systemProperties['os.name']} - #{info.systemProperties['os.version']} - #{info.systemProperties['os.arch']}"
+          readonly="true"
+          label="Operating System"/>
+
+    </tc:section>
+
+    <tc:section label="System Properties">
+
+      <tc:sheet var="entry" value="#{info.systemPropertiesAsList}" columns="*;2*" rows="1000">
+        <tc:column label="Key">
+          <tc:out value="#{entry.key}"/>
+        </tc:column>
+        <tc:column label="Value">
+          <tc:out value="#{entry.value}"/>
+        </tc:column>
+      </tc:sheet>
+    </tc:section>
+
+    <tc:section label="Sessions">
+
+      <tc:sheet value="#{activityList.values}" var="activity"
+                showRowRange="left" showPageRange="right" showDirectLinks="center">
+        <tc:column label="Session Id">
+          <tc:out value="#{activity.sessionId}"/>
+        </tc:column>
+        <tc:column label="Creation Date">
+          <tc:out value="#{activity.creationDate}"/>
+        </tc:column>
+        <tc:column label="Jsf Request Count">
+          <tc:out value="#{activity.jsfRequest}"/>
+        </tc:column>
+        <tc:column label="Ajax Request Count">
+          <tc:out value="#{activity.ajaxRequest}"/>
+        </tc:column>
+      </tc:sheet>
+    </tc:section>
+
+    <tc:section label="Manifest">
+
+      <tc:sheet value="#{manifestReader.manifestTree}" state="#{manifestReader.state}" var="manifest">
+        <tc:columnNode label="Library/Key">
+          <tc:treeIndent/>
+          <tc:treeLabel value="#{manifest.name}"/>
+        </tc:columnNode>
+        <tc:column label="Value">
+          <tc:out value="#{manifest.value}"/>
+        </tc:column>
+      </tc:sheet>
+
+    </tc:section>
+
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/demo.css b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/demo.css
new file mode 100644
index 0000000..4c4eb7f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/demo.css
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.demo-selected {
+  background-color: #ffddff;
+}
+
+#demo-view-source .demo-selected {
+  border: 1px solid #cccccc;
+}
+
+.blue {
+  background-color: #2aabff;
+}
+
+.demo-data-attribute {
+  height: 100px;
+  border: 1px solid #000000;
+  border-radius: .25rem;
+}
+
+pre, code {
+  font-size: 75%;
+}
+
+/* todo: should be switchable
+.comment {
+  display: none;
+}
+*/
+
+/* Prism and Bootstrap both use "tag" as CSS class name. So we need to "fix" some stuff. */
+.language-markup .token.tag {
+  font-weight: inherit;
+  font-size: inherit;
+  line-height: inherit;
+  /*display: inherit;*/
+  white-space: inherit;
+  text-align: inherit;
+  padding: inherit;
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/prism.css b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/prism.css
new file mode 100644
index 0000000..6e9eed2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/prism.css
@@ -0,0 +1,138 @@
+/* http://prismjs.com/download.html?themes=prism&languages=markup+css+clike+javascript+java+less */
+/**
+ * prism.js default theme for JavaScript, CSS and HTML
+ * Based on dabblet (http://dabblet.com)
+ * @author Lea Verou
+ */
+
+code[class*="language-"],
+pre[class*="language-"] {
+	color: black;
+	text-shadow: 0 1px white;
+	font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
+	direction: ltr;
+	text-align: left;
+	white-space: pre;
+	word-spacing: normal;
+	word-break: normal;
+	word-wrap: normal;
+	line-height: 1.5;
+
+	-moz-tab-size: 4;
+	-o-tab-size: 4;
+	tab-size: 4;
+
+	-webkit-hyphens: none;
+	-moz-hyphens: none;
+	-ms-hyphens: none;
+	hyphens: none;
+}
+
+pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
+code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
+	text-shadow: none;
+	background: #b3d4fc;
+}
+
+pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
+code[class*="language-"]::selection, code[class*="language-"] ::selection {
+	text-shadow: none;
+	background: #b3d4fc;
+}
+
+@media print {
+	code[class*="language-"],
+	pre[class*="language-"] {
+		text-shadow: none;
+	}
+}
+
+/* Code blocks */
+pre[class*="language-"] {
+	padding: 1em;
+	margin: .5em 0;
+	overflow: auto;
+}
+
+:not(pre) > code[class*="language-"],
+pre[class*="language-"] {
+	background: #f5f2f0;
+}
+
+/* Inline code */
+:not(pre) > code[class*="language-"] {
+	padding: .1em;
+	border-radius: .3em;
+}
+
+.token.comment,
+.token.prolog,
+.token.doctype,
+.token.cdata {
+	color: slategray;
+}
+
+.token.punctuation {
+	color: #999;
+}
+
+.namespace {
+	opacity: .7;
+}
+
+.token.property,
+.token.tag,
+.token.boolean,
+.token.number,
+.token.constant,
+.token.symbol,
+.token.deleted {
+	color: #905;
+}
+
+.token.selector,
+.token.attr-name,
+.token.string,
+.token.char,
+.token.builtin,
+.token.inserted {
+	color: #690;
+}
+
+.token.operator,
+.token.entity,
+.token.url,
+.language-css .token.string,
+.style .token.string {
+	color: #a67f59;
+	background: hsla(0, 0%, 100%, .5);
+}
+
+.token.atrule,
+.token.attr-value,
+.token.keyword {
+	color: #07a;
+}
+
+.token.function {
+	color: #DD4A68;
+}
+
+.token.regex,
+.token.important,
+.token.variable {
+	color: #e90;
+}
+
+.token.important,
+.token.bold {
+	font-weight: bold;
+}
+.token.italic {
+	font-style: italic;
+}
+
+.token.entity {
+	cursor: help;
+}
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/qunit-1.23.1.css b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/qunit-1.23.1.css
new file mode 100644
index 0000000..ae68fc4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/qunit-1.23.1.css
@@ -0,0 +1,305 @@
+/*!
+ * QUnit 1.23.1
+ * https://qunitjs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2016-04-12T17:29Z
+ */
+
+/** Font Family and Sizes */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
+	font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
+}
+
+#qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-tests { font-size: smaller; }
+
+
+/** Resets */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+	margin: 0;
+	padding: 0;
+}
+
+
+/** Header */
+
+#qunit-header {
+	padding: 0.5em 0 0.5em 1em;
+
+	color: #8699A4;
+	background-color: #0D3349;
+
+	font-size: 1.5em;
+	line-height: 1em;
+	font-weight: 400;
+
+	border-radius: 5px 5px 0 0;
+}
+
+#qunit-header a {
+	text-decoration: none;
+	color: #C2CCD1;
+}
+
+#qunit-header a:hover,
+#qunit-header a:focus {
+	color: #FFF;
+}
+
+#qunit-testrunner-toolbar label {
+	display: inline-block;
+	padding: 0 0.5em 0 0.1em;
+}
+
+#qunit-banner {
+	height: 5px;
+}
+
+#qunit-testrunner-toolbar {
+	padding: 0.5em 1em 0.5em 1em;
+	color: #5E740B;
+	background-color: #EEE;
+	overflow: hidden;
+}
+
+#qunit-filteredTest {
+	padding: 0.5em 1em 0.5em 1em;
+	background-color: #F4FF77;
+	color: #366097;
+}
+
+#qunit-userAgent {
+	padding: 0.5em 1em 0.5em 1em;
+	background-color: #2B81AF;
+	color: #FFF;
+	text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+
+#qunit-modulefilter-container {
+	float: right;
+	padding: 0.2em;
+}
+
+.qunit-url-config {
+	display: inline-block;
+	padding: 0.1em;
+}
+
+.qunit-filter {
+	display: block;
+	float: right;
+	margin-left: 1em;
+}
+
+/** Tests: Pass/Fail */
+
+#qunit-tests {
+	list-style-position: inside;
+}
+
+#qunit-tests li {
+	padding: 0.4em 1em 0.4em 1em;
+	border-bottom: 1px solid #FFF;
+	list-style-position: inside;
+}
+
+#qunit-tests > li {
+	display: none;
+}
+
+#qunit-tests li.running,
+#qunit-tests li.pass,
+#qunit-tests li.fail,
+#qunit-tests li.skipped {
+	display: list-item;
+}
+
+#qunit-tests.hidepass {
+	position: relative;
+}
+
+#qunit-tests.hidepass li.running,
+#qunit-tests.hidepass li.pass {
+	visibility: hidden;
+	position: absolute;
+	width:   0;
+	height:  0;
+	padding: 0;
+	border:  0;
+	margin:  0;
+}
+
+#qunit-tests li strong {
+	cursor: pointer;
+}
+
+#qunit-tests li.skipped strong {
+	cursor: default;
+}
+
+#qunit-tests li a {
+	padding: 0.5em;
+	color: #C2CCD1;
+	text-decoration: none;
+}
+
+#qunit-tests li p a {
+	padding: 0.25em;
+	color: #6B6464;
+}
+#qunit-tests li a:hover,
+#qunit-tests li a:focus {
+	color: #000;
+}
+
+#qunit-tests li .runtime {
+	float: right;
+	font-size: smaller;
+}
+
+.qunit-assert-list {
+	margin-top: 0.5em;
+	padding: 0.5em;
+
+	background-color: #FFF;
+
+	border-radius: 5px;
+}
+
+.qunit-source {
+	margin: 0.6em 0 0.3em;
+}
+
+.qunit-collapsed {
+	display: none;
+}
+
+#qunit-tests table {
+	border-collapse: collapse;
+	margin-top: 0.2em;
+}
+
+#qunit-tests th {
+	text-align: right;
+	vertical-align: top;
+	padding: 0 0.5em 0 0;
+}
+
+#qunit-tests td {
+	vertical-align: top;
+}
+
+#qunit-tests pre {
+	margin: 0;
+	white-space: pre-wrap;
+	word-wrap: break-word;
+}
+
+#qunit-tests del {
+	background-color: #E0F2BE;
+	color: #374E0C;
+	text-decoration: none;
+}
+
+#qunit-tests ins {
+	background-color: #FFCACA;
+	color: #500;
+	text-decoration: none;
+}
+
+/*** Test Counts */
+
+#qunit-tests b.counts                       { color: #000; }
+#qunit-tests b.passed                       { color: #5E740B; }
+#qunit-tests b.failed                       { color: #710909; }
+
+#qunit-tests li li {
+	padding: 5px;
+	background-color: #FFF;
+	border-bottom: none;
+	list-style-position: inside;
+}
+
+/*** Passing Styles */
+
+#qunit-tests li li.pass {
+	color: #3C510C;
+	background-color: #FFF;
+	border-left: 10px solid #C6E746;
+}
+
+#qunit-tests .pass                          { color: #528CE0; background-color: #D2E0E6; }
+#qunit-tests .pass .test-name               { color: #366097; }
+
+#qunit-tests .pass .test-actual,
+#qunit-tests .pass .test-expected           { color: #999; }
+
+#qunit-banner.qunit-pass                    { background-color: #C6E746; }
+
+/*** Failing Styles */
+
+#qunit-tests li li.fail {
+	color: #710909;
+	background-color: #FFF;
+	border-left: 10px solid #EE5757;
+	white-space: pre;
+}
+
+#qunit-tests > li:last-child {
+	border-radius: 0 0 5px 5px;
+}
+
+#qunit-tests .fail                          { color: #000; background-color: #EE5757; }
+#qunit-tests .fail .test-name,
+#qunit-tests .fail .module-name             { color: #000; }
+
+#qunit-tests .fail .test-actual             { color: #EE5757; }
+#qunit-tests .fail .test-expected           { color: #008000; }
+
+#qunit-banner.qunit-fail                    { background-color: #EE5757; }
+
+/*** Skipped tests */
+
+#qunit-tests .skipped {
+	background-color: #EBECE9;
+}
+
+#qunit-tests .qunit-skipped-label {
+	background-color: #F4FF77;
+	display: inline-block;
+	font-style: normal;
+	color: #366097;
+	line-height: 1.8em;
+	padding: 0 0.5em;
+	margin: -0.4em 0.4em -0.4em 0;
+}
+
+/** Result */
+
+#qunit-testresult {
+	padding: 0.5em 1em 0.5em 1em;
+
+	color: #2B81AF;
+	background-color: #D2E0E6;
+
+	border-bottom: 1px solid #FFF;
+}
+#qunit-testresult .module-name {
+	font-weight: 700;
+}
+
+/** Fixture */
+
+#qunit-fixture {
+	position: absolute;
+	top: -10000px;
+	left: -10000px;
+	width: 1000px;
+	height: 1000px;
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/tobago.css b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/tobago.css
new file mode 100644
index 0000000..b229d43
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/style/tobago.css
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.tobago-sheet-cell-markup-sun {
+  background-color: #fffacd;
+}
+
+.tobago-sheet-cell-markup-planet {
+  background-color: #ffb6c1;
+}
+
+.tobago-sheet-cell-markup-moon {
+  background-color: #6495ed;
+}
+
+.tobago-sheet-cell-markup-lightgreen {
+  background-color: #ddffdd;
+}
+
+.tobago-sheet-cell-markup-lightred {
+  background-color: #ffdddd;
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/test.xhtml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/test.xhtml
new file mode 100644
index 0000000..119d637
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/test.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition template="/plain.xhtml"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns="http://www.w3.org/1999/xhtml">
+  <tc:script file="#{request.contextPath}/script/demo.js"/>
+  <tc:script file="#{request.contextPath}/script/qunit-1.23.1.js"/>
+  <tc:script file="#{request.contextPath}/script/tobago-test.js"/>
+  <tc:style file="#{request.contextPath}/style/qunit-1.23.1.css"/>
+  <tc:script file="#{param['testjs']}"/>
+
+  <div id="qunit"></div>
+  <div id="qunit-fixture"></div>
+
+  <tc:object id="testframe" src="#{param['page']}">
+    <tc:style width="100%"/>
+  </tc:object>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/charlotteville/standard/property/demo.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/charlotteville/standard/property/demo.properties.xml
new file mode 100644
index 0000000..a5abfbf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/charlotteville/standard/property/demo.properties.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="theme_photo">The Pier in the center of Charlotteville</entry>
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/richmond/standard/property/demo.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/richmond/standard/property/demo.properties.xml
new file mode 100644
index 0000000..1b325bf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/richmond/standard/property/demo.properties.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="theme_photo">Flowers near Richmond</entry>
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/scarborough/standard/property/demo.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/scarborough/standard/property/demo.properties.xml
new file mode 100644
index 0000000..18a0eb3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/scarborough/standard/property/demo.properties.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="theme_photo">Sundown from hill above Scarborough</entry>
+</properties>
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/speyside/standard/property/demo.properties.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/speyside/standard/property/demo.properties.xml
new file mode 100644
index 0000000..61f4c4f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/main/webapp/tobago-resource/html/speyside/standard/property/demo.properties.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
+
+<properties>
+  <entry key="theme_photo">A green parrot in a tree above Speyside</entry>
+</properties>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/clickImage.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/clickImage.psd
new file mode 100644
index 0000000..47d8af5
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/clickImage.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country.psd
new file mode 100644
index 0000000..792fd31
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_AT.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_AT.psd
new file mode 100644
index 0000000..6488695
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_AT.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_CH.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_CH.psd
new file mode 100644
index 0000000..1b5145b
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_CH.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_DE.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_DE.psd
new file mode 100644
index 0000000..3a086f4
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_de_DE.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_en_GB.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_en_GB.psd
new file mode 100644
index 0000000..394b5c8
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_en_GB.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_en_US.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_en_US.psd
new file mode 100644
index 0000000..d300acc
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_en_US.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_ja_JP.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_ja_JP.psd
new file mode 100644
index 0000000..190fe91
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_ja_JP.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_ru_RU.psd b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_ru_RU.psd
new file mode 100644
index 0000000..d110dc2
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-demo/src/origin/image/country_ru_RU.psd differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/ArquillianTest.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/ArquillianTest.java
new file mode 100644
index 0000000..72b4aba
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/ArquillianTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import java.io.File;
+import java.net.URL;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.arquillian.graphene.findby.FindByJQuery;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.archive.importer.MavenImporter;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.support.FindBy;
+
+/**
+ * if PhantomJS is configured, ensure that content-security-policy mode="off" is in tobago-config.xml otherwise
+ * it will result in "Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed
+ * source of script in the following Content Security Policy directive"
+ * see: https://github.com/ariya/phantomjs/issues/13114
+ */
+@RunWith(Arquillian.class)
+@RunAsClient
+public class ArquillianTest {
+
+  @Drone
+  private WebDriver browser;
+
+  @ArquillianResource
+  private URL contextPath;
+
+  @FindBy(id = "page:iajax::field")
+  private WebElement input;
+
+  @FindBy(id = "page:oajax")
+  private WebElement output;
+
+  @FindByJQuery("#page\\:oajax > label")
+  private WebElement outputLabel;
+
+  @FindByJQuery("#page\\:oajax > span")
+  private WebElement outputField;
+
+  @Deployment(testable = false)
+  public static WebArchive createDeployment() {
+    File pom = new File("tobago-example/tobago-example-demo/pom.xml");
+    WebArchive webArchive = ShrinkWrap.create(MavenImporter.class).
+            loadPomFromFile(pom, "jsf-provided", "!myfaces-2.0").importBuildOutput()
+            .as(WebArchive.class);
+    // XXX there should be a proper profile in POM for that
+    webArchive.delete("/WEB-INF/lib/hibernate-validator-4.3.2.Final.jar");
+    return webArchive;
+  }
+
+  @Test
+  public void ajaxOnChange() {
+    browser.get(contextPath + "/faces/content/20-component/010-input/10-in/in.xhtml");
+
+    Assert.assertEquals("On Server", outputLabel.getText());
+    Assert.assertEquals("", outputField.getText());
+
+    final String text = "Testtext";
+    input.sendKeys(text);
+    output.click();
+//    Graphene.waitAjax();
+/*
+    try {
+      Thread.sleep(30000);
+    } catch (InterruptedException e) {
+      e.printStackTrace();
+    }
+*/
+
+    Assert.assertEquals(text, outputField.getText());
+
+
+//    JavascriptExecutor js = (JavascriptExecutor) browser;
+//    js.executeScript("$(Tobago.Utils.escapeClientId('{}')).blur();", output.getAttribute("id"));
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/NavigationUnitTest.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/NavigationUnitTest.java
new file mode 100644
index 0000000..4c31fe9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/NavigationUnitTest.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.servlet.ServletContext;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+public class NavigationUnitTest extends AbstractTobagoTestBase {
+
+  private static final List<String> LIST = new ArrayList<String>(Arrays.asList(
+      "/content/00/test-1.xhtml",
+      "/content/00/07/test-2.xhtml",
+      "/content/01/test.xhtml",
+      "/content/00/00/test-4.xhtml",
+      "/content/bad.jsp",
+      "/content/00_00_bad.png"
+  ));
+
+  @Test
+  public void testFileNames() {
+    final NavigationTree navigation = new NavigationTree() {
+      @Override
+      protected List<String> locateResourcesInWar(
+          ServletContext servletContext, String directory, List<String> result) {
+        return LIST;
+      }
+    };
+    navigation.postConstruct();
+    final NavigationNode root = navigation.getTree();
+    Assert.assertEquals(2, root.getChildCount());
+    final NavigationNode n00 = (NavigationNode) root.getChildAt(0);
+    Assert.assertEquals("/content/00", n00.getBranch());
+    Assert.assertEquals("test-1", n00.getName());
+    final NavigationNode n01 = (NavigationNode) root.getChildAt(1);
+    Assert.assertEquals("/content/01", n01.getBranch());
+    Assert.assertEquals("test", n01.getName());
+    final NavigationNode n0000 = (NavigationNode) n00.getChildAt(0);
+    Assert.assertEquals("/content/00/00", n0000.getBranch());
+    Assert.assertEquals("test-4", n0000.getName());
+    final NavigationNode n0007 = (NavigationNode) n00.getChildAt(1);
+    Assert.assertEquals("/content/00/07", n0007.getBranch());
+    Assert.assertEquals("test-2", n0007.getName());
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/QUnitTests.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/QUnitTests.java
new file mode 100644
index 0000000..dec101f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/QUnitTests.java
@@ -0,0 +1,429 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo;
+
+import org.jboss.arquillian.container.test.api.Deployment;
+import org.jboss.arquillian.container.test.api.RunAsClient;
+import org.jboss.arquillian.drone.api.annotation.Drone;
+import org.jboss.arquillian.graphene.findby.FindByJQuery;
+import org.jboss.arquillian.junit.Arquillian;
+import org.jboss.arquillian.test.api.ArquillianResource;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.resolver.api.maven.archive.importer.MavenImporter;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebDriver;
+import org.openqa.selenium.WebElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+
+@RunWith(Arquillian.class)
+@RunAsClient
+public class QUnitTests {
+
+  private static final Logger LOG = LoggerFactory.getLogger(QUnitTests.class);
+  private static List<String> testedPages = new LinkedList<String>();
+
+  @Drone
+  private WebDriver browser;
+  @ArquillianResource
+  private URL contextPath;
+  @FindByJQuery("#qunit")
+  private WebElement qunit;
+
+  @Deployment
+  public static WebArchive createDeployment() {
+    WebArchive webArchive;
+    try {
+      webArchive = createWebArchive(new File("tobago-example/tobago-example-demo/pom.xml"));
+    } catch (Exception e) {
+      webArchive = createWebArchive(new File("pom.xml")); // Jenkins
+    }
+    return webArchive;
+  }
+
+  private static WebArchive createWebArchive(File pom) {
+    WebArchive webArchive = ShrinkWrap.create(MavenImporter.class).
+       loadPomFromFile(pom, "jsf-provided", "!myfaces-2.0").importBuildOutput()
+       .as(WebArchive.class);
+    // XXX there should be a proper profile in POM for that
+    webArchive.delete("/WEB-INF/lib/hibernate-validator-4.3.2.Final.jar");
+    return webArchive;
+  }
+
+  private void setupBrowser(String page, String testJs) throws UnsupportedEncodingException {
+    LOG.info("setup browser for: " + page);
+    browser.get(contextPath + "/faces/test.xhtml?page=" + URLEncoder.encode(page, "UTF-8") + "&testjs="
+        + contextPath + URLEncoder.encode(testJs, "UTF-8"));
+  }
+
+  private void runStandardTest(String page) throws UnsupportedEncodingException, InterruptedException {
+    testedPages.add(page);
+
+    if (!ignorePages().contains(page)) {
+      String testJs = page.substring(0, page.length() - 6) + ".test.js";
+      setupBrowser(page, testJs);
+
+      checkQUnitResults(page);
+    }
+  }
+
+  private void checkQUnitResults(String page) throws InterruptedException {
+    waitForTestCases();
+    List<WebElement> testCases = qunit.findElement(By.id("qunit-tests")).findElements(By.xpath("li"));
+    Assert.assertTrue("There must be at least one test case.", testCases.size() > 0);
+
+    for (WebElement testCase : testCases) {
+      finishTestCaseExecution(testCase);
+      String testName = testCase.findElement(By.className("test-name")).getText();
+      String runtime = testCase.findElement(By.className("runtime")).getText();
+
+      if ("pass".equals(testCase.getAttribute("class"))) {
+        LOG.info("test '" + testName + "' for " + page + " passed in " + runtime);
+        Assert.assertTrue(true);
+      } else if ("fail".equals(testCase.getAttribute("class"))) {
+        WebElement assertList = testCase.findElement(By.className("qunit-assert-list"));
+        List<WebElement> asserts = assertList.findElements(By.tagName("li"));
+
+        int assertionCount = 0;
+        for (WebElement assertion : asserts) {
+          assertionCount++;
+          if ("pass".equals(assertion.getAttribute("class"))) {
+            Assert.assertTrue(true);
+          } else if ("fail".equals(assertion.getAttribute("class"))) {
+            WebElement source = assertion.findElement(By.className("test-source"));
+            LOG.warn("test '" + testName + "' for " + page + " failed on assertion " + assertionCount
+                + "\n" + source.getText());
+            String message = assertion.findElement(By.className("test-message")).getText();
+            String expected = assertion.findElement(By.className("test-expected")).getText();
+            String actual = assertion.findElement(By.className("test-actual")).getText();
+            Assert.assertEquals(message, expected, actual);
+          }
+        }
+      } else if ("running".equals(testCase.getAttribute("class"))) {
+        LOG.warn("test '" + testName + "' for " + page + " is still running...");
+        Assert.fail();
+      } else {
+        LOG.warn("unexpected error on test '" + testName + "' for " + page);
+        Assert.fail();
+      }
+    }
+  }
+
+  private void waitForTestCases() throws InterruptedException {
+    long endTime = System.currentTimeMillis() + 20000;
+    boolean testCasesExist = false;
+    while (System.currentTimeMillis() < endTime && !testCasesExist) {
+      try {
+        qunit.findElement(By.id("qunit-tests")).findElements(By.xpath("li"));
+        testCasesExist = true;
+      } catch (Exception e) {
+        LOG.info("wait for testCases exist... (" + (endTime - System.currentTimeMillis()) + "ms left)");
+        Thread.sleep(50);
+      }
+    }
+  }
+
+  private void finishTestCaseExecution(WebElement testCase) throws InterruptedException {
+    long endTime = System.currentTimeMillis() + 20000;
+    boolean testExecuted = false;
+    while (System.currentTimeMillis() < endTime && !testExecuted) {
+      if ("running".equals(testCase.getAttribute("class"))) {
+        testExecuted = false;
+        LOG.info("wait for test execution... (" + (endTime - System.currentTimeMillis()) + "ms left)");
+        Thread.sleep(50);
+      } else {
+        testExecuted = true;
+      }
+    }
+  }
+
+  @AfterClass
+  public static void checkMissingTests() {
+    if (testedPages.size() > 1) {
+      List<String> pages = getXHTMLs();
+      int testablePagesCount = 0;
+
+      StringBuilder stringBuilder = new StringBuilder();
+      for (String page : pages) {
+        if (new File(page.substring(0, page.length() - 6) + ".test.js").exists()) {
+          testablePagesCount++;
+
+          String pathForBrowser = page.substring(page.indexOf("src/main/webapp/") + "src/main/webapp/".length());
+          if (!testedPages.contains(pathForBrowser)) {
+            String errorString = "missing testmethod for " + pathForBrowser;
+            LOG.warn(errorString);
+            stringBuilder.append("\n");
+            stringBuilder.append(errorString);
+          }
+        }
+      }
+      Assert.assertEquals(stringBuilder.toString(), testablePagesCount, testedPages.size());
+    }
+  }
+
+  @Test
+  public void testAccessAllPages() throws UnsupportedEncodingException, InterruptedException {
+    List<String> pages = getXHTMLs();
+    String testJs = "error/error.test.js";
+    List<WebElement> results;
+
+    // Test if 'has no exception' test is correct.
+    setupBrowser("error/exception.xhtml", testJs);
+    results = qunit.findElement(By.id("qunit-tests")).findElements(By.xpath("li"));
+    Assert.assertEquals(results.get(0).getAttribute("class"), "fail");
+    Assert.assertEquals(results.get(1).getAttribute("class"), "pass");
+
+    // Test if 'has no 404' test is correct.
+    setupBrowser("error/404.xhtml", testJs);
+    results = qunit.findElement(By.id("qunit-tests")).findElements(By.xpath("li"));
+    Assert.assertEquals(results.get(0).getAttribute("class"), "pass");
+    Assert.assertEquals(results.get(1).getAttribute("class"), "fail");
+
+    for (String page : pages) {
+      String pathForBrowser = page.substring(page.indexOf("src/main/webapp/") + "src/main/webapp/".length());
+      setupBrowser(pathForBrowser, testJs);
+      checkQUnitResults(page);
+    }
+  }
+
+  private static List<String> getXHTMLs() {
+    File rootDir = new File("tobago-example/tobago-example-demo/src/main/webapp/content");
+    if (!rootDir.exists()) {
+      rootDir = new File("src/main/webapp/content"); // Jenkins.
+    }
+    return getXHTMLs(rootDir);
+  }
+
+  private static List<String> getXHTMLs(File dir) {
+    List<String> xhtmls = new ArrayList<String>();
+    for (File file : dir.listFiles()) {
+      if (file.isDirectory()) {
+        xhtmls.addAll(getXHTMLs(file));
+      } else if (!file.getName().startsWith("x-") && file.getName().endsWith(".xhtml")) {
+        xhtmls.add(file.getPath());
+      }
+    }
+    return xhtmls;
+  }
+
+  private List<String> ignorePages() {
+    List<String> ignore = new ArrayList<String>();
+    //Knows bugs
+    ignore.add("content/20-component/010-input/50-input-group/group.xhtml");
+    //PhantomJs miscalculate the height of the dropdown box
+    ignore.add("content/40-test/3000-sheet/10-sheet-types/sheet-types.xhtml");
+    //ajaxListener doesn't work for <tc:in> events: focus, blur, click, dblclick
+    ignore.add("content/40-test/6000-event/event.xhtml");
+    return ignore;
+  }
+
+  @Test
+  public void in() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/010-input/10-in/in.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void suggest() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/010-input/20-suggest/suggest.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void date() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/010-input/40-date/date.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void group() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/010-input/50-input-group/group.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void selectBooleanCheckbox() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/030-select/10-selectBooleanCheckbox/selectBooleanCheckbox.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void selectOneChoice() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/030-select/20-selectOneChoice/selectOneChoice.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void selectOneRadio() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/030-select/30-selectOneRadio/selectOneRadio.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void selectOneListbox() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/030-select/40-selectOneListbox/selectOneListbox.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void selectManyCheckbox() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/030-select/50-selectManyCheckbox/selectManyCheckbox.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void popup() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/060-popup/popup.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void sheetSorting() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/080-sheet/10-sort/sheet-sorting.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void sheetEvent() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/080-sheet/30-event/sheet-event.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void treeSelect() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/20-component/090-tree/01-select/tree-select.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void contentValidation() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/06-validation/00/content-validation.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void validationJsr303() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/06-validation/01/validation-jsr303.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void form() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/08-form/form.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void formRequired() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/08-form/10-required/form-required.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void formAjax() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/08-form/20-ajax/form-ajax.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void forEach() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/51-for-each/for-each.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void collapsibleBox() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/53-collapsible/00-collapsible-box/collapsible-box.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void collapsiblePopup() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/53-collapsible/10-collapsible-popup/collapsible-popup.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void collapsiblePanel() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/53-collapsible/20-collapsible-panel/collapsible-panel.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void collapsibleSection() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/30-concept/53-collapsible/30-collapsible-section/collapsible-section.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void suggestMethod() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/35-deprecated/15-suggest-method/suggest-method.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void testDate() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/40-test/1040-date/date.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void testButtonLink() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/40-test/4000-button+link/button+link.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void testSheetTypes() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/40-test/3000-sheet/10-sheet-types/sheet-types.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void testEvent() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/40-test/6000-event/event.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void rendererBaseGetCurrentValue() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/40-test/50000-java/10-rendererBase-getCurrentValue/rendererBase-getCurrentValue.xhtml";
+    runStandardTest(page);
+  }
+
+  @Test
+  public void ajaxExecute() throws UnsupportedEncodingException, InterruptedException {
+    String page = "content/40-test/50000-java/20-ajax-execute/ajax-execute.xhtml";
+    runStandardTest(page);
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/sudoku/SudokuUnitTest.java b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/sudoku/SudokuUnitTest.java
new file mode 100644
index 0000000..a4c2f34
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/java/org/apache/myfaces/tobago/example/demo/sudoku/SudokuUnitTest.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.demo.sudoku;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SudokuUnitTest {
+
+  private static final Sudoku TRIVIAL = new Sudoku(new byte[]{
+      0, 1, 2, 3, 4, 5, 6, 7, 8,
+      3, 4, 5, 6, 7, 8, 0, 1, 2,
+      6, 7, 8, 0, 1, 2, 3, 4, 5,
+
+      1, 2, 3, 4, 5, 6, 7, 8, 0,
+      4, 5, 6, 7, 8, 0, 1, 2, 3,
+      7, 8, 0, 1, 2, 3, 4, 5, 6,
+
+      2, 3, 4, 5, 6, 7, 8, 0, 1,
+      5, 6, 7, 8, 0, 1, 2, 3, 4,
+      8, 0, 1, 2, 3, 4, 5, 6, 7,
+  });
+
+  private static final Sudoku WRONG = new Sudoku(new byte[]{
+      0, -1, -1, -1, -1, -1, -1, -1, 0,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1,
+
+      -1, -1, -1, -1, 0, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, 0, -1, -1, -1,
+
+      -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, -1, -1, -1, -1,
+      -1, -1, -1, -1, -1, 0, -1, -1, -1,
+  });
+
+  @Test
+  public void testCheckRowRules() {
+    Assert.assertTrue(TRIVIAL.checkRowRules());
+    Assert.assertFalse(WRONG.checkRowRules());
+  }
+
+  @Test
+  public void testCheckColumnRules() {
+    Assert.assertTrue(TRIVIAL.checkColumnRules());
+    Assert.assertFalse(WRONG.checkColumnRules());
+  }
+
+  @Test
+  public void testCheckSquareRules() {
+    Assert.assertTrue(TRIVIAL.checkSquareRules());
+    Assert.assertFalse(WRONG.checkSquareRules());
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/arquillian.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/arquillian.xml
new file mode 100644
index 0000000..7354a00
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/arquillian.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?>

<!--
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
-->

<arquillian xmlns="http://jboss.org/schema/arquillian"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xsi:schemaLocation
 ="http://jboss.org/schema/arquillian http://jboss.org/schema/arquillian/arquillian_1_0.xsd">
   <defaultProtocol type="Servlet 3.0"/>
   <container qualifier="tomee" default="true">
      <configuration>
         <property name="httpPort">-1</property>
         <property name="stopPort">-1</property>
         <!--<property name="cleanOnStartUp">true</property>-->
         <!--<property name="appWorkingDir">${project.build.directory}/tomee-test</property>-->
         <!--<property name="dir">${project.build.directory}/tomee</property>-->
         <!--<property name="debug">${arquillian.remote.debug}</property>-->
         <!--<property name="debugPort">5005</property>-->
         <!--<property name="catalina_opts">${argLine} -Djava.security.auth.login.config=${project.basedir}/src/main/tomee/conf/jaas.config</property>-->
      </configuration>
   </container>
   <extension qualifier="webdriver">
      <property name="browser">${arquillian.browser}</property>
<!--      <property name
 ="dimensions">1280x1024</property>
      <property name="reuseCookies">false</property>-->
   </extension>
   <extension qualifier="screenshooter">
      <property name="rootDir">${project.build.directory}/screenshots</property>
   </extension>
</arquillian>
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/realm.properties b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/realm.properties
new file mode 100644
index 0000000..be4a79a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/realm.properties
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# username: password [,rolename ...]
+guest: guest,demo-guest
+admin: admin,demo-admin
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/server.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/server.xml
new file mode 100644
index 0000000..959bdf0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/resources/server.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!--
+    this is for the websphere liberty profile
+-->
+<server description="new server">
+
+    <!-- Enable features -->
+    <featureManager>
+        <feature>cdi-1.0</feature>
+        <feature>jsp-2.2</feature>
+        <feature>servlet-3.0</feature>
+        <feature>jsf-2.0</feature>
+    </featureManager>
+
+    <httpEndpoint id="defaultHttpEndpoint"
+                  host="localhost"
+                  httpPort="9080"
+                  httpsPort="9443" />
+
+
+</server>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/tomee/conf/tomcat-users.xml b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/tomee/conf/tomcat-users.xml
new file mode 100644
index 0000000..c626471
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-demo/src/test/tomee/conf/tomcat-users.xml
@@ -0,0 +1,25 @@
+<?xml version='1.0' encoding='utf-8'?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tomcat-users>
+  <role rolename="demo-guest"/>
+  <role rolename="demo-admin"/>
+  <user username="guest" password="guest" roles="demo-guest"/>
+  <user username="admin" password="admin" roles="demo-admin"/>
+</tomcat-users>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/pom.xml b/tobago-3.0.x/tobago-example/tobago-example-portlet/pom.xml
new file mode 100644
index 0000000..f8f6bcb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-example</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-example-portlet</artifactId>
+  <packaging>war</packaging>
+  <name>Tobago Example for Portlets</name>
+
+</project>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/java/org/apache/myfaces/tobago/example/portlet/User.java b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/java/org/apache/myfaces/tobago/example/portlet/User.java
new file mode 100644
index 0000000..3250f36
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/java/org/apache/myfaces/tobago/example/portlet/User.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.portlet;
+
+public class User {
+  private String name;
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public String getName() {
+    return name;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/resources/logback.xml b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/resources/logback.xml
new file mode 100644
index 0000000..c7bb531
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/resources/logback.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- Schema is NOT official from logback -->
+<configuration
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="https://raw.github.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{ISO8601} [%-16.16thread] %-5level %-50.50logger{50}:%-20.20method:%-4.4line [%mdc] %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <!--
+    <logger name="org.apache.myfaces.tobago" level="debug"/>
+  -->
+
+  <root level="info">
+    <appender-ref ref="console"/>
+  </root>
+</configuration>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/faces-config.xml b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..e878b41
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<faces-config
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
+    version="2.0">
+
+  <application>
+    <locale-config>
+      <default-locale>en</default-locale>
+    </locale-config>
+  </application>
+
+  <navigation-rule>
+    <navigation-case>
+      <from-outcome>helloWorld</from-outcome>
+      <to-view-id>/index.jsp</to-view-id>
+    </navigation-case>
+  </navigation-rule>
+  <navigation-rule>
+    <navigation-case>
+      <from-outcome>sayHello</from-outcome>
+      <to-view-id>/hello.jsp</to-view-id>
+    </navigation-case>
+  </navigation-rule>
+
+  <managed-bean>
+    <managed-bean-name>user</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.portlet.User</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+</faces-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/liferay-portlet.xml b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/liferay-portlet.xml
new file mode 100644
index 0000000..c433a95
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/liferay-portlet.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE liferay-portlet-app PUBLIC "-//Liferay//DTD Portlet Application 5.1.0//EN" "http://www.liferay.com/dtd/liferay-portlet-app_5_1_0.dtd">
+
+<liferay-portlet-app>
+	<portlet>
+		<portlet-name>tobago-example-portlet</portlet-name>
+		<instanceable>true</instanceable>
+	</portlet>
+</liferay-portlet-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/portlet.xml b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/portlet.xml
new file mode 100644
index 0000000..4de64d2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/portlet.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<portlet-app xmlns="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd" version="1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_1_0.xsd">
+
+  <portlet>
+    <portlet-name>tobago-example-portlet</portlet-name>
+    <display-name>Tobago Portlet Example (not functional)</display-name>
+
+    <portlet-class>org.apache.myfaces.portlet.MyFacesGenericPortlet</portlet-class>
+
+    <init-param>
+			<name>default-view</name>
+      <value>/index.jsp</value>
+    </init-param>
+		<supports>
+			<mime-type>text/html</mime-type>
+		</supports>
+    <portlet-info>
+      <title>Tobago Portlet Example (not functional)</title>
+      <short-title>Tobago Portlet Example (not functional)</short-title>
+    </portlet-info>
+  </portlet>
+
+</portlet-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/web.xml b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..79db900
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<web-app
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+    version="3.0">
+
+  <servlet>
+    <servlet-name>FacesServlet</servlet-name>
+    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+    <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+    <multipart-config>
+      <max-request-size>20000000</max-request-size>
+      <max-file-size>1000000</max-file-size>
+    </multipart-config>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>FacesServlet</servlet-name>
+    <url-pattern>/faces/*</url-pattern>
+  </servlet-mapping>
+
+  <session-config>
+    <cookie-config>
+      <http-only>true</http-only>
+    </cookie-config>
+  </session-config>
+
+</web-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/hello.xhtml b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/hello.xhtml
new file mode 100644
index 0000000..c36e2b6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/hello.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;auto" rows="auto;*"/>
+    </f:facet>
+    <tc:out value="Hello #{user.name}!"/>
+    <tc:button action="helloWorld" label="Return"/>
+    <tc:panel/>
+    <tc:panel/>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/index.xhtml b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/index.xhtml
new file mode 100644
index 0000000..db661a5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-portlet/src/main/webapp/index.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;auto" rows="auto;*"/>
+    </f:facet>
+    <tc:in label="Your Name" tip="Please enter your name here!" value="#{user.name}"/>
+    <tc:button action="sayHello" label="Click Here"/>
+    <tc:panel/>
+    <tc:panel/>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/pom.xml b/tobago-3.0.x/tobago-example/tobago-example-test/pom.xml
new file mode 100644
index 0000000..c34aba8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/pom.xml
@@ -0,0 +1,292 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-example</artifactId>
+    <version>3.0.3-SNAPSHOT</version>
+  </parent>
+  <artifactId>tobago-example-test</artifactId>
+  <packaging>war</packaging>
+  <name>Tobago Example Test</name>
+  <description>A web application to provide test pages for running automated tests.</description>
+  <build>
+    <finalName>tobago-example-test</finalName>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-war-plugin</artifactId>
+        <configuration>
+          <webResources>
+            <resource>
+              <targetPath>src</targetPath>
+              <directory>${basedir}/src/main/java</directory>
+            </resource>
+          </webResources>
+        </configuration>
+      </plugin>
+      <plugin>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <skip>false</skip>
+          <excludes>
+            <exclude>**/*SeleniumTest.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-example-data</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-sandbox</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>oro</groupId>
+      <artifactId>oro</artifactId>
+      <version>2.0.8</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.seleniumhq.selenium</groupId>
+      <artifactId>selenium-java</artifactId>
+      <version>2.53.1</version>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+    <!-- DeltaSpike/CDI -->
+<!--
+    <dependency>
+      <groupId>org.apache.deltaspike.modules</groupId>
+      <artifactId>deltaspike-jsf-module-impl</artifactId>
+      <version>1.3.0</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jcdi_1.0_spec</artifactId>
+      <version>1.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-atinject_1.0_spec</artifactId>
+      <version>1.0</version>
+    </dependency>
+-->
+  </dependencies>
+  <profiles>
+    <profile>
+      <id>integration-test</id>
+      <build>
+        <plugins>
+          <plugin>
+            <artifactId>maven-surefire-plugin</artifactId>
+            <configuration>
+              <skip>false</skip>
+              <excludes>
+                <exclude>**/*SeleniumTest.java</exclude>
+              </excludes>
+            </configuration>
+            <executions>
+              <execution>
+                <id>integration-tests</id>
+                <phase>integration-test</phase>
+                <goals>
+                  <goal>test</goal>
+                </goals>
+                <configuration>
+                  <skip>false</skip>
+                  <excludes>
+                    <exclude>none</exclude>
+                  </excludes>
+                  <includes>
+                    <include>**/*SeleniumTest.java</include>
+                  </includes>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+          <!--
+                <plugin>
+                  <groupId>org.codehaus.cargo</groupId>
+                  <artifactId>cargo-maven2-plugin</artifactId>
+                  <version>1.0-beta-2</version>
+                  <configuration>
+                    <wait>false</wait>
+                    <container>
+                      <containerId>tomcat5x</containerId>
+                      <zipUrlInstaller>
+                        <url>http://archive.apache.org/dist/tomcat/tomcat-5/v5.5.26/bin/apache-tomcat-5.5.26.zip</url>
+                      </zipUrlInstaller>
+                    </container>
+                  </configuration>
+
+                  <executions>
+                    <execution>
+                      <id>start-container</id>
+                      <phase>pre-integration-test</phase>
+                      <goals>
+                        <goal>start</goal>
+                        <goal>deploy</goal>
+                      </goals>
+                    </execution>
+
+                    <execution>
+                      <id>stop-container</id>
+                      <phase>post-integration-test</phase>
+                      <goals>
+                        <goal>stop</goal>
+                      </goals>
+                    </execution>
+                  </executions>
+                </plugin>
+          -->
+          <plugin>
+            <groupId>org.eclipse.jetty</groupId>
+            <!--<groupId>org.eclipse.jetty</groupId>-->
+            <artifactId>jetty-maven-plugin</artifactId>
+            <configuration>
+              <httpConnector>
+                <port>8080</port>
+              </httpConnector>
+              <stopKey>stopKey</stopKey>
+              <stopPort>9999</stopPort>
+            </configuration>
+            <executions>
+              <execution>
+                <id>start-jetty</id>
+                <phase>pre-integration-test</phase>
+                <goals>
+                  <goal>deploy-war</goal>
+                </goals>
+                <configuration>
+                  <daemon>true</daemon>
+                </configuration>
+              </execution>
+              <execution>
+                <id>stop-jetty</id>
+                <phase>post-integration-test</phase>
+                <goals>
+                  <goal>stop</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+
+          <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>selenium-maven-plugin</artifactId>
+            <version>2.3</version>
+            <executions>
+              <execution>
+                <id>start</id>
+                <phase>pre-integration-test</phase>
+                <goals>
+                  <goal>start-server</goal>
+                </goals>
+                <configuration>
+                  <background>true</background>
+                  <logOutput>true</logOutput>
+                  <!--multiWindow>true</multiWindow-->
+                </configuration>
+              </execution>
+
+              <execution>
+                <id>stop</id>
+                <phase>post-integration-test</phase>
+                <goals>
+                  <goal>stop-server</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <!--
+       mvn package cargo:start -Ptomcat6x
+      -->
+      <id>tomcat6x</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.cargo</groupId>
+            <artifactId>cargo-maven2-plugin</artifactId>
+            <version>1.0</version>
+            <configuration>
+              <container>
+                <containerId>tomcat6x</containerId>
+                <zipUrlInstaller>
+                  <url>http://archive.apache.org/dist/tomcat/tomcat-6/v6.0.33/bin/apache-tomcat-6.0.33.zip</url>
+                  <installDir>${project.build.directory}/tomcat6</installDir>
+                </zipUrlInstaller>
+              </container>
+              <configuration>
+                <home>${project.build.directory}/tomcat6/container</home>
+              </configuration>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <!--
+       mvn package cargo:start -Ptomcat5x
+      -->
+      <id>tomcat5x</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.codehaus.cargo</groupId>
+            <artifactId>cargo-maven2-plugin</artifactId>
+            <version>1.0</version>
+            <configuration>
+              <container>
+                <containerId>tomcat5x</containerId>
+                <zipUrlInstaller>
+                  <url>http://archive.apache.org/dist/tomcat/tomcat-5/v5.5.33/bin/apache-tomcat-5.5.33.zip</url>
+                  <installDir>${project.build.directory}/tomcat5</installDir>
+                </zipUrlInstaller>
+              </container>
+              <configuration>
+                <home>${project.build.directory}/tomcat5/container</home>
+              </configuration>
+            </configuration>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Attribute.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Attribute.java
new file mode 100644
index 0000000..1c393a0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Attribute.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+
+public class Attribute implements Serializable {
+
+  private int counter;
+  private boolean condition;
+
+  public void resetCounter() {
+    counter = 0;
+  }
+
+  public void reload() {
+    counter++;
+  }
+
+  public int getCounter() {
+    return counter;
+  }
+
+  public void setCounter(final int counter) {
+    this.counter = counter;
+  }
+
+  public boolean isCondition() {
+    return condition;
+  }
+
+  public void setCondition(final boolean condition) {
+    this.condition = condition;
+  }
+  
+  public String getValue() {
+    return "value from model";
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Bootstrap.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Bootstrap.java
new file mode 100644
index 0000000..71e441f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Bootstrap.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class Bootstrap {
+
+  private String value;
+
+  public Bootstrap() {
+    reset();
+  }
+
+  public String save() {
+    return "test/html/bootstrap.xhtml";
+  }
+
+  public String delete() {
+    value = null;
+    return "test/html/bootstrap.xhtml";
+  }
+
+  public String reset() {
+    value = "initial value";
+    return "test/html/bootstrap.xhtml";
+  }
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(final String value) {
+    this.value = value;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ClientConfigController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ClientConfigController.java
new file mode 100644
index 0000000..2cd50b5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ClientConfigController.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.config.TobagoConfig;
+import org.apache.myfaces.tobago.context.Theme;
+import org.apache.myfaces.tobago.context.TobagoContext;
+import org.apache.myfaces.tobago.internal.util.ObjectUtils;
+
+import javax.faces.application.Application;
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+public class ClientConfigController implements Serializable {
+
+  private Theme theme;
+  private SelectItem[] themeItems;
+
+  private Locale locale;
+
+  public ClientConfigController() {
+
+    // theme
+
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final TobagoConfig tobagoConfig = TobagoConfig.getInstance(facesContext);
+
+    final List<Theme> themes = new ArrayList<Theme>(tobagoConfig.getSupportedThemes());
+    themes.add(0, tobagoConfig.getDefaultTheme());
+    themeItems = new SelectItem[themes.size()];
+    for (int i = 0; i < themeItems.length; i++) {
+      final Theme themeItem = themes.get(i);
+      themeItems[i] = new SelectItem(themeItem, themeItem.getDisplayName());
+    }
+
+    // locale
+
+    locale = facesContext.getViewRoot().getLocale();
+
+    // load
+
+    loadFromClientProperties();
+  }
+
+  public String submit() {
+    storeInClientProperties();
+    return "navigation";
+  }
+
+// ///////////////////////////////////////////// logic
+
+  public void storeInClientProperties() {
+    TobagoContext.getInstance(FacesContext.getCurrentInstance()).setTheme(theme);
+  }
+
+  public void loadFromClientProperties() {
+    theme = TobagoContext.getInstance(FacesContext.getCurrentInstance()).getTheme();
+  }
+
+  public List<SelectItem> getLocaleItems() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    final Application application = facesContext.getApplication();
+    final Locale defaultLocale = application.getDefaultLocale();
+    final Iterator supportedLocales = application.getSupportedLocales();
+
+    boolean defaultInList = false;
+    final List<SelectItem> localeItems = new ArrayList<SelectItem>();
+    while (supportedLocales.hasNext()) {
+      final Locale locale = (Locale) supportedLocales.next();
+      localeItems.add(createLocaleItem(locale));
+      if (locale.equals(defaultLocale)) {
+        defaultInList = true;
+      }
+    }
+    // If the default is already in the list, don't add it.
+    // Background: Must the default be in the supported list? Yes or No?
+    // This question is not specified explicit and different implemented in the RI and MyFaces
+    if (!defaultInList && defaultLocale != null) {
+      localeItems.add(0, createLocaleItem(defaultLocale));
+    }
+    return localeItems;
+  }
+
+  private SelectItem createLocaleItem(final Locale localeItem) {
+    if (locale != null) {
+      return new SelectItem(localeItem, localeItem.getDisplayName(locale));
+    } else {
+      return new SelectItem(localeItem, localeItem.getDisplayName(localeItem));
+    }
+  }
+
+  public Theme getTheme() {
+    return theme;
+  }
+
+  public String getLocalizedTheme() {
+    for (int i = 0; i < themeItems.length; i++) {
+      final SelectItem themeItem = themeItems[i];
+      if (ObjectUtils.equals(themeItem.getValue(), theme)) {
+        return themeItem.getLabel();
+      }
+    }
+    return "???";
+  }
+
+  public void setTheme(final Theme theme) {
+    this.theme = theme;
+  }
+
+  public SelectItem[] getThemeItems() {
+    return themeItems;
+  }
+
+  public void setThemeItems(final SelectItem[] themeItems) {
+    this.themeItems = themeItems;
+  }
+
+  public Locale getLocale() {
+    return locale;
+  }
+
+  public String getLocalizedLocale() {
+    if (locale != null) {
+      return locale.getDisplayName(locale);
+    } else{
+      return null;
+    }
+  }
+
+  public void setLocale(final Locale locale) {
+    this.locale = locale;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DateController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DateController.java
new file mode 100644
index 0000000..a22c97f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DateController.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+public class DateController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DateController.class);
+
+  private Date once;
+
+  public DateController() {
+    try {
+      once = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS").parse("1980-03-07 21:05:09 012");
+    } catch (ParseException e) {
+      LOG.error("should not happen. ", e);
+    }
+  }
+
+  public Date getOnce() {
+    return once;
+  }
+
+  public void setOnce(Date once) {
+    this.once = once;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DirectoryBrowser.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DirectoryBrowser.java
new file mode 100644
index 0000000..a2b1018
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DirectoryBrowser.java
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.servlet.ServletContext;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+public class DirectoryBrowser implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(DirectoryBrowser.class);
+
+  private PageItem tree;
+  private PageItem current;
+
+  public DirectoryBrowser() {
+    tree = new PageItem("/", false, false);
+    final ServletContext servletContext
+        = (ServletContext) FacesContext.getCurrentInstance().getExternalContext().getContext();
+
+    locateResourcesInWar(tree, servletContext);
+    current = tree;
+  }
+
+  private void locateResourcesInWar(final PageItem node, final ServletContext servletContext) {
+
+    String path = node.getName();
+
+    // fix for jetty6
+    if (path.endsWith("/") && path.length() > 1) {
+      path = path.substring(0, path.length() - 1);
+    }
+    final Set<String> resourcePaths = servletContext.getResourcePaths(path);
+    if (resourcePaths == null || resourcePaths.isEmpty()) {
+      if (LOG.isDebugEnabled()) {
+        LOG.debug("Skipping empty resource path: path='" + path + "'");
+      }
+      return;
+    }
+
+    final List<PageItem> list = new ArrayList<PageItem>();
+
+    for (final String childPath : resourcePaths) {
+      if (childPath.endsWith("/")) {
+        // ignore, because weblogic puts the path directory itself in the Set
+        if (!childPath.equals(path)) {
+          if (TestPageFilter.isValid(childPath)) {
+            if (LOG.isDebugEnabled()) {
+              LOG.debug("childPath dir " + childPath);
+            }
+            list.add(new PageItem(childPath, TestPageFilter.isDisabled(childPath), TestPageFilter.isTodo(childPath)));
+          }
+        }
+      } else {
+        if (TestPageFilter.isValid(childPath)) {
+          LOG.info("add resc " + childPath);
+          list.add(new PageItem(childPath, TestPageFilter.isDisabled(childPath), TestPageFilter.isTodo(childPath)));
+        }
+      }
+    }
+
+    Collections.sort(list);
+
+    for (final PageItem pageItem : list) {
+      node.add(pageItem);
+
+      if (pageItem.isFolder()) {
+        locateResourcesInWar(pageItem, servletContext);
+      }
+    }
+  }
+
+  public PageItem getTree() {
+    return tree;
+  }
+
+  public PageItem getCurrent() {
+    return current;
+  }
+
+  public void setCurrent(final PageItem current) {
+    this.current = current;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicBean.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicBean.java
new file mode 100644
index 0000000..2560576
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicBean.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class DynamicBean implements Serializable {
+
+  private List<DynamicPanel> panels = new ArrayList<DynamicPanel>();
+
+  public String addPanel() {
+
+    switch (panels.size()) {
+      case 0:
+        panels.add(new DynamicPanel1());
+        break;
+      case 1:
+        panels.add(new DynamicPanel2());
+        break;
+      case 2:
+        panels.add(new DynamicPanel3());
+        break;
+      default:
+        FacesContext.getCurrentInstance().addMessage(null,
+            new FacesMessage(FacesMessage.SEVERITY_WARN, "All panels where added!", null));
+    }
+    return "/test/forEach/dynamic-include.xhtml";
+//    return null;
+  }
+
+  public String reset() {
+    panels.clear();
+    return "/test/forEach/dynamic-include.xhtml";
+//    return null;
+  }
+
+  public List<DynamicPanel> getPanels() {
+    return panels;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel.java
new file mode 100644
index 0000000..8d4294c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public abstract class DynamicPanel {
+
+  private static final String[] PANEL_FILES = new String[]{
+      "panel-one-fragment.xhtml",
+      "panel-two-fragment.xhtml",
+      "panel-three-fragment.xhtml"};
+
+  private final String name;
+
+  public DynamicPanel() {
+    final String simpleName = this.getClass().getSimpleName();
+    final int number = Integer.parseInt(simpleName.substring(simpleName.length() - 1)) - 1;
+    this.name = PANEL_FILES[number];
+  }
+
+  public String getName() {
+    return name;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel1.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel1.java
new file mode 100644
index 0000000..a250169
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel1.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class DynamicPanel1 extends DynamicPanel {
+
+  private String value;
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(final String value) {
+    this.value = value;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel2.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel2.java
new file mode 100644
index 0000000..f3a1779
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel2.java
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class DynamicPanel2 extends DynamicPanel {
+
+  private String firstName;
+  private String secondName;
+
+  public String getFirstName() {
+    return firstName;
+  }
+
+  public void setFirstName(final String firstName) {
+    this.firstName = firstName;
+  }
+
+  public String getSecondName() {
+    return secondName;
+  }
+
+  public void setSecondName(final String secondName) {
+    this.secondName = secondName;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel3.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel3.java
new file mode 100644
index 0000000..25d1432
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/DynamicPanel3.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+
+public class DynamicPanel3 extends DynamicPanel implements Serializable {
+
+  private String street;
+  private String city;
+
+  public String getStreet() {
+    return street;
+  }
+
+  public void setStreet(final String street) {
+    this.street = street;
+  }
+
+  public String getCity() {
+    return city;
+  }
+
+  public void setCity(final String city) {
+    this.city = city;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ErrorTest.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ErrorTest.java
new file mode 100644
index 0000000..2f0f572
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ErrorTest.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class ErrorTest {
+
+  public String error() {
+    throw new ErrorTestException("This exception is thrown to test error pages");
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ErrorTestException.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ErrorTestException.java
new file mode 100644
index 0000000..c513318
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ErrorTestException.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class ErrorTestException extends RuntimeException {
+
+  public ErrorTestException(final String message) {
+    super(message);
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Hidden.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Hidden.java
new file mode 100644
index 0000000..cac680a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Hidden.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Hidden {
+
+  private String value1 = "value 1";
+  private String value2 = "value 2";
+  private String value3 = "value 3";
+
+  private static final Logger LOG = LoggerFactory.getLogger(Hidden.class);
+
+  public String getValue1() {
+    return value1;
+  }
+
+  public void setValue1(final String value1) {
+    this.value1 = value1;
+  }
+
+  public String getValue2() {
+    return value2;
+  }
+
+  public void setValue2(final String value2) {
+    this.value2 = value2;
+  }
+
+  public String getValue3() {
+    return value3;
+  }
+
+  public void setValue3(final String value3) {
+    this.value3 = value3;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Immediate.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Immediate.java
new file mode 100644
index 0000000..c46ee05
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Immediate.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.context.FacesContext;
+import javax.faces.model.SelectItem;
+import java.io.Serializable;
+
+public class Immediate implements Serializable {
+
+  private String in;
+  private int selectOne;
+  private Integer[] selectMany;
+
+  private SelectItem[] selectItems = new SelectItem[] {
+        new SelectItem(0, "Zero"),
+        new SelectItem(1, "One"),
+        new SelectItem(2, "Two"),
+        new SelectItem(3, "Tree"),
+        new SelectItem(4, "Four"),
+    };
+
+  private static final Logger LOG = LoggerFactory.getLogger(Immediate.class);
+
+  public String test() {
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+//    LOG.warn("user: " + facesContext.getExternalContext().getRemoteUser().hashCode());
+    LOG.warn("requ: " + facesContext.getExternalContext().getRequest().hashCode());
+    LOG.warn("sess: " + facesContext.getExternalContext().getSessionMap().hashCode());
+    return null;
+  }
+  
+  public String getIn() {
+    return in;
+  }
+
+  public void setIn(final String in) {
+    this.in = in;
+  }
+
+  public int getSelectOne() {
+    return selectOne;
+  }
+
+  public void setSelectOne(final int selectOne) {
+    this.selectOne = selectOne;
+  }
+
+  public SelectItem[] getSelectItems() {
+    return selectItems;
+  }
+
+  public void setSelectMany(final Integer[] selectMany) {
+    this.selectMany = selectMany;
+  }
+
+  public Integer[] getSelectMany() {
+    return selectMany;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/InBean.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/InBean.java
new file mode 100644
index 0000000..e5e1f9a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/InBean.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+
+public class InBean implements Serializable {
+
+  private String first;
+
+  private String second;
+
+  public String getFirst() {
+    return first;
+  }
+
+  public void setFirst(final String first) {
+    this.first = first;
+  }
+
+  public String getSecond() {
+    return second;
+  }
+
+  public void setSecond(final String second) {
+    this.second = second;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/InputSuggestController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/InputSuggestController.java
new file mode 100644
index 0000000..c87b665
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/InputSuggestController.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIInput;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class InputSuggestController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(InputSuggestController.class);
+
+  public List<String> inputSuggestItems(final UIInput component) {
+    final String prefix = (String) component.getSubmittedValue();
+    LOG.info("Creating items for prefix :\"" + prefix + "\"");
+    final List<String> li = new ArrayList<String>();
+    li.add(prefix + 1);
+    li.add(prefix + 2);
+    li.add(prefix + 3);
+    li.add(prefix + 4);
+    li.add(prefix + 5);
+    li.add(prefix + 6);
+    return li;
+  }
+  
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/KillSession.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/KillSession.java
new file mode 100644
index 0000000..c94430a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/KillSession.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+public class KillSession extends HttpServlet {
+
+  @Override
+  protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+      throws ServletException, IOException {
+    final HttpSession session = request.getSession(false);
+    if (session != null) {
+       session.invalidate();
+    }
+    response.getOutputStream().write("session killed".getBytes());
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/MeasureBean.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/MeasureBean.java
new file mode 100644
index 0000000..d5b5bd1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/MeasureBean.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.layout.Measure;
+
+public class MeasureBean {
+
+  public int getIntWidth() {
+    return 200;
+  }
+
+  public int getIntHeight() {
+    return 95;
+  }
+
+  public Integer getIntegerWidth() {
+    return 250;
+  }
+
+  public Integer getIntegerHeight() {
+    return 95;
+  }
+
+  public Measure getMeasureWidth() {
+    return Measure.valueOf(300);
+  }
+
+  public Measure getMeasureHeight() {
+    return Measure.valueOf(95);
+  }
+
+  public String getStringWidth() {
+    return "350";
+  }
+
+  public String getStringHeight() {
+    return "95";
+  }
+
+  public String getStringPxWidth() {
+    return "400px";
+  }
+
+  public String getStringPxHeight() {
+    return "95px";
+  }
+
+  public long getLongWidth() {
+    return 450L;
+  }
+
+  public long getLongHeight() {
+    return 95L;
+  }
+
+  public Any getAnyWidth() {
+    return new Any("500");
+  }
+
+  public Any getAnyHeight() {
+    return new Any("95");
+  }
+
+  public static class Any {
+    
+    private String value;
+
+    public Any(final String value) {
+      this.value = value;
+    }
+
+    @Override
+    public String toString() {
+      return value;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Messages.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Messages.java
new file mode 100644
index 0000000..4cb1dee
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Messages.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import java.io.Serializable;
+
+public class Messages implements Serializable {
+
+  public String createMessages() {
+
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+    facesContext.addMessage("message1",
+        new FacesMessage(FacesMessage.SEVERITY_INFO, "Info message.", "Example of an info message."));
+    facesContext.addMessage(null,
+        new FacesMessage(FacesMessage.SEVERITY_WARN, "Warn message.", "Example of a warn message."));
+    facesContext.addMessage(null,
+        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Error message.", "Example of an error message."));
+    facesContext.addMessage(null,
+        new FacesMessage(FacesMessage.SEVERITY_FATAL, "Fatal message.", "Example of a fatal message."));
+    facesContext.addMessage(null,
+        new FacesMessage("Message without a severity.", "Example of a message without a severity."));
+
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PageItem.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PageItem.java
new file mode 100644
index 0000000..2c6a067
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PageItem.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.context.Markup;
+import org.apache.myfaces.tobago.util.VariableResolverUtils;
+
+import javax.faces.context.FacesContext;
+import javax.swing.tree.DefaultMutableTreeNode;
+
+
+public class PageItem extends DefaultMutableTreeNode implements Comparable {
+
+  private String name;
+  private String label;
+  private boolean folder;
+  private boolean disabled;
+  private boolean todo;
+
+  public PageItem(final String name, final boolean disabled, final boolean todo) {
+    this.name = name;
+    folder = name.endsWith("/");
+
+    label = name;
+    if (folder && label.length() > 1) {
+      label = label.substring(0, label.length() - 1);
+    }
+    label = label.substring(label.lastIndexOf("/") + 1);
+//    label = label.replaceAll("_", "__");
+    this.disabled = disabled;
+    this.todo = todo;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public String getLabel() {
+    return label;
+  }
+
+  @Override
+  public int compareTo(final Object object) {
+    return label.compareTo(((PageItem) object).label);
+  }
+
+  public boolean isFolder() {
+    return folder;
+  }
+
+  public boolean isDisabled() {
+    return disabled;
+  }
+
+  public Markup getMarkup() {
+    if (todo) {
+      return Markup.valueOf("todo");
+    } else {
+      return null;
+    }
+  }
+
+  public String navigate() {
+    final DirectoryBrowser browser =
+        (DirectoryBrowser) VariableResolverUtils.resolveVariable(FacesContext.getCurrentInstance(), "browser");
+    browser.setCurrent(this);
+    return null; // here it works, but return null is usually not a good idea.
+  }
+
+  @Override
+  public String toString() {
+    return name;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Partially.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Partially.java
new file mode 100644
index 0000000..80fdd85
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Partially.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+
+public class Partially implements Serializable {
+
+  private int counter;
+
+  private String characters;
+
+  public Partially() {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("test_characters = [ ");
+    for (char c = 0; c < 0x24F; c++) {
+
+      builder.append('\'');
+      if (c == '\'' || c == '\\' || c == '\n' || c == '\r') { // to have a valid JavaScript string.
+        builder.append('\\');
+      }
+      builder.append(c);
+      builder.append("\', ");
+      if (c % 16 == 15) {
+        builder.append("\n");
+      }
+    }
+    builder.append("];");
+    characters = builder.toString();
+  }
+
+  public void resetCounter() {
+    counter = 0;
+  }
+
+  public void reload() {
+    counter++;
+  }
+
+  public int getCounter() {
+    return counter;
+  }
+
+  public void setCounter(final int counter) {
+    this.counter = counter;
+  }
+
+  public String getCharacters() {
+    return characters;
+  }
+
+  public void setCharacters(final String characters) {
+    this.characters = characters;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupData.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupData.java
new file mode 100644
index 0000000..5e3219d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupData.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class PopupData {
+
+  private String value;
+
+  public String getValue() {
+    return value;
+  }
+
+  public void setValue(final String value) {
+    this.value = value;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupModalAttribute.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupModalAttribute.java
new file mode 100644
index 0000000..06f79fb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupModalAttribute.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class PopupModalAttribute {
+
+  public boolean isAlwaysTrue() {
+    return true;
+  }
+
+  public boolean isAlwaysFalse() {
+    return false;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupReferenceController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupReferenceController.java
new file mode 100644
index 0000000..f981545
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/PopupReferenceController.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.myfaces.tobago.component.UISheet;
+
+import javax.faces.component.UIComponent;
+import javax.faces.event.ActionEvent;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PopupReferenceController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(PopupReferenceController.class);
+
+  private Entry entry;
+
+  private List<Entry> sheet;
+
+
+  public PopupReferenceController() {
+    sheet = new ArrayList<Entry>();
+    for (int i = 0; i < 10; i++) {
+      final Entry tmp = new Entry();
+      tmp.setColumn1("cell__1__" + i);
+      tmp.setColumn2("cell_2_" + i);
+      tmp.setColumn3("cell_3_" + i);
+      sheet.add(tmp);
+    }
+  }
+
+  public void selectEntry(final ActionEvent event) {
+    UIComponent component = event.getComponent();
+    while (!(component instanceof UISheet)) {
+      component = component.getParent();
+    }
+
+    final UISheet sheet = (UISheet) component;
+    entry = (Entry) sheet.getRowData();
+    LOG.info("entry = \"" + entry.getColumn1() + "\"");
+  }
+
+  public void saveChanges(final ActionEvent event) {
+    LOG.info("saveChanges()");
+    // nothing to do here
+  }
+
+
+  public List<Entry> getSheet() {
+    return sheet;
+  }
+
+  public Entry getEntry() {
+    return entry;
+  }
+
+  public void setEntry(final Entry entry) {
+    this.entry = entry;
+  }
+
+  public static class Entry{
+    private String column1;
+    private String column2;
+    private String column3;
+
+    public String getColumn1() {
+      return column1;
+    }
+
+    public void setColumn1(final String column1) {
+      this.column1 = column1;
+    }
+
+    public String getColumn2() {
+      return column2;
+    }
+
+    public void setColumn2(final String column2) {
+      this.column2 = column2;
+    }
+
+    public String getColumn3() {
+      return column3;
+    }
+
+    public void setColumn3(final String column3) {
+      this.column3 = column3;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Progress.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Progress.java
new file mode 100644
index 0000000..d8bea33
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Progress.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import javax.swing.BoundedRangeModel;
+import javax.swing.DefaultBoundedRangeModel;
+import java.io.Serializable;
+
+public class Progress implements Serializable {
+
+  private BoundedRangeModel range;
+  private BoundedRangeModel emptyRange;
+
+  public Progress() {
+    this.range = new DefaultBoundedRangeModel(60, 0, 0, 100);
+    this.emptyRange = new DefaultBoundedRangeModel(0, 0, 0, 0);
+  }
+
+  public BoundedRangeModel getRange() {
+    return range;
+  }
+
+  public BoundedRangeModel getEmptyRange() {
+    return emptyRange;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Reload.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Reload.java
new file mode 100644
index 0000000..e3e7c2e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Reload.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+
+public class Reload implements Serializable {
+  
+  private int counter;
+
+  public boolean isReload() {
+    counter++;
+    return true;
+  }
+  
+  public String tick() {
+    counter++;
+    return null;
+  }
+
+  public String reset() {
+    counter = 0;
+    return null;
+  }
+
+  public boolean isOnlyEven() {
+    counter++;
+    return counter % 2 == 0;
+  }
+
+  public int getCounter() {
+    return counter;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceBean.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceBean.java
new file mode 100644
index 0000000..a657dda
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceBean.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import javax.faces.context.FacesContext;
+import java.util.Arrays;
+import java.util.List;
+
+public class ResourceBean {
+
+  private List<ResourceEntry> resources;
+  private int fails;
+
+  public ResourceBean() {
+    if (resources == null) {
+      final FacesContext facesContext = FacesContext.getCurrentInstance();
+
+      resources = Arrays.asList(
+          new ResourceEntry(
+              "data/sun-behind-mountains.jpg",
+              ResourceType.IMAGE,
+              "comes from JAR (tobago-example-data): META-INF/resources"),
+          new ResourceEntry(
+              "non-existing.jpg",
+              ResourceType.IMAGE,
+              "should fail"),
+          new ResourceEntry(
+              "image/date.png",
+              ResourceType.IMAGE,
+              "comes from JAR (tobago-theme-speyside)"),
+          new ResourceEntry(
+              "image/wait/cat.jpg",
+              ResourceType.IMAGE,
+              "comes from the WAR directly"),
+          new ResourceEntry(
+              "tobago",
+              "configTheme",
+              ResourceType.PROPERTY,
+              "comes from the theme (tobago-theme-scarborough)"),
+          new ResourceEntry(
+              "tobago",
+              "not-existing",
+              ResourceType.PROPERTY,
+              "should fail")
+      );
+
+      for (final ResourceEntry resource : resources) {
+        if (!resource.check(facesContext)) {
+          fails++;
+        }
+      }
+    }
+  }
+
+  public List<ResourceEntry> getResultList() {
+    return resources;
+  }
+
+  public int getFails() {
+    return fails;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceEntry.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceEntry.java
new file mode 100644
index 0000000..4843e91
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceEntry.java
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import javax.faces.context.FacesContext;
+
+public class ResourceEntry {
+
+  private String name;
+  private String key;
+  private ResourceType type;
+  private boolean valid;
+  private String comment;
+
+  public ResourceEntry(final String name, final ResourceType type, final String comment) {
+    this.name = name;
+    this.type = type;
+    this.comment = comment;
+    assert type == ResourceType.IMAGE;
+  }
+
+  public ResourceEntry(final String name, final String key, final ResourceType type, final String comment) {
+    this.name = name;
+    this.key = key;
+    this.type = type;
+    this.comment = comment;
+    assert type == ResourceType.PROPERTY;
+  }
+
+  public boolean check(final FacesContext facesContext) {
+/*
+    switch (type) {
+      case IMAGE:
+        valid = ResourceManagerUtils.getImageWithPath(facesContext, name) != null;
+        break;
+      case PROPERTY:
+        valid = ResourceManagerUtils.getProperty(facesContext, name, key) != null;
+        break;
+      default:
+        throw new IllegalArgumentException("Unknown type " + type);
+    }
+    return valid;
+*/
+    //XXX RM
+
+    return true;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public ResourceType getType() {
+    return type;
+  }
+
+  public void setType(final ResourceType type) {
+    this.type = type;
+  }
+
+  public boolean isValid() {
+    return valid;
+  }
+
+  public void setValid(final boolean valid) {
+    this.valid = valid;
+  }
+
+  public String getComment() {
+    return comment;
+  }
+
+  public void setComment(final String comment) {
+    this.comment = comment;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceType.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceType.java
new file mode 100644
index 0000000..b275c78
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ResourceType.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public enum ResourceType {
+  IMAGE,
+  PROPERTY
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEvent.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEvent.java
new file mode 100644
index 0000000..f634e59
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEvent.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ScriptEvent implements Serializable {
+
+  private List<ScriptEventItem> items = new ArrayList<ScriptEventItem>();
+
+  public void onLoad() {
+    items.add(new ScriptEventItem("onload"));
+  }
+
+  public void onUnload() {
+    items.add(new ScriptEventItem("onunload"));
+  }
+
+  public void onExit() {
+    items.add(new ScriptEventItem("onexit"));
+  }
+
+  public String action() {
+    items.add(new ScriptEventItem("action"));
+    return null;
+  }
+
+  public List<ScriptEventItem> getItems() {
+    return items;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEventItem.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEventItem.java
new file mode 100644
index 0000000..18a6333
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEventItem.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Date;
+
+public class ScriptEventItem {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ScriptEventItem.class);
+
+  private String name;
+  private Date time;
+
+  public ScriptEventItem(final String name) {
+    this.name = name;
+    this.time = new Date();
+    LOG.info(name);
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public Date getTime() {
+    return time;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEventServlet.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEventServlet.java
new file mode 100644
index 0000000..3c9b6bd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ScriptEventServlet.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import java.io.IOException;
+
+public class ScriptEventServlet extends HttpServlet {
+
+  private static final Logger LOG = LoggerFactory.getLogger(ScriptEventServlet.class);
+
+  @Override
+  protected void doGet(final HttpServletRequest request, final HttpServletResponse response)
+      throws ServletException, IOException {
+    final HttpSession session = request.getSession(false);
+    if (session != null) {
+      final ScriptEvent scriptEvent = (ScriptEvent) session.getAttribute("scriptEvent");
+      if (scriptEvent != null) {
+        final String event = request.getParameter("event");
+        if (event.equals("onload")) {
+          scriptEvent.onLoad();
+        } else if (event.equals("onunload")) {
+          scriptEvent.onUnload();
+        } else if (event.equals("onexit")) {
+          scriptEvent.onExit();
+        } else {
+          LOG.warn("Unknown event");
+        }
+      }
+    }
+    response.getOutputStream().write("done".getBytes());
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SelectBooleanCheckboxBean.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SelectBooleanCheckboxBean.java
new file mode 100644
index 0000000..ce259c0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SelectBooleanCheckboxBean.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+
+public class SelectBooleanCheckboxBean implements Serializable {
+  
+  private boolean value00 = true;
+  private boolean value01 = true;
+  private boolean value02 = true;
+  private boolean value10 = true;
+  private boolean value11 = true;
+  private boolean value12 = true;
+
+  public boolean isValue0() {
+    return value00;
+  }
+
+  public void setValue0(final boolean value00) {
+    this.value00 = value00;
+  }
+
+  public boolean isValue1() {
+    return value01;
+  }
+
+  public void setValue1(final boolean value01) {
+    this.value01 = value01;
+  }
+
+  public boolean isValue2() {
+    return value02;
+  }
+
+  public void setValue2(final boolean value02) {
+    this.value02 = value02;
+  }
+
+  public boolean isRequired0() {
+    return value10;
+  }
+
+  public void setRequired0(final boolean value10) {
+    this.value10 = value10;
+  }
+
+  public boolean isRequired1() {
+    return value11;
+  }
+
+  public void setRequired1(final boolean value11) {
+    this.value11 = value11;
+  }
+
+  public boolean isRequired2() {
+    return value12;
+  }
+
+  public void setRequired2(final boolean value12) {
+    this.value12 = value12;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SelectManyListboxBean.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SelectManyListboxBean.java
new file mode 100644
index 0000000..69b318d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SelectManyListboxBean.java
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Currency;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+public class SelectManyListboxBean implements Serializable {
+
+  private List<String> stringList;
+  private String[] stringArray;
+  private Set<String> stringSet = new HashSet<String>();
+  private Collection<String> stringCollection = new LinkedList<String>();
+
+  private List<Currency> currencyList;
+  private Currency[] currencyArray;
+  private Set<Currency> currencySet = new HashSet<Currency>();
+  private Collection<Currency> currencyCollection = new LinkedList<Currency>();
+
+  private Currency[] currencyItems;
+
+  public SelectManyListboxBean() {
+    currencyItems = new Currency[]{
+        Currency.getInstance("JPY"),
+        Currency.getInstance("TTD"),
+        Currency.getInstance("USD"),
+        Currency.getInstance("EUR")
+    };
+  }
+
+  public List<String> getStringList() {
+    return stringList;
+  }
+
+  public void setStringList(final List<String> stringList) {
+    this.stringList = stringList;
+  }
+
+  public String[] getStringArray() {
+    return stringArray;
+  }
+
+  public void setStringArray(final String[] stringArray) {
+    this.stringArray = stringArray;
+  }
+
+  public Set<String> getStringSet() {
+    return stringSet;
+  }
+
+  public void setStringSet(final Set<String> stringSet) {
+    this.stringSet = stringSet;
+  }
+
+  public Collection<String> getStringCollection() {
+    return stringCollection;
+  }
+
+  public void setStringCollection(final Collection<String> stringCollection) {
+    this.stringCollection = stringCollection;
+  }
+
+  public List<Currency> getCurrencyList() {
+    return currencyList;
+  }
+
+  public void setCurrencyList(final List<Currency> currencyList) {
+    this.currencyList = currencyList;
+  }
+
+  public Currency[] getCurrencyArray() {
+    return currencyArray;
+  }
+
+  public void setCurrencyArray(final Currency[] currencyArray) {
+    this.currencyArray = currencyArray;
+  }
+
+  public Set<Currency> getCurrencySet() {
+    return currencySet;
+  }
+
+  public void setCurrencySet(final Set<Currency> currencySet) {
+    this.currencySet = currencySet;
+  }
+
+  public Collection<Currency> getCurrencyCollection() {
+    return currencyCollection;
+  }
+
+  public void setCurrencyCollection(final Collection<Currency> currencyCollection) {
+    this.currencyCollection = currencyCollection;
+  }
+
+  public Currency[] getCurrencyItems() {
+    return currencyItems;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SheetController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SheetController.java
new file mode 100644
index 0000000..c2f2377
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SheetController.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.example.data.LocaleEntry;
+import org.apache.myfaces.tobago.example.data.LocaleList;
+import org.apache.myfaces.tobago.example.data.SolarObject;
+
+import javax.faces.model.DataModel;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SheetController implements Serializable {
+
+  private SolarObject[] solarArray = SolarObject.getArray();
+  private SolarObject[] solarArray3 = init3();
+  private DataModel undefined = new UndefinedRowCountDataModel(solarArray);
+
+  public SheetController() {
+    init3();
+  }
+
+  private SolarObject[] init3() {
+    final SolarObject[] help = new SolarObject[3];
+    for (int i = 0; i < 3; i++) {
+      help[i] = solarArray[i];
+    }
+    return help;
+  }
+
+  // Create a copy for sorting, because the LocaleList.DATA is not modifiable.
+  private List<LocaleEntry> localeList = new ArrayList<LocaleEntry>(LocaleList.DATA);
+
+  public SolarObject[] getSolarArray() {
+    return solarArray;
+  }
+
+  public SolarObject[] getSolarArray3() {
+    return solarArray3;
+  }
+
+  public List<LocaleEntry> getLocaleList() {
+    return localeList;
+  }
+
+  public DataModel getUndefined() {
+    return undefined;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SheetSortController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SheetSortController.java
new file mode 100644
index 0000000..4538ffd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/SheetSortController.java
@@ -0,0 +1,141 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class SheetSortController implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SheetSortController.class);
+
+  private List<Entry> list;
+
+  public SheetSortController() {
+    init();
+  }
+
+  private void init() {
+    list = new ArrayList<Entry>();
+    for (int i = 0; i < 26; i++) {
+      list.add(new Entry(i));
+    }
+  }
+
+  public List<Entry> getList() {
+    return list;
+  }
+
+  public static final class Entry {
+    
+    private String first;
+    private String second;
+    private String third;
+    private String fourth;
+    private Date fifth;
+    private String sixth;
+
+    private Entry(int i) {
+      this.first = "" + upper(i);
+      i++;
+      this.second = "" + upper(i) + lower(i);
+      i++;
+      this.third = "" + upper(i) + lower(i) + lower(i);
+      i++;
+      this.fourth = "" + upper(i) + lower(i) + lower(i) + lower(i);
+      i++;
+      final String dateString = "2012-02-" + i % 26;
+      try {
+        final SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.UK);
+        simpleDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
+        this.fifth = simpleDateFormat.parse(dateString);
+      } catch (final ParseException e) {
+        LOG.error("string=" + dateString, e);
+      }
+      i++;
+      this.sixth = "" + upper(i) + lower(i) + lower(i) + lower(i) + lower(i);
+    }
+    
+    private char upper(final int i) {
+      return (char) (i % 26 + 'A');
+    }
+
+    private char lower(final int i) {
+      return (char) (i % 26 + 'a');
+    }
+
+    public String getFirst() {
+      return first;
+    }
+
+    public void setFirst(final String first) {
+      this.first = first;
+    }
+
+    public String getSecond() {
+      return second;
+    }
+
+    public void setSecond(final String second) {
+      this.second = second;
+    }
+
+    public String getThird() {
+      return third;
+    }
+
+    public void setThird(final String third) {
+      this.third = third;
+    }
+
+    public String getFourth() {
+      return fourth;
+    }
+
+    public void setFourth(final String fourth) {
+      this.fourth = fourth;
+    }
+
+    public Date getFifth() {
+      return fifth;
+    }
+
+    public void setFifth(final Date fifth) {
+      this.fifth = fifth;
+    }
+
+    public String getSixth() {
+      return sixth;
+    }
+
+    public void setSixth(final String sixth) {
+      this.sixth = sixth;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Shuttle.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Shuttle.java
new file mode 100644
index 0000000..aa8f1aa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Shuttle.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Shuttle implements Serializable {
+
+  private List<String> value;
+
+  public Shuttle() {
+    this.value = new ArrayList<String>();
+  }
+
+  public List<String> getValue() {
+    return value;
+  }
+
+  public void setValue(final List<String> value) {
+    this.value = value;
+  }
+
+  public String getResult() {
+    return StringUtils.joinWithSurroundingSeparator(value).substring(1, Math.max(value.size() * 2, 1));
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestExceptionHandler.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestExceptionHandler.java
new file mode 100644
index 0000000..623f5da
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestExceptionHandler.java
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.commons.lang.exception.ExceptionUtils;
+
+import javax.faces.FacesException;
+import javax.faces.application.FacesMessage;
+import javax.faces.application.NavigationHandler;
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerWrapper;
+import javax.faces.context.FacesContext;
+import javax.faces.event.ExceptionQueuedEvent;
+import javax.faces.event.ExceptionQueuedEventContext;
+import java.util.Iterator;
+
+public class TestExceptionHandler extends ExceptionHandlerWrapper {
+
+  private ExceptionHandler wrapped;
+
+  public TestExceptionHandler(final ExceptionHandler wrapped) {
+    this.wrapped = wrapped;
+  }
+
+  @Override
+  public ExceptionHandler getWrapped() {
+    return wrapped;
+  }
+
+  @Override
+  public void handle() throws FacesException {
+
+    final Iterator<ExceptionQueuedEvent> iterator = getUnhandledExceptionQueuedEvents().iterator();
+    while (iterator.hasNext()) {
+      final ExceptionQueuedEvent event = iterator.next();
+      final ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();
+      final Throwable cause = ExceptionUtils.getRootCause(context.getException());
+      if (cause instanceof ErrorTestException) {
+        final FacesContext facesContext = FacesContext.getCurrentInstance();
+        final NavigationHandler nav = facesContext.getApplication().getNavigationHandler();
+        try {
+          facesContext.addMessage(null, new FacesMessage("The expected exception was thrown!"));
+          nav.handleNavigation(facesContext, null, "/test/error/display-exception.xhtml");
+          facesContext.renderResponse();
+        } finally {
+          iterator.remove();
+        }
+      }
+    }
+    getWrapped().handle();
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestExceptionHandlerFactory.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestExceptionHandlerFactory.java
new file mode 100644
index 0000000..b9d212a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestExceptionHandlerFactory.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import javax.faces.context.ExceptionHandler;
+import javax.faces.context.ExceptionHandlerFactory;
+
+public class TestExceptionHandlerFactory extends ExceptionHandlerFactory {
+
+  private ExceptionHandlerFactory parent;
+
+  public TestExceptionHandlerFactory(final ExceptionHandlerFactory parent) {
+    this.parent = parent;
+  }
+
+  @Override
+  public ExceptionHandler getExceptionHandler() {
+    ExceptionHandler result = parent.getExceptionHandler();
+    result = new TestExceptionHandler(result);
+    return result;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestPageFilter.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestPageFilter.java
new file mode 100644
index 0000000..50ea7eb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TestPageFilter.java
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+public class TestPageFilter {
+
+  public static final List<String> ALLOWED = Arrays.asList(
+      ".*\\/",
+      ".*\\.xhtml",
+      ".*\\.html"
+  );
+
+  public static final Set<String> HIDDEN = new HashSet<String>(Arrays.asList(
+      "/META-INF/.*",
+      "/WEB-INF/.*",
+      "/script/.*",
+      "/style/.*",
+      "/org/.*",
+      "/src/.*",
+      ".*/\\.svn/.*",
+      ".*\\.selenium\\.html",
+      "/javax\\.faces/.*",
+      "/oam\\.custom\\..*",
+      "/org\\.apache\\.myfaces/.*",
+      "/org\\.apache\\.myfaces\\.custom/.*"
+  ));
+
+  /**
+   * Internal pages and pages that are impossible to run.
+   */
+  public static final Set<String> DISABLED = new HashSet<String>(Arrays.asList(
+      ".*-fragment\\.xhtml", // intern
+
+      "/index.html", // intern
+      "/navigation.*", // intern
+
+      "/404.*", // meta test
+      "/500.*", // meta test
+
+      "/meta-test/meta-1.*", // meta test
+      "/meta-test/meta-3.*\\.xhtml", // meta test
+      "/meta-test/meta-4.*", // meta test
+      "/meta-test/meta-5.*", // meta test
+
+      "/test/button/plain.html", // intern
+      "/test/button/plain_de.html" // intern
+  ));
+
+  /**
+   * Switched off temporary.
+   */
+  private static final Set<String> TODO = new HashSet<String>(Arrays.asList(
+      "/test/gridLayout/scrolling-2-levels.*", // todo: ?
+      "/test/gridLayout/scrolling-tab.*", // todo: measurement problem with firefox?
+      "/test/treeListbox/*", // todo
+      "/test/label/label-tx.xhtml" // todo see TOBAGO-993
+  ));
+
+  public static boolean isValid(final String name) {
+
+    // 1st all has to start with a '/' slash
+
+    if (!name.startsWith("/")) {
+      return false;
+    }
+
+    // 2nd the positive check
+
+    boolean matches = false;
+    for (final String allowed : ALLOWED) {
+      if (name.matches(allowed)) {
+        matches = true;
+      }
+    }
+    if (!matches) {
+      return false;
+    }
+
+    // 3rd the negative check
+
+    for (final String hidden : HIDDEN) {
+      if (name.matches(hidden)) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  public static boolean isDisabled(final String name) {
+    for (final String disabled : DISABLED) {
+      if (name.matches(disabled)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+  public static boolean isTodo(final String name) {
+    for (final String todo : TODO) {
+      if (name.matches(todo)) {
+        return true;
+      }
+    }
+
+    return false;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Tobago1041.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Tobago1041.java
new file mode 100644
index 0000000..a8e95cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Tobago1041.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.myfaces.tobago.internal.component.AbstractUISelectBooleanCheckbox;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+
+public class Tobago1041 {
+
+  public String getHackFacesMessages() {
+
+    final FacesContext facesContext = FacesContext.getCurrentInstance();
+
+    createMessage(facesContext, "page:literal-tc-both");
+    createMessage(facesContext, "page:literal-tc-item");
+    createMessage(facesContext, "page:literal-tc-label");
+    createMessage(facesContext, "page:literal-tc-no");
+
+    createMessage(facesContext, "page:literal-tx-both");
+    createMessage(facesContext, "page:literal-tx-item");
+    createMessage(facesContext, "page:literal-tx-label");
+    createMessage(facesContext, "page:literal-tx-no");
+
+    createMessage(facesContext, "page:expression-tc-both");
+    createMessage(facesContext, "page:expression-tc-item");
+    createMessage(facesContext, "page:expression-tc-label");
+    createMessage(facesContext, "page:expression-tc-no");
+
+    createMessage(facesContext, "page:expression-tx-both");
+    createMessage(facesContext, "page:expression-tx-item");
+    createMessage(facesContext, "page:expression-tx-label");
+    createMessage(facesContext, "page:expression-tx-no");
+
+    return "hack";
+  }
+
+  private void createMessage(final FacesContext facesContext, final String id) {
+    String label = ((AbstractUISelectBooleanCheckbox) facesContext.getViewRoot().findComponent(id)).getLabel();
+    if (StringUtils.isBlank(label)) {
+      label = "-";
+    }
+    facesContext.addMessage(id, new FacesMessage(FacesMessage.SEVERITY_ERROR, label, label));
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TreeController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TreeController.java
new file mode 100644
index 0000000..1c79f76
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TreeController.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.example.data.CantorInterval;
+import org.apache.myfaces.tobago.example.data.CategoryTree;
+import org.apache.myfaces.tobago.example.data.SmallTree;
+import org.apache.myfaces.tobago.model.ExpandedState;
+import org.apache.myfaces.tobago.model.SelectedState;
+import org.apache.myfaces.tobago.model.TreeDataModel;
+import org.apache.myfaces.tobago.model.TreeNodeDataModel;
+import org.apache.myfaces.tobago.model.TreeState;
+
+import javax.swing.tree.DefaultMutableTreeNode;
+import java.io.Serializable;
+
+public class TreeController implements Serializable {
+
+  private DefaultMutableTreeNode tree = CategoryTree.createSample();
+
+  private DefaultMutableTreeNode small = SmallTree.createSample();
+  
+  private TreeState state = new TreeState(new ExpandedState(1), new SelectedState());
+
+  private TreeDataModel treeInSheet = new TreeNodeDataModel(tree, false, state.getExpandedState());
+
+  private CantorInterval infinite = new CantorInterval();
+
+  public TreeController() {
+    state.getExpandedState().expand(tree);
+  }
+
+  public DefaultMutableTreeNode getTree() {
+    return tree;
+  }
+
+  public DefaultMutableTreeNode getSmall() {
+    return small;
+  }
+
+  public TreeDataModel getTreeInSheet() {
+    return treeInSheet;
+  }
+
+  public TreeState getState() {
+    return state;
+  }
+
+  public String openAll() {
+    state.getExpandedState().expandAll();
+    return null;
+  }
+
+  public CantorInterval getInfinite() {
+    return infinite;
+  }
+
+  public Object clearSelected() {
+    state.getSelectedState().clear();
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TrueAndFalseList.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TrueAndFalseList.java
new file mode 100644
index 0000000..e36c1c1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/TrueAndFalseList.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.util.ArrayList;
+
+public class TrueAndFalseList extends ArrayList<Boolean> {
+
+  public TrueAndFalseList() {
+    super(2);
+    add(true);
+    add(false);
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/UndefinedRowCountDataModel.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/UndefinedRowCountDataModel.java
new file mode 100644
index 0000000..68714f9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/UndefinedRowCountDataModel.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.example.data.SolarObject;
+
+import javax.faces.model.ArrayDataModel;
+
+public class UndefinedRowCountDataModel extends ArrayDataModel {
+
+  public UndefinedRowCountDataModel(final SolarObject[] array) {
+    super(array);
+  }
+
+  @Override
+  public int getRowCount() {
+    return -1;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Upload.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Upload.java
new file mode 100644
index 0000000..a4c9374
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Upload.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.internal.util.PartUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.application.FacesMessage;
+import javax.faces.context.FacesContext;
+import javax.servlet.http.Part;
+import java.io.Serializable;
+
+public class Upload implements Serializable {
+
+  private static final Logger LOG = LoggerFactory.getLogger(Upload.class);
+
+  private Part part;
+
+  public String upload() {
+    if (part == null) {
+      FacesContext.getCurrentInstance().addMessage(
+          null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "No UploadItem found!", null));
+      return null;
+    }
+    LOG.info("type=" + part.getContentType());
+    LOG.info("size=" + part.getSize());
+    final String name = PartUtils.getSubmittedFileName(part);
+    LOG.info("name=" + name);
+    FacesContext.getCurrentInstance().addMessage(
+        null, new FacesMessage(FacesMessage.SEVERITY_INFO, "File was uploaded: " + name, null));
+
+    return "/test/file/file.xhtml";
+  }
+  
+  public Part getFile() {
+    return part;
+  }
+
+  public void setFile(final Part file) {
+    this.part = file;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Version.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Version.java
new file mode 100644
index 0000000..d05548c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/Version.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.apache.myfaces.tobago.util.FacesVersion;
+
+import javax.faces.context.FacesContext;
+
+public class Version {
+
+  public boolean isVersion11() {
+    return !FacesVersion.supports12();
+  }
+
+  public boolean isVersion12() {
+    return FacesVersion.supports12() && !FacesVersion.supports20();
+  }
+
+  public boolean isVersion20() {
+    return FacesVersion.supports20() && !FacesVersion.supports21();
+  }
+
+  public boolean isVersion21() {
+    return FacesVersion.supports21() && !FacesVersion.supports22();
+  }
+
+  public boolean isVersion22() {
+    return FacesVersion.supports22();
+  }
+
+  public boolean isMojarra() {
+    return FacesVersion.isMojarra();
+  }
+
+  public boolean isMyfaces() {
+    return FacesVersion.isMyfaces();
+  }
+
+  public String getJsfVersion() {
+    return FacesContext.class.getPackage().getImplementationVersion();
+  }
+
+  public String getJsfTitle() {
+    return FacesContext.class.getPackage().getImplementationTitle();
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/WaitFilter.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/WaitFilter.java
new file mode 100644
index 0000000..b9353b5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/WaitFilter.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import java.io.IOException;
+
+/**
+ * This filter waits for 10 seconds to emulate network or application problems.
+ */
+public class WaitFilter implements Filter {
+
+  private static final Logger LOG = LoggerFactory.getLogger(WaitFilter.class);
+
+  @Override
+  public void init(final FilterConfig filterConfig) throws ServletException {
+  }
+
+  @Override
+  public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+      throws IOException, ServletException {
+
+    LOG.info("Start waiting 10000 ms");
+
+    try {
+      Thread.sleep(10000L);
+    } catch (final InterruptedException e) {
+      LOG.error("Can't sleep 10000 ms", e);
+    }
+
+    LOG.info("Continuing...");
+
+    chain.doFilter(request, response);
+  }
+
+  @Override
+  public void destroy() {
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ZIndexController.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ZIndexController.java
new file mode 100644
index 0000000..d496d0f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/java/org/apache/myfaces/tobago/example/test/ZIndexController.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import java.io.Serializable;
+
+public class ZIndexController implements Serializable {
+
+  private Boolean modal1 = true;
+  private Boolean modal2 = true;
+
+  public Boolean getModal1() {
+    return modal1;
+  }
+
+  public void setModal1(final Boolean modal1) {
+    this.modal1 = modal1;
+  }
+
+  public Boolean getModal2() {
+    return modal2;
+  }
+
+  public void setModal2(final Boolean modal2) {
+    this.modal2 = modal2;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/META-INF/popup.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/META-INF/popup.xhtml
new file mode 100644
index 0000000..41de0aa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/META-INF/popup.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition xmlns:ui="http://java.sun.com/jsf/facelets"
+                xmlns:tc="http://myfaces.apache.org/tobago/component"
+                xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:button label="#{label}">
+    <f:facet name="popup">
+      <tc:popup>
+        <tc:attribute name="modal" value="#{modal}" mode="valueIfSet"/>
+        <f:facet name="layout">
+          <tc:gridLayout rows="auto" columns="200px"/>
+        </f:facet>
+        <tc:box label="#{label}">
+          <tc:button label="Close">
+            <tc:attribute name="popupClose" value="immediate"/>
+          </tc:button>
+            </tc:box>
+      </tc:popup>
+    </f:facet>
+  </tc:button>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/META-INF/tobago-example-test.taglib.xml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/META-INF/tobago-example-test.taglib.xml
new file mode 100644
index 0000000..6147e47
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/META-INF/tobago-example-test.taglib.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<facelet-taglib
+    version="2.0"
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd">
+
+  <namespace>http://myfaces.apache.org/tobago/example/test</namespace>
+
+  <tag>
+    <tag-name>popup</tag-name>
+    <source>popup.xhtml</source>
+  </tag>
+
+</facelet-taglib>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/logback.xml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/logback.xml
new file mode 100644
index 0000000..fed249e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/resources/logback.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!-- Schema is NOT official from logback -->
+<configuration
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:noNamespaceSchemaLocation="https://raw.github.com/enricopulatzo/logback-XSD/master/src/main/xsd/logback.xsd">
+
+  <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+    <encoder>
+      <pattern>%date{ISO8601} [%-16.16thread] %-5level %-50.50logger{50}:%-20.20method:%-4.4line [%mdc] %msg%n</pattern>
+    </encoder>
+  </appender>
+
+  <logger name="org.apache.myfaces.tobago.example.test" level="debug"/>
+
+  <root level="info">
+    <appender-ref ref="console"/>
+  </root>
+</configuration>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/404.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/404.xhtml
new file mode 100644
index 0000000..8588a8d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/404.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component">
+  <tc:page label="404 - page not found" id="page" width="1000px" height="750px">
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;*;*"/>
+      </f:facet>
+
+      <tc:messages/>
+      <tc:out value="The page was not found!"/>
+      <tc:out escape="false" value="&lt;h1>404 - page not found&lt;/h1>"/>
+    </tc:panel>
+
+    <tc:script onload="LOG.error('404 - page not found')"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/500.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/500.xhtml
new file mode 100644
index 0000000..82fffc7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/500.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:tc="http://myfaces.apache.org/tobago/component">
+  <tc:page label="500 - server error" id="page" width="1000px" height="750px">
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;*;*"/>
+      </f:facet>
+
+      <tc:messages/>
+      <tc:out escape="false" value="&lt;h1>500 - server error&lt;/h1>"/>
+    </tc:panel>
+
+    <tc:script onload="LOG.error('500 - server error')"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/faces-config.xml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/faces-config.xml
new file mode 100644
index 0000000..bc7d196
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/faces-config.xml
@@ -0,0 +1,262 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<faces-config
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
+    version="2.0">
+
+  <application>
+    <locale-config>
+      <default-locale>en</default-locale>
+      <supported-locale>de</supported-locale>
+      <supported-locale>es</supported-locale>
+      <supported-locale>ja</supported-locale>
+    </locale-config>
+  </application>
+
+  <factory>
+    <exception-handler-factory>
+      org.apache.myfaces.tobago.example.test.TestExceptionHandlerFactory
+    </exception-handler-factory>
+  </factory>
+
+  <managed-bean>
+    <managed-bean-name>browser</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.DirectoryBrowser</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>clientConfig</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.ClientConfigController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>in</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.InBean</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>inputSuggest</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.InputSuggestController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>immediate</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Immediate</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>hidden</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Hidden</managed-bean-class>
+    <managed-bean-scope>request</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>upload</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Upload</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>measureBean</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.MeasureBean</managed-bean-class>
+    <managed-bean-scope>none</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>selectBooleanCheckboxBean</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.SelectBooleanCheckboxBean</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>selectManyListboxBean</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.SelectManyListboxBean</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>reload</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Reload</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>sheet</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.SheetController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>sort</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.SheetSortController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>tree</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.TreeController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>zIndex</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.ZIndexController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>trueAndFalseList</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.TrueAndFalseList</managed-bean-class>
+    <managed-bean-scope>none</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>partially</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Partially</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>attribute</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Attribute</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>popupModalAttribute</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.PopupModalAttribute</managed-bean-class>
+    <managed-bean-scope>none</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>popupData</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.PopupData</managed-bean-class>
+    <managed-bean-scope>request</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>progress</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Progress</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>tobago1041</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Tobago1041</managed-bean-class>
+    <managed-bean-scope>none</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>shuttle</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Shuttle</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>scriptEvent</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.ScriptEvent</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>resourceBean</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.ResourceBean</managed-bean-class>
+    <managed-bean-scope>request</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>errorTest</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.ErrorTest</managed-bean-class>
+    <managed-bean-scope>none</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>version</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Version</managed-bean-class>
+    <managed-bean-scope>none</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>dynamic</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.DynamicBean</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>panel1</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.DynamicPanel1</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>panel2</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.DynamicPanel2</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>panel3</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.DynamicPanel3</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>bootstrap</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Bootstrap</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>popupReference</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.PopupReferenceController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>messages</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.Messages</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <managed-bean>
+    <managed-bean-name>dateController</managed-bean-name>
+    <managed-bean-class>org.apache.myfaces.tobago.example.test.DateController</managed-bean-class>
+    <managed-bean-scope>session</managed-bean-scope>
+  </managed-bean>
+
+  <navigation-rule>
+    <navigation-case>
+      <from-outcome>navigation</from-outcome>
+      <to-view-id>/navigation.xhtml</to-view-id>
+    </navigation-case>
+    <navigation-case>
+      <from-outcome>/test/file/file.xhtml</from-outcome>
+      <to-view-id>/test/file/file.xhtml</to-view-id>
+    </navigation-case>
+  </navigation-rule>
+
+</faces-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/sun-web.xml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/sun-web.xml
new file mode 100644
index 0000000..132427b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/sun-web.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<!DOCTYPE sun-web-app PUBLIC "-//Sun Microsystems, Inc.//DTD GlassFish Application Server 3.0 Servlet 3.0//EN"
+    "http://www.sun.com/software/appserver/dtds/sun-web-app_3_0-0.dtd">
+<!--
+  This file is needed to run the application on Glassfish 3.0
+  Also, we have to add EL support to the pom.xml (el-ri.jar)
+  The reason may be: http://java.net/jira/browse/JAVASERVERFACES-1828
+-->
+<sun-web-app>
+  <class-loader delegate="false"/>
+<!--
+  <property name="useMyFaces" value="true"/>
+-->
+  <property name="useBundledJsf" value="true"/>
+</sun-web-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/tobago-config.xml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/tobago-config.xml
new file mode 100644
index 0000000..ceb21c5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/tobago-config.xml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<tobago-config xmlns="http://myfaces.apache.org/tobago/tobago-config"
+   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-2.0.xsd"
+   version="2.0">
+
+  <theme-config>
+    <default-theme>standard</default-theme>
+    <supported-theme>scarborough</supported-theme>
+    <supported-theme>richmond</supported-theme>
+    <supported-theme>charlotteville</supported-theme>
+  </theme-config>
+
+  <!-- XXX old -->
+  <resource-dir>tobago-resource</resource-dir>
+
+  <!-- because this application uses frames -->
+  <prevent-frame-attacks>false</prevent-frame-attacks>
+
+  <auto-access-key-from-label>false</auto-access-key-from-label>
+
+  <!-- this disables CSP -->
+  <!-- XXX With CSP Tobago 3.0.x is currently not working 100% see TOBAGO-1534 -->
+  <content-security-policy mode="report-only"/>
+
+  <renderers>
+    <renderer>
+      <name>Image</name>
+      <supported-markup>
+        <markup>double</markup>
+      </supported-markup>
+    </renderer>
+
+    <renderer>
+      <name>TreeCommand</name>
+      <supported-markup>
+        <markup>todo</markup>
+      </supported-markup>
+    </renderer>
+  </renderers>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/web.xml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..1705199
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<web-app
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+    version="3.0">
+
+  <display-name>Tobago Application for Quality Assurance</display-name>
+  <description>Will be used for automated tests in the build process.</description>
+
+  <context-param>
+    <param-name>javax.faces.PROJECT_STAGE</param-name>
+    <!--<param-value>Production</param-value>-->
+    <param-value>Development</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>com.sun.faces.validateXml</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.FACELETS_SKIP_COMMENTS</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.FACELETS_VIEW_MAPPINGS</param-name>
+    <param-value>*.xhtml</param-value>
+  </context-param>
+
+  <context-param>
+    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
+    <param-value>true</param-value>
+  </context-param>
+
+  <filter>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <filter-class>org.apache.myfaces.tobago.internal.webapp.LoggingMdcFilter</filter-class>
+  </filter>
+  <filter-mapping>
+    <filter-name>LoggingMdcFilter</filter-name>
+    <url-pattern>/*</url-pattern>
+  </filter-mapping>
+
+  <servlet>
+    <servlet-name>FacesServlet</servlet-name>
+    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
+    <load-on-startup>3</load-on-startup>
+    <!-- This is needed, for file upload e.g. <tc:file> with JSF 2.0 or 2.1, JSF 2.2 doesn't need it. -->
+    <multipart-config>
+      <max-request-size>20000000</max-request-size>
+      <max-file-size>1000000</max-file-size>
+    </multipart-config>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>FacesServlet</servlet-name>
+    <url-pattern>/faces/*</url-pattern>
+  </servlet-mapping>
+
+  <servlet>
+    <servlet-name>KillSessionServlet</servlet-name>
+    <servlet-class>org.apache.myfaces.tobago.example.test.KillSession</servlet-class>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>KillSessionServlet</servlet-name>
+    <url-pattern>/KillSession</url-pattern>
+  </servlet-mapping>
+
+  <servlet>
+    <servlet-name>ScriptEventServlet</servlet-name>
+    <servlet-class>org.apache.myfaces.tobago.example.test.ScriptEventServlet</servlet-class>
+  </servlet>
+  <servlet-mapping>
+    <servlet-name>ScriptEventServlet</servlet-name>
+    <url-pattern>/ScriptEventServlet</url-pattern>
+  </servlet-mapping>
+
+<!--
+  <filter>
+    <filter-name>MyFacesExtensionsFilter</filter-name>
+    <filter-class>org.apache.myfaces.webapp.filter.ExtensionsFilter</filter-class>
+      <init-param>
+          <param-name>uploadMaxFileSize</param-name>
+          <param-value>20m</param-value>
+      </init-param>
+  </filter>
+
+  &lt;!&ndash; extension mapping for adding <script/>, <link/>, and other resource tags to JSF-pages  &ndash;&gt;
+  <filter-mapping>
+      <filter-name>MyFacesExtensionsFilter</filter-name>
+      &lt;!&ndash; servlet-name must match the name of your javax.faces.webapp.FacesServlet entry &ndash;&gt;
+      <servlet-name>FacesServlet</servlet-name>
+  </filter-mapping>
+
+  &lt;!&ndash; extension mapping for serving page-independent resources (javascript, stylesheets, images, etc.)  &ndash;&gt;
+  <filter-mapping>
+      <filter-name>MyFacesExtensionsFilter</filter-name>
+      <url-pattern>/faces/myFacesExtensionResource/*</url-pattern>
+  </filter-mapping>
+-->
+
+  <error-page>
+    <error-code>404</error-code>
+    <location>/faces/404.xhtml</location>
+  </error-page>
+
+  <error-page>
+    <error-code>500</error-code>
+    <location>/faces/500.xhtml</location>
+  </error-page>
+
+  <jsp-config>
+    <jsp-property-group>
+      <url-pattern>*.jsp</url-pattern>
+      <url-pattern>*.jspx</url-pattern>
+      <url-pattern>*.html</url-pattern>
+      <page-encoding>UTF-8</page-encoding>
+    </jsp-property-group>
+  </jsp-config>
+
+<!-- This is an alternative way to set the project stage.
+  <env-entry>
+    <env-entry-name>jsf/ProjectStage</env-entry-name>
+    <env-entry-type>java.lang.String</env-entry-type>
+    <env-entry-value>Development</env-entry-value>
+  </env-entry>
+-->
+
+  <filter>
+    <filter-name>WaitFilter</filter-name>
+    <filter-class>org.apache.myfaces.tobago.example.test.WaitFilter</filter-class>
+  </filter>
+
+  <filter-mapping>
+      <filter-name>WaitFilter</filter-name>
+      <url-pattern>/image/wait/*</url-pattern>
+  </filter-mapping>
+
+  <session-config>
+    <cookie-config>
+      <http-only>true</http-only>
+    </cookie-config>
+  </session-config>
+
+</web-app>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/facet/contextMenu/panel.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/facet/contextMenu/panel.xhtml
new file mode 100644
index 0000000..f51768a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/facet/contextMenu/panel.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="200px"/>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*" rows="*;*"/>
+      </f:facet>
+      <f:facet name="contextMenu">
+        <tc:menu>
+          <tc:menuCommand onclick="alert('Main Menu 1')" label="Main Menu 1"/>
+          <tc:menuCommand onclick="alert('Main Menu 2')" label="Main Menu 2"/>
+          <tc:menu label="Main Submenu">
+            <tc:menuCommand onclick="alert('Main Menu 3')" label="Main Menu 3"/>
+            <tc:menuCommand onclick="alert('Main Menu 4')" label="Main Menu 4"/>
+          </tc:menu>
+        </tc:menu>
+      </f:facet>
+
+      <tc:textarea readonly="true" value="Main Menu">
+        <tc:gridLayoutConstraint columnSpan="2"/>
+      </tc:textarea>
+
+      <tc:textarea readonly="true" value="Also Main Menu"/>
+
+      <tc:panel>
+        <f:facet name="contextMenu">
+          <tc:menu>
+            <tc:menuCommand onclick="alert('Other Menu 1')" label="Other Menu 1"/>
+            <tc:menuCommand onclick="alert('Other Menu 2')" label="Other Menu 2"/>
+            <tc:menu label="Other Submenu">
+              <tc:menuCommand onclick="alert('Other Menu 3')" label="Other Menu 3"/>
+              <tc:menuCommand onclick="alert('Other Menu 4')" label="Other Menu 4"/>
+            </tc:menu>
+          </tc:menu>
+        </f:facet>
+
+        <tc:textarea readonly="true" value="Other Menu"/>
+      </tc:panel>
+
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/feather-leaf.png b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/feather-leaf.png
new file mode 100644
index 0000000..f1208e0
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/feather-leaf.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/foo.gif b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/foo.gif
new file mode 100644
index 0000000..c35c507
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/foo.gif differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/foo.png b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/foo.png
new file mode 100644
index 0000000..5ad500e
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/foo.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/fooDisabled.gif b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/fooDisabled.gif
new file mode 100644
index 0000000..1e35d77
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/fooDisabled.gif differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/fooDisabled.png b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/fooDisabled.png
new file mode 100644
index 0000000..bc6e5bf
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/fooDisabled.png differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/wait/cat.jpg b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/wait/cat.jpg
new file mode 100644
index 0000000..a9ab635
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/image/wait/cat.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/immediate.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/immediate.xhtml
new file mode 100644
index 0000000..06ccb67
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/immediate.xhtml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page" width="300px" height="300px">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*;auto"/>
+    </f:facet>
+
+    <tc:in value="#{immediate.in}" required="true"/>
+    <tc:selectOneListbox value="#{immediate.selectOne}">
+      <tc:selectItems value="#{immediate.selectItems}"/>
+    </tc:selectOneListbox>
+    <!--
+        <tc:selectManyListbox value="#{immediate.selectMany}">
+          <tc:selectItems value="#{immediate.selectItems}"/>
+        </tc:selectManyListbox>
+    -->
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*"/>
+      </f:facet>
+
+      <tc:button label="immediate" immediate="true" action="#{immediate.test}"/>
+      <tc:button label="normal" action="#{immediate.test}"/>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/index.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/index.html
new file mode 100644
index 0000000..394623d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/index.html
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html>
+<head>
+  <meta http-equiv="Cache-Control" content="no-cache">
+  <meta http-equiv="Refresh" content="0; URL=faces/navigation.xhtml">
+</head>
+<body>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-0-ok.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-0-ok.xhtml
new file mode 100644
index 0000000..04c5e45
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-0-ok.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+
+    <tc:out value="Test of the automatic test system."/>
+
+  </tc:page>
+
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-1-fail.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-1-fail.xhtml
new file mode 100644
index 0000000..d2af6d1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-1-fail.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  Test of the automatic test system.
+
+  This test will fail!
+
+  <tc:page id="page">
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertWidth('page', 600);"/>
+
+  </tc:page>
+
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-2-ok.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-2-ok.xhtml
new file mode 100644
index 0000000..04c5e45
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-2-ok.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+
+    <tc:out value="Test of the automatic test system."/>
+
+  </tc:page>
+
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-3-ok.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-3-ok.xhtml
new file mode 100644
index 0000000..04c5e45
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-3-ok.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+
+    <tc:out value="Test of the automatic test system."/>
+
+  </tc:page>
+
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-4-not-tobago.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-4-not-tobago.xhtml
new file mode 100644
index 0000000..eb241cf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-4-not-tobago.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+
+<f:view
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns="http://www.w3.org/1999/xhtml">
+  <html>
+  <body> Test of the automatic test system.
+  </body>
+  </html>
+</f:view>
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-5-error-on-server.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-5-error-on-server.xhtml
new file mode 100644
index 0000000..d95dc26
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/meta-test/meta-5-error-on-server.xhtml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+
+    <!-- browser.errorOnPage doesn't exists: thats the error on this page -->
+    <tc:out value="#{browser.errorOnPage}"/>
+
+  </tc:page>
+
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/navigation.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/navigation.xhtml
new file mode 100644
index 0000000..d9f42f6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/navigation.xhtml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:h="http://java.sun.com/jsf/html"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page" label="Tobago Example Test">
+    <tc:flexLayout columns="300px;*">
+      <tc:panel>
+        <f:facet name="layout">
+          <!--todo replace 20px with "auto" -->
+          <tc:gridLayout rows="auto;*"/>
+        </f:facet>
+
+        <tc:panel>
+          <f:facet name="layout">
+            <tc:gridLayout columns="*;30px" rows="auto;auto"/>
+          </f:facet>
+
+          <tc:selectOneChoice value="#{clientConfig.theme}" label="Theme">
+            <f:selectItems value="#{clientConfig.themeItems}"/>
+          </tc:selectOneChoice>
+          <tc:button action="#{clientConfig.submit}" label="OK">
+            <tc:gridLayoutConstraint rowSpan="2"/>
+          </tc:button>
+          <tc:selectOneChoice value="#{clientConfig.locale}" label="Locale">
+            <f:selectItems value="#{clientConfig.localeItems}"/>
+          </tc:selectOneChoice>
+        </tc:panel>
+
+        <tc:tree value="#{browser.tree}" var="node">
+          <tc:treeNode disabled="#{node.disabled}">
+            <tc:treeIndent/>
+            <tc:treeIcon/>
+            <tc:treeCommand link="#{node.resource}" label="#{node.label}" target="content"
+                            rendered="#{node.childCount == 0}" markup="#{node.markup}"/>
+            <tc:treeLabel value="#{node.label}" rendered="#{node.childCount > 0}"/>
+          </tc:treeNode>
+        </tc:tree>
+      </tc:panel>
+
+      <!-- src will be set via <tc:treeNode target="page:content"> -->
+      <tc:object name="content"/>
+
+      <!--<tc:script file="http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js"/>-->
+    </tc:flexLayout>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/partially/encoding.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/partially/encoding.xhtml
new file mode 100644
index 0000000..3788191
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/partially/encoding.xhtml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="500px"/>
+
+    <tc:box id="box" label="Test the encoding of the partial loaded stuff (TOBAGO-1132 and TOBAGO-1133)">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;20px;auto;auto;*;auto"/>
+      </f:facet>
+
+      <tc:messages/>
+
+      <tc:out value="Test if all characters can be transported for normal and AJAX requests."/>
+
+      <tc:in label="Counter:" value="#{partially.counter}" readonly="true"/>
+
+      <tc:in label="as attribute" value="#{partially.characters}"/>
+
+      <tc:textarea label="U+0000 to U+024F" value="#{partially.characters}"/>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;auto;auto;auto"/>
+        </f:facet>
+
+        <tc:panel/>
+        <tc:button label="Info" onclick="info();"/>
+        <tc:button label="Full Reload" action="#{partially.reload}"/>
+        <tc:button label="AJAX Reload" action="#{partially.reload}">
+          <f:ajax render="box" execute="box"/>
+        </tc:button>
+
+      </tc:panel>
+
+      <tc:script>
+
+        test_version = #{partially.counter};
+        #{partially.characters}
+
+        function info() {
+          LOG.info("Found the Backslash: '" + test_characters[92] + "'. Used version: '" + test_version + "'");
+          LOG.show();
+        }
+
+      </tc:script>
+
+    </tc:box>
+
+    <!-- todo automatic tests with selenium -->
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-point.jpg b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-point.jpg
new file mode 100644
index 0000000..f5d817d
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-point.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-pointDisabled.jpg b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-pointDisabled.jpg
new file mode 100644
index 0000000..00f3f9d
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-pointDisabled.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-pointHover.jpg b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-pointHover.jpg
new file mode 100644
index 0000000..fa347b3
Binary files /dev/null and b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/pidgeon-pointHover.jpg differ
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/resource-manager/image.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/resource-manager/image.xhtml
new file mode 100644
index 0000000..35c585f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/resource-manager/image.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page" width="300px" height="500px">
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*"/>
+    </f:facet>
+
+<!-- XXX commented out because: date.png is a bad example, because a local icon in the app results in ugly date pickers in the hole app.
+    <tc:out value="The date.png exists in the app and in the theme. The app image should be displayed, when activating fix-resource-order in tobago config."/>
+
+    <tc:image id="date" value="image/date.png"/>
+-->
+
+    <tc:out value="The config.png exists only in the theme."/>
+
+    <tc:image id="config" value="image/config.png"/>
+
+    <tc:out value="The foo.png exists only in the app."/>
+
+    <tc:image id="foo" value="image/foo.png"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/resource-manager/script.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/resource-manager/script.xhtml
new file mode 100644
index 0000000..7668bf0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/resource-manager/script.xhtml
@@ -0,0 +1,100 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page" width="300px" height="500px">
+    <f:facet name="layout">
+      <tc:gridLayout rows="30px;auto;auto;auto;auto"/>
+    </f:facet>
+
+    <tc:out value="Tests the order of included script files. The field shows the position of the include in the HTML head."/>
+
+    <tc:in readonly="true" fieldId="standard" label="Standard"/>
+    <tc:in readonly="true" fieldId="standardApp" label="Standard Application"/>
+    <tc:in readonly="true" fieldId="scarborough" label="Scarborough"/>
+    <tc:in readonly="true" fieldId="application" label="Application"/>
+
+    <tc:script onload="check()">
+      function check() {
+
+        var pos = -1;
+        var posStandard = -1;
+        var posStandardApp = -1;
+        var posScarborough = -1;
+        var posApp = -1;
+
+        jQuery("html>head>script").each(function () {
+          pos++;
+          var src = jQuery(this).attr("src");
+          if (src == null) {
+            return; // skip
+          }
+          if (src.match(/\/org\/apache\/myfaces\/tobago\/renderkit\/\d.+\/html\/standard\/standard\/script\/tobago.js/)) {
+            posStandard = pos;
+          }
+          if (src.match(/\/tobago-resource\/html\/standard\/standard\/script\/tobago.js/)) {
+            posStandardApp = pos;
+          }
+          if (src.match(/\/org\/apache\/myfaces\/tobago\/renderkit\/\d.+\/html\/scarborough\/standard\/script\/tobago.js/)) {
+            posScarborough = pos;
+          }
+          if (src.match(/\/script\/tobago.js/)) {
+            posApp = pos;
+          }
+        });
+
+        jQuery(Tobago.Utils.escapeClientId("page:standard")).val(posStandard);
+        jQuery(Tobago.Utils.escapeClientId("page:standardApp")).val(posStandardApp);
+        jQuery(Tobago.Utils.escapeClientId("page:scarborough")).val(posScarborough);
+        jQuery(Tobago.Utils.escapeClientId("page:application")).val(posApp);
+
+        if (posStandard == -1) {
+          LOG.error("Script for theme 'standard' not found!");
+        }
+
+        if (posStandardApp == -1) {
+          LOG.error("The application specific script for theme 'standard' not found!");
+        }
+
+        if (posScarborough == -1) {
+          LOG.error("Script for theme 'scarborough' not found!");
+        }
+
+        if (posApp == -1) {
+          LOG.error("The application specific script not found!");
+        }
+
+        if (posStandard >= posStandardApp) {
+          LOG.error("Script for theme 'standard' must be included before the application specific script of 'standard'!");
+        }
+
+        if (posStandardApp >= posScarborough) {
+          LOG.error("Application specific script for theme 'standard' must be included before the script of 'scarborough'!");
+        }
+
+        if (posScarborough >= posApp) {
+          LOG.error("Script for theme 'scarborough' must be included before the application specific script!");
+        }
+      }
+    </tc:script>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/script/tobago-assert.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/script/tobago-assert.js
new file mode 100644
index 0000000..7bc5ee4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/script/tobago-assert.js
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * Utilities to make client side tests easier.
+ */
+
+var TobagoAssert = {
+
+  failed: false,
+
+  assertLeft:function (elementOrId, left, epsilon) {
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    epsilon = epsilon != null ? epsilon : 0;
+    var offsetLeft = element.offset().left;
+    if (Math.abs(offsetLeft - left) > epsilon) {
+      TobagoAssert.fail("left", element, left, offsetLeft);
+    }
+  },
+
+  assertTop:function (elementOrId, top, epsilon) {
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    epsilon = epsilon != null ? epsilon : 0;
+    var offsetTop = element.offset().top;
+    if (Math.abs(offsetTop - top) > epsilon) {
+      TobagoAssert.fail("top", element, top, offsetTop);
+    }
+  },
+
+  assertWidth:function (elementOrId, width, epsilon) {
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    epsilon = epsilon != null ? epsilon : 0;
+    var offsetWidth = element.get(0).offsetWidth;
+    if (Math.abs(offsetWidth - width) > epsilon) {
+      TobagoAssert.fail("width", element, width, offsetWidth);
+    }
+  },
+
+  assertHeight:function (elementOrId, height, epsilon) {
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    epsilon = epsilon != null ? epsilon : 0;
+    var offsetHeight = element.get(0).offsetHeight;
+    if (Math.abs(offsetHeight - height) > epsilon) {
+      TobagoAssert.fail("height", element, height, offsetHeight);
+    }
+  },
+
+  fail: function(name, element, expected, actual) {
+    var text;
+    if (element) {
+      element.overlay({error: true, ajax: true});
+      text = "The element '" + element.get(0).tagName + "' with id='" + element.attr("id")
+          + "' has wrong " + name + ": expected=" + expected + " actual=" + actual;
+      var overlay = element.data("tobago-overlay").overlay;
+      overlay.attr("title", (overlay.attr("title") === undefined ? "" : overlay.attr("title") + "\n" ) + text);
+    } else {
+      text = name + ": expected=" + expected + " actual=" + actual;
+    }
+    TobagoAssert.assert(false, text);
+  },
+
+  assert: function (test, text) {
+    console.assert(test, text);
+    if (!test) {
+      TobagoAssert.failed = true;
+    }
+  },
+
+  assertLayout:function (elementOrId, left, top, width, height) {
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    TobagoAssert.assertLeft(element, left);
+    TobagoAssert.assertTop(element, top);
+    TobagoAssert.assertWidth(element, width);
+    TobagoAssert.assertHeight(element, height);
+  },
+
+  assertAbsence:function (id) {
+    var element = document.getElementById(id);
+    var result = element == null;
+    TobagoAssert.assert(result, "The element with id=" + id + " was found, but should not!");
+  },
+
+  assertAttribute:function (elementOrId, attribute, expected) {
+    TobagoAssert.assert("value" != attribute,
+      "The assertAttribute() is not allowed for the value attribute, please use assertValue() instead.");
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    TobagoAssert.assert(element.attr(attribute) == expected,
+      "The attribute '" + attribute + "' of element with id=" + element.attr('id')
+          + " is '" + element.attr(attribute) + "', but expected was '" + expected + "'.");
+  },
+
+  assertValue:function (elementOrId, expected) {
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    TobagoAssert.assert(element.val() == expected,
+        "The value of element with id=" + element.attr('id')
+        + " is '" + element.val() + "', but expected was '" + expected + "'.");
+  },
+
+  assertContent:function (elementOrId, expected) {
+    var element = TobagoAssert.jQueryElement(elementOrId);
+    TobagoAssert.assert(element.html() == expected,
+        "The content of element with id=" + element.attr('id')
+          + " is '" + element.html() + "', but expected was '" + expected + "'.");
+  },
+
+  /**
+   * Util to get an jQuery object from a plain id string (unescaped) or a jQuery object.
+   */
+  jQueryElement:function (elementOrId) {
+    var element;
+    if (typeof elementOrId == "string") {
+      element = jQuery(Tobago.Utils.escapeClientId(elementOrId));
+    } else { // JQuery Object Array
+      element = elementOrId;
+    }
+    return element;
+  }
+};
+
+(function ($) {
+
+  $.widget("test.assertLayout", {
+
+    _create: function () {
+
+      var epsilon = this.element.data("assert-epsilon");
+
+      var left = this.element.data("assert-left");
+      if (left != null) {
+        TobagoAssert.assertLeft(this.element, left, epsilon);
+      }
+      var top = this.element.data("assert-top");
+      if (top != null) {
+        TobagoAssert.assertTop(this.element, top, epsilon);
+      }
+      var width = this.element.data("assert-width");
+      if (width != null) {
+        TobagoAssert.assertWidth(this.element, width, epsilon);
+      }
+      var height = this.element.data("assert-height");
+      if (height != null) {
+        TobagoAssert.assertHeight(this.element, height, epsilon);
+      }
+    },
+
+    _destroy: function () {
+    }
+
+  });
+
+}(jQuery));
+
+Tobago.registerListener(function() {
+    jQuery("[data-assert-width],[data-assert-height],[data-assert-left],[data-assert-top]").assertLayout();
+}, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/script/tobago.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/script/tobago.js
new file mode 100644
index 0000000..734f9b9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/script/tobago.js
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This entry is to test order of included JS Files.
+ * Used in resource-manager/script.xhtml
+ */
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/simple.xhtml
new file mode 100644
index 0000000..394342b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/simple.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+
+    <tc:in readonly="true" id="in" value="Simple Test"/>
+    <tc:button label="CLICK" />
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/style/tobago.css b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/style/tobago.css
new file mode 100644
index 0000000..9c0f5cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/style/tobago.css
@@ -0,0 +1,20 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+.tobago-treeNode .tobago-treeCommand-markup-todo {
+  color: #ff0000;
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/accessKey/accessKey-auto-off.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/accessKey/accessKey-auto-off.xhtml
new file mode 100644
index 0000000..1a8e3b7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/accessKey/accessKey-auto-off.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:out value="Please test with tobago-config.xml -> auto-access-key-from-label=false"/>
+
+    <tc:messages/>
+
+    <tc:in accessKey="f" label="First Value"/>
+
+    <tc:button accessKey="s" label="Submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/accessKey/accessKey-auto-on.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/accessKey/accessKey-auto-on.xhtml
new file mode 100644
index 0000000..d0473fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/accessKey/accessKey-auto-on.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:out value="Please test with tobago-config.xml -> auto-access-key-from-label=true"/>
+
+    <tc:messages/>
+
+    <tc:in label="_First Value"/>
+
+    <tc:button label="_Submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/attribute.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/attribute.xhtml
new file mode 100644
index 0000000..910046a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/attribute.xhtml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns:c="http://java.sun.com/jsp/jstl/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto;auto;auto;*" columns="250px;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:label value="condition"/>
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*"/>
+      </f:facet>
+      <tc:selectBooleanCheckbox value="#{attribute.condition}"/>
+      <tc:button label="update"/>
+    </tc:panel>
+
+    <tc:label value="simple output"/>
+    <tc:in readonly="true">
+      <tc:attribute name="value" value="Some Value from the tc:attribute"/>
+    </tc:in>
+
+    <tc:label value="output over EL"/>
+    <tc:in readonly="true">
+      <tc:attribute name="value" value="#{attribute.counter}"/>
+    </tc:in>
+
+    <tc:label value="action"/>
+    <tc:button label="Click">
+      <tc:attribute name="action" value="#{attribute.reload}"/>
+    </tc:button>
+
+    <tc:label value="conditional action (#{attribute.condition})"/>
+    <tc:button label="Click">
+      <c:if test="${attribute.condition}">
+        <tc:attribute name="action" value="#{attribute.reload}"/>
+      </c:if>
+    </tc:button>
+
+    <tc:label value="conditional action not (#{not attribute.condition})"/>
+    <tc:button label="Click">
+      <c:if test="${not attribute.condition}">
+        <tc:attribute name="action" value="#{attribute.reload}"/>
+      </c:if>
+    </tc:button>
+
+    <tc:label value="conditional action (#{attribute.condition}) and link not (#{not attribute.condition})"/>
+    <tc:button label="Click">
+      <c:if test="${attribute.condition}">
+        <tc:attribute name="action" value="#{attribute.reload}"/>
+      </c:if>
+      <c:if test="${not attribute.condition}">
+        <tc:attribute name="link" value="/"/>
+      </c:if>
+    </tc:button>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/mode-valueIfSet.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/mode-valueIfSet.js
new file mode 100644
index 0000000..28b5991
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/mode-valueIfSet.js
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+jQuery(document).ready(function () {
+
+  // only to display
+  jQuery("#page\\:id-box").find("input").each(function () {
+    jQuery(this).val(jQuery(this).attr('id'));
+  });
+
+  // assertions
+  TobagoAssert.assertValue("page:direct", "direct literal");
+  TobagoAssert.assertValue("page:v1", "from var");
+  TobagoAssert.assertValue("page:v2", "from var");
+  TobagoAssert.assertValue("page:v3", "from var ++");
+  TobagoAssert.assertValue("page:v4", "value from model");
+  TobagoAssert.assertValue("page:vu", "");
+
+  var i1 = jQuery(Tobago.Utils.escapeClientId("page:id-box")).find("input:eq(0)");
+  TobagoAssert.assertAttribute(i1, "id", "page:my_number_1");
+//        TobagoAssert.assertAttribute(..., "id", "");
+  var i3 = jQuery(Tobago.Utils.escapeClientId("page:id-box")).find("input:eq(2)");
+  TobagoAssert.assertAttribute(i3, "id", "page:my_number_3");
+//        TobagoAssert.assertAttribute(..., "id", "");
+});
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/mode-valueIfSet.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/mode-valueIfSet.xhtml
new file mode 100644
index 0000000..db44df7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/mode-valueIfSet.xhtml
@@ -0,0 +1,106 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns:c="http://java.sun.com/jsp/jstl/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:label value="demo of the valueIfSet mode of tc:attribute (facelets only)"/>
+
+    <tc:box label="value">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto;auto;auto;auto;*" columns="250px;*"/>
+      </f:facet>
+
+      <tc:label value="value"/>
+      <tc:in id="direct">
+        <tc:attribute name="value" value="direct literal" mode="valueIfSet"/>
+      </tc:in>
+
+      <c:set var="value1" value="from var"/>
+      <tc:label value="value"/>
+      <tc:in id="v1">
+        <tc:attribute name="value" value="#{value1}" mode="valueIfSet"/>
+      </tc:in>
+
+      <c:set var="value2" value="#{value1}"/>
+      <tc:label value="value"/>
+      <tc:in id="v2">
+        <tc:attribute name="value" value="#{value2}" mode="valueIfSet"/>
+      </tc:in>
+
+      <c:set var="value3" value="#{value1} ++"/>
+      <tc:label value="value"/>
+      <tc:in id="v3">
+        <tc:attribute name="value" value="#{value3}" mode="valueIfSet"/>
+      </tc:in>
+
+      <c:set var="value4" value="#{attribute.value}"/>
+      <tc:label value="value"/>
+      <tc:in id="v4">
+        <tc:attribute name="value" value="#{value4}" mode="valueIfSet"/>
+      </tc:in>
+
+      <tc:label value="value (undefined)"/>
+      <tc:in id="vu">
+        <tc:attribute name="value" value="#{value_undefined}" mode="valueIfSet"/>
+      </tc:in>
+
+    </tc:box>
+
+    <tc:box label="id" id="id-box">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto;auto;auto;auto;*" columns="250px;*"/>
+      </f:facet>
+
+      <tc:label value="id"/>
+      <tc:in>
+        <tc:attribute name="id" value="my_number_1" mode="valueIfSet"/>
+      </tc:in>
+
+      <tc:label value="id (not implemented)"/>
+      <tc:in>
+        <tc:attribute name="id" value="#{'my_number_2'}" mode="valueIfSet"/>
+      </tc:in>
+
+      <c:set var="id3" value="my_number_3"/>
+      <tc:label value="id"/>
+      <tc:in>
+        <tc:attribute name="id" value="#{id3}" mode="valueIfSet"/>
+      </tc:in>
+
+      <tc:label value="id (undefined)"/>
+      <tc:in>
+        <tc:attribute name="id" value="#{id_undefined}" mode="valueIfSet"/>
+      </tc:in>
+
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script file="test/attribute/mode-valueIfSet.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/popup-modal.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/popup-modal.selenium.html
new file mode 100644
index 0000000..9a961c2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/popup-modal.selenium.html
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/attribute/popup-modal.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//button[1]</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>class=tobago-popup tobago-popup-markup-modal</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//div[2]/button</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//button[2]</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>class=tobago-popup tobago-popup-markup-modal</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//div[2]/button</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//button[3]</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>class=tobago-popup</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//div[2]/button</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//button[4]</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>class=tobago-popup tobago-popup-markup-modal</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//div[2]/button</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//button[5]</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>class=tobago-popup</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//div[2]/button</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//button[6]</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>class=tobago-popup tobago-popup-markup-modal</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//div[2]/button</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>//button[7]</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>class=tobago-popup</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//div[2]/button</td>
+	<td></td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/popup-modal.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/popup-modal.xhtml
new file mode 100644
index 0000000..c9f971c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/attribute/popup-modal.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:test="http://myfaces.apache.org/tobago/example/test"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+
+    <f:facet name="layout">
+      <tc:gridLayout columns="300px" rows="auto;auto;auto;auto;auto;auto;auto"/>
+    </f:facet>
+
+    <test:popup id="d" label="modal: default"/>
+    <test:popup id="t" label="modal: true" modal="true"/>
+    <test:popup id="f" label="modal: false" modal="false"/>
+    <test:popup id="te" label="modal: \#{true}" modal="#{true}"/>
+    <test:popup id="fe" label="modal: \#{false}" modal="#{false}"/>
+    <test:popup id="tb" label="modal: \#{popupModalAttribute.alwaysTrue}" modal="#{popupModalAttribute.alwaysTrue}"/>
+    <test:popup id="fb" label="modal: \#{popupModalAttribute.alwaysFalse}" modal="#{popupModalAttribute.alwaysFalse}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box-box-auto.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box-box-auto.xhtml
new file mode 100644
index 0000000..33d2759
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box-box-auto.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto" rows="auto"/>
+    </f:facet>
+
+    <tc:box id="outerbox" label="outer box">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="0"/>
+      <tc:dataAttribute name="assert-width" value="226"/>
+      <tc:dataAttribute name="assert-height" value="116"/>
+      <f:facet name="layout">
+        <tc:gridLayout columns="auto" rows="auto"/>
+      </f:facet>
+
+      <tc:box id="innerbox" label="inner box">
+        <tc:dataAttribute name="assert-left" value="6"/>
+        <tc:dataAttribute name="assert-top" value="26"/>
+        <tc:dataAttribute name="assert-width" value="213"/>
+        <tc:dataAttribute name="assert-height" value="83"/>
+        <f:facet name="layout">
+          <tc:gridLayout columns="auto" rows="auto"/>
+        </f:facet>
+
+        <tc:textarea id="textarea" value="Some text.">
+          <tc:dataAttribute name="assert-left" value="12"/>
+          <tc:dataAttribute name="assert-top" value="52"/>
+          <tc:dataAttribute name="assert-width" value="200"/>
+          <tc:dataAttribute name="assert-height" value="50"/>
+          <tc:gridLayoutConstraint preferredWidth="200px" preferredHeight="50px"/>
+        </tc:textarea>
+
+      </tc:box>
+
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box-box-relative.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box-box-relative.xhtml
new file mode 100644
index 0000000..5b58fc7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box-box-relative.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="200px"/>
+
+    <tc:box id="outerbox" label="outer box">
+
+      <tc:box id="innerbox" label="inner box">
+
+        <tc:textarea id="textarea" value="Some text."/>
+
+      </tc:box>
+
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:outerbox', 0, 0, 500, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:innerbox', 6, 26, 487, 167);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:textarea', 12, 52, 474, 134);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box.xhtml
new file mode 100644
index 0000000..342d385
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/box/box.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="200px"/>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:box id="box" label="A simple box">
+      <f:facet name="layout">
+        <tc:gridLayout/>
+      </f:facet>
+
+      <tc:textarea id="textarea"
+          value="Some text without label, some text without label, some text without label, some text without label, some text without label, some text without label, some text without label, some text without label, some text without label, some text without label, ..."/>
+
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:box', 0, 0, 500, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:textarea', 6, 26, 487, 167);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/button-static-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/button-static-layout.xhtml
new file mode 100644
index 0000000..99bccd9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/button-static-layout.xhtml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+    
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="310px" height="100px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*;*" rows="auto;auto;*"/>
+    </f:facet>
+
+    <tc:button label="1" id="b-1"/>
+    <tc:button label="2" id="b-2"/>
+    <tc:button label="3" id="b-3"/>
+    <tc:button label="4" id="b-4"/>
+    <tc:button label="5" id="b-5"/>
+    <tc:button label="6" id="b-6"/>
+
+    <tc:panel>
+      <tc:gridLayoutConstraint columnSpan="3"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b-1', 0, 0, 100, 20);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b-2', 105, 0, 100, 20);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b-3', 210, 0, 100, 20);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b-4', 0, 25, 100, 20);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b-5', 105, 25, 100, 20);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b-6', 210, 25, 100, 20);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/defaultCommand.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/defaultCommand.xhtml
new file mode 100644
index 0000000..841486e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/defaultCommand.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+    
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="310px" height="100px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;auto;auto" rows="auto;auto;*"/>
+    </f:facet>
+
+
+    <tc:panel>
+      <tc:gridLayoutConstraint columnSpan="3"/>
+
+      <tc:date id="date" fieldId="field" label="Date"/>
+    </tc:panel>
+
+    <tc:panel/>
+    <tc:button label="Any" id="b-1"/>
+    <tc:button label="Default" id="b-2" defaultCommand="true"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/link-attribute.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/link-attribute.selenium.html
new file mode 100644
index 0000000..b7b06d3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/link-attribute.selenium.html
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/button/link-attribute.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:button-internal-link-with-slash</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyTextPresent</td>
+	<td>A simple page for the resource test (static).</td>
+	<td></td>
+</tr>
+<tr>
+	<td>open</td>
+	<td>/faces/test/button/link-attribute.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:button-internal-link-without-slash</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyTextPresent</td>
+	<td>A simple page for the resource test (static).</td>
+	<td></td>
+</tr>
+<tr>
+	<td>open</td>
+	<td>/faces/test/button/link-attribute.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:button-external-link</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyTextPresent</td>
+	<td>TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION</td>
+	<td></td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/link-attribute.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/link-attribute.xhtml
new file mode 100644
index 0000000..78ecfe6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/link-attribute.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto"/>
+    </f:facet>
+
+    <tc:button id="button-internal-link-with-slash" label="internal link with slash" link="/test/button/plain.html"/>
+    <tc:button id="button-internal-link-without-slash" label="internal link without slash" link="plain.html"/>
+    <tc:button id="button-external-link" label="external link" link="http://www.apache.org/licenses/LICENSE-2.0.txt"/>
+    <tc:button id="button-internal-link-with-slash-and-param" label="internal link with slash and param" link="/test/button/plain.html?foo=&quot;page:id&quot;"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain.html
new file mode 100644
index 0000000..1335b3b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain.html
@@ -0,0 +1,22 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html>
+<body>
+A simple page for the resource test (static).
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain.xhtml
new file mode 100644
index 0000000..f83c975
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page" width="300px" height="50px">
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:out value="A simple page for the resource test (dynamic)."/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain_de.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain_de.html
new file mode 100644
index 0000000..af1ec77
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain_de.html
@@ -0,0 +1,22 @@
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html>
+<body>
+Eine einfache Seite für den Resourcen-Test (statisch).
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain_de.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain_de.xhtml
new file mode 100644
index 0000000..f097e06
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/button/plain_de.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page" width="300px" height="50px">
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:out value="Eine einfache Seite für den Resourcen-Test (dynamisch)."/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/3x3-center.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/3x3-center.xhtml
new file mode 100644
index 0000000..01318c6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/3x3-center.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;100px;*" columns="*;100px;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="300px" height="300px"/>
+
+    <tc:panel>
+      <tc:gridLayoutConstraint columnSpan="3"/>
+    </tc:panel>
+
+    <tc:panel/>
+    <tc:image value="pidgeon-point.jpg" id="in"/>
+    <tc:panel/>
+
+    <tc:panel>
+      <tc:gridLayoutConstraint columnSpan="3"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:in', 100, 100, 100, 100);"/>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/position-4x4-span-steps.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/position-4x4-span-steps.xhtml
new file mode 100644
index 0000000..97551c4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/position-4x4-span-steps.xhtml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="6*;9*;13*;2*" rows="4*;11*;10*;5*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="315px" height="315px"/>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+    <tc:panel>
+      <tc:gridLayoutConstraint rowSpan="2"/>
+      <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    </tc:panel>
+    <tc:panel>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+      <tc:image id="i-2" value="pidgeon-point.jpg"/>
+    </tc:panel>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+    <tc:panel>
+      <tc:gridLayoutConstraint rowSpan="2"/>
+      <tc:image id="i-4" value="pidgeon-point.jpg"/>
+    </tc:panel>
+    <tc:image id="i-5" value="pidgeon-point.jpg"/>
+    <tc:panel>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+      <tc:image  id="i-6" value="pidgeon-point.jpg"/>
+    </tc:panel>
+    <tc:panel>
+      <tc:gridLayoutConstraint rowSpan="2"/>
+      <tc:image id="i-7" value="pidgeon-point.jpg"/>
+    </tc:panel>
+    <tc:image id="i-8" value="pidgeon-point.jpg"/>
+    <tc:panel>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+      <tc:image id="i-9" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 60, 40);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 65, 0, 90, 155);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 160, 0, 155, 40);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 0, 45, 60, 110);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-4', 160, 45, 130, 215);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-5', 295, 45, 20, 110);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-6', 0, 160, 155, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-7', 295, 160, 20, 155);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-8', 0, 265, 60, 50);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-9', 65, 265, 225, 50);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/subview.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/subview.xhtml
new file mode 100644
index 0000000..3947f3c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/cell/subview.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="100px" height="310px"/>
+
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:panel>
+      <f:subview id="subview">
+        <tc:panel>
+          <f:facet name="layout">
+            <tc:gridLayout rows="100px;100px"/>
+          </f:facet>
+
+          <tc:image id="i-2" value="pidgeon-point.jpg"/>
+          <tc:image id="i-3" value="pidgeon-point.jpg"/>
+        </tc:panel>
+      </f:subview>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 0, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:subview:i-2', 0, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:subview:i-3', 0, 210, 100, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date-layout.xhtml
new file mode 100644
index 0000000..23a3348
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date-layout.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:date id="s1"/>
+
+    <tc:date label="normal" fieldId="s2"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 158, 20);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 309, 25, 158, 20);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date-tobago-1105.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date-tobago-1105.xhtml
new file mode 100644
index 0000000..01eb5a9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date-tobago-1105.xhtml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:box>
+      <f:facet name="layout">
+        <tc:gridLayout columns="2*;*" rows="auto;auto;auto;auto;auto"/>
+      </f:facet>
+      <tc:gridLayoutConstraint width="900px" height="300px" marginLeft="10px" marginTop="10px" marginRight="10px"/>
+
+      <tc:date readonly="#{false}" id="normal">
+        <f:convertDateTime/>
+      </tc:date>
+      <tc:datePicker for="normal" id="normalPicker"/>
+
+      <tc:date readonly="#{true}" id="readonly">
+        <f:convertDateTime/>
+      </tc:date>
+      <tc:datePicker for="readonly" id="readonlyPicker"/>
+
+      <tc:date disabled="#{true}" id="disabled">
+        <f:convertDateTime/>
+      </tc:date>
+      <tc:datePicker for="disabled" id="disabledPicker"/>
+
+      <tc:script file="script/tobago-assert.js"/>
+
+      <tc:script onload="check()">
+        function check() {
+          // assertions
+          var id0 = "page:normalPicker";
+          if (jQuery(Tobago.Utils.escapeClientId(id0)).filter("a").size() == 0) {
+            LOG.error("The element with id='" + id0 + "' was not found or is not an 'a' tag!");
+          }
+
+          // assertions
+          var id1 = "page:readonlyPicker";
+          if (jQuery(Tobago.Utils.escapeClientId(id1)).filter("span").size() == 0) {
+            LOG.error("The element with id='" + id1 + "' was not found or is not a 'span' tag!");
+          }
+
+          // assertions
+          var id2 = "page:disabledPicker";
+          if (jQuery(Tobago.Utils.escapeClientId(id2)).filter("span").size() == 0) {
+            LOG.error("The element with id='" + id2 + "' was not found or is not a 'span' tag!");
+          }
+        }
+      </tc:script>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date.xhtml
new file mode 100644
index 0000000..6f26824
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/date.xhtml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:box>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;*" rows="auto;auto;auto;auto;auto;auto;auto;auto;*;auto"/>
+      </f:facet>
+      <tc:gridLayoutConstraint width="900px" height="300px" marginLeft="10px" marginTop="10px" marginRight="10px"/>
+
+      <tc:date/>
+      <tc:date>
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only"/>
+
+      <tc:date readonly="true"/>
+      <tc:date readonly="true">
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only" readonly="true"/>
+
+      <tc:date disabled="true"/>
+      <tc:date disabled="true">
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only" disabled="true"/>
+
+      <tc:date markup="error"/>
+      <tc:date markup="error">
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only" markup="error"/>
+
+      <tc:date label="Date"/>
+      <tc:date label="Date/Time">
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="In" value="for comparison only"/>
+
+      <tc:date label="Date" readonly="true"/>
+      <tc:date label="Date/Time" readonly="true">
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="In" value="for comparison only" readonly="true"/>
+
+      <tc:date label="Date" disabled="true"/>
+      <tc:date label="Date/Time" disabled="true">
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="In" value="for comparison only" disabled="true"/>
+
+      <tc:date label="Date" markup="error"/>
+      <tc:date label="Date/Time" markup="error">
+        <f:convertDateTime type="date" pattern="dd.MM.yyyy HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="In" value="for comparison only" markup="error"/>
+
+      <tc:panel/>
+      <tc:panel/>
+      <tc:panel/>
+
+      <tc:panel/>
+      <tc:panel/>
+      <tc:button label="Submit"/>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/datetime.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/datetime.js
new file mode 100644
index 0000000..99c0f85
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/datetime.js
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+TestDateTime = {};
+
+TestDateTime.init = function () {
+
+  var panel = jQuery("#page\\:jquery_date_time_pattern");
+  var inputs = panel.children(".tobago-in, .tobago-date");
+
+  for (var i = 0; i < inputs.length; i += 5) {
+    var javaPattern = inputs.eq(i);
+    var javaFormatted = inputs.eq(i + 1);
+    var jQueryUIDatePattern = inputs.eq(i + 2);
+    var jQueryUITimePattern = inputs.eq(i + 3);
+    var jQueryUIFormatted = inputs.eq(i + 4);
+    var result = jQueryUIFormatted.next();
+
+    var pattern = javaFormatted.data("tobago-pattern");
+    javaPattern.val(pattern);
+
+    var analyzed = Tobago.DateTime.analyzePattern(pattern);
+
+    jQueryUIDatePattern.val(analyzed.dateFormat);
+    jQueryUITimePattern.val(analyzed.timeFormat);
+
+    try {
+      var javaValue = javaFormatted.val();
+      var date = null; // type: JS date
+      var time = null; // type: jQuery UI time object
+      var jQueryValue = null;
+      var i18n = javaFormatted.data("tobago-date-time-i18n");
+      switch (analyzed.type) {
+        case "datetime":
+          date = jQuery.datepicker.parseDateTime(
+              analyzed.dateFormat, analyzed.timeFormat, javaValue, i18n, {
+                separator: analyzed.separator,
+                // workaround for bug: https://github.com/trentrichardson/jQuery-Timepicker-Addon/issues/736
+                timeFormat: analyzed.timeFormat
+              }
+          );
+          time = {
+            hour: date.getHours(),
+            minute: date.getMinutes(),
+            second: date.getSeconds(),
+            millisec: date.getMilliseconds(),
+            microsec: date.getMicroseconds()
+          };
+          jQueryValue
+              = jQuery.datepicker.formatDate(analyzed.dateFormat, date, i18n)
+              + analyzed.separator
+              + jQuery.datepicker.formatTime(analyzed.timeFormat, time, i18n);
+          break;
+        case "date":
+          date = jQuery.datepicker.parseDate(analyzed.dateFormat, javaValue, i18n);
+          jQueryValue = jQuery.datepicker.formatDate(analyzed.dateFormat, date, i18n);
+          break;
+        case "time":
+          time = jQuery.datepicker.parseTime(analyzed.timeFormat, javaValue, i18n);
+          jQueryValue = jQuery.datepicker.formatTime(analyzed.timeFormat, time, i18n);
+          break;
+        default:
+          console.error("invalid: not date-pattern nor time-pattern");  // @DEV_ONLY
+          jQueryValue = "no type";
+      }
+      jQueryUIFormatted.val(jQueryValue);
+
+    } catch (e) {
+      console.error(e);
+    }
+
+    if (javaFormatted.val() != jQueryUIFormatted.val()) {
+      jQueryUIFormatted.addClass("tobago-in-markup-error");
+
+      if (javaPattern.hasClass("tobago-in-markup-error")) {
+        result.addClass("tobago-label-markup-warn");
+        result.html("java pattern broken");
+      } else {
+        result.addClass("tobago-label-markup-error");
+        result.html("pattern conversion failed");
+      }
+    } else {
+      result.addClass("tobago-label-markup-info");
+      if (javaPattern.hasClass("tobago-in-markup-error")) {
+        result.html("fixed");
+      } else {
+        result.html("okay");
+      }
+    }
+  }
+};
+
+TestDateTime.test = function () {
+  TestDateTime.testDate();
+  TestDateTime.testTime();
+  TestDateTime.testBoth();
+};
+
+TestDateTime.testDate = function () {
+
+  var date;
+  var format = "dd.mm.yy";
+  var initial = "13.05.2014";
+  var result;
+
+  date = jQuery.datepicker.parseDate(format, initial);
+  result = jQuery.datepicker.formatDate(format, date);
+
+  if (result != initial) {
+    console.error("Error!");
+  } else {
+    console.info("Okay!");
+  }
+
+};
+
+TestDateTime.testTime = function () {
+
+  var date;
+  var format = "HH:mm:ss";
+  var initial = "14:06:55";
+  var result;
+
+  date = jQuery.datepicker.parseTime(format, initial);
+  result = jQuery.datepicker.formatTime(format, date);
+
+  if (result != initial) {
+    console.error("Error!");
+  } else {
+    console.info("Okay!");
+  }
+
+};
+
+TestDateTime.testBoth = function () {
+
+  var date, dateT;
+  var formatD = "dd.mm.yy";
+  var formatT = "HH:mm:ss";
+  var initial = "13.05.2014 13:05:55";
+  var result;
+  var separator = " ";
+
+  date = jQuery.datepicker.parseDateTime(formatD, formatT, initial);
+  dateT = {
+    hour: date.getHours(),
+    minute: date.getMinutes(),
+    second: date.getSeconds(),
+    millisec: date.getMilliseconds(),
+    microsec: date.getMicroseconds()
+  };
+  result = jQuery.datepicker.formatDate(formatD, date) + separator + jQuery.datepicker.formatTime(formatT, dateT);
+
+  if (result != initial) {
+    console.error("Error!");
+  } else {
+    console.info("Okay!");
+  }
+
+};
+
+Tobago.registerListener(TestDateTime.init, Tobago.Phase.DOCUMENT_READY);
+
+Tobago.registerListener(TestDateTime.test, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/datetime.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/datetime.xhtml
new file mode 100644
index 0000000..c683358
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/date/datetime.xhtml
@@ -0,0 +1,496 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    locale="DE"
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+<tc:page id="page">
+
+<tc:panel>
+
+<tc:panel id="jquery_date_time_pattern">
+<f:facet name="layout">
+  <tc:gridLayout columns="2*;2*;2*;*;*;2*;2*"
+                 rows="auto;60px;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+</f:facet>
+
+<tc:label value="Name"/>
+<tc:label value="Java Pattern"/>
+<tc:label value="Java Formatted"/>
+<tc:label value="jQuery UI Pattern">
+  <tc:gridLayoutConstraint columnSpan="2"/>
+</tc:label>
+<tc:label value="jQuery UI Formatted"/>
+<tc:label value="Result"/>
+
+<tc:label value="Comment"/>
+<tc:out value="Error means, that the pattern that comes from the server is invalid.
+    This is defined manually on the page."/>
+<tc:out/>
+<tc:out value="date"/>
+<tc:out value="time"/>
+<tc:out value="Error means, that the date parsed and formatted is unequal to the original.
+    The error state is computed with the JS functions."/>
+<tc:out/>
+
+<!-- y - year -->
+
+<tc:label value="1 y (wrong, but fixable)"/>
+<tc:in readonly="true" markup="error"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.y"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="2 y"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.yy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="3 y (wrong, but fixable)"/>
+<tc:in readonly="true" markup="error"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.yyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="4 y"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="5 y (can't fix)"/>
+<tc:in readonly="true" markup="error"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.yyyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="6 y (can't fix)"/>
+<tc:in readonly="true" markup="error"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.yyyyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- M - month -->
+
+<tc:label value="1 M"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.M.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="2 M"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="3 M"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd. MMM yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="4 M"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd. MMMM yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="5 M"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd. MMMMM yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- L - month (stand alone) -->
+
+<!--
+    <tc:label value="1 L"/>
+    <tc:in readonly="true"/>
+    <tc:date value="#{dateController.once}">
+      <f:convertDateTime pattern="L"/>
+    </tc:date>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:label/>
+
+    <tc:label value="2 L"/>
+    <tc:in readonly="true"/>
+    <tc:date value="#{dateController.once}">
+      <f:convertDateTime pattern="LL"/>
+    </tc:date>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:label/>
+
+    <tc:label value="3 L"/>
+    <tc:in readonly="true"/>
+    <tc:date value="#{dateController.once}">
+      <f:convertDateTime pattern="LLL"/>
+    </tc:date>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:label/>
+
+    <tc:label value="4 L"/>
+    <tc:in readonly="true"/>
+    <tc:date value="#{dateController.once}">
+      <f:convertDateTime pattern="LLLL"/>
+    </tc:date>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:label/>
+
+    <tc:label value="5 L"/>
+    <tc:in readonly="true"/>
+    <tc:date value="#{dateController.once}">
+      <f:convertDateTime pattern="LLLLL"/>
+    </tc:date>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:in readonly="true"/>
+    <tc:label/>
+-->
+
+<!-- d - day -->
+
+<tc:label value="1 d"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="d.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="2 d"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="3 d (can't fix)"/>
+<tc:in readonly="true" markup="error"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="ddd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- E - day name in week -->
+
+<tc:label value="1 E"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="E, dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="2 E"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="EE, dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="3 E"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="EEE, dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="4 E"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="EEEE, dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="5 E"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="EEEEE, dd.MM.yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+
+<!-- D - day in year -->
+
+<tc:label value="1 D"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="D yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="2 D"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="DD yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="3 D"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="DDD yyyy"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- dateStyle -->
+
+<tc:label value="dateStyle=short"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="short"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="dateStyle=medium"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="medium"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="dateStyle=long"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="long"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="dateStyle=full"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="full"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- time -->
+
+<tc:label value="?"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="HH:mm:ss" type="time"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- timeStyle -->
+
+<tc:label value="timeStyle=short"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime timeStyle="short" type="time"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="timeStyle=medium"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime timeStyle="medium" type="time"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="timeStyle=long"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime timeStyle="long" type="time"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="timeStyle=full"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime timeStyle="full" type="time"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- date time -->
+
+<tc:label value="?"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss.SSS"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<!-- dateStyle + TimeStyle -->
+
+<tc:label value="dateStyle=timeStyle=short"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="short" timeStyle="short" type="both"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="dateStyle=timeStyle=medium"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="medium" timeStyle="medium" type="both"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="dateStyle=timeStyle=long"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="long" timeStyle="long" type="both"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+<tc:label value="dateStyle=timeStyle=full"/>
+<tc:in readonly="true"/>
+<tc:date value="#{dateController.once}">
+  <f:convertDateTime dateStyle="full" timeStyle="full" type="both"/>
+</tc:date>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:in readonly="true"/>
+<tc:label/>
+
+
+</tc:panel>
+
+</tc:panel>
+
+<tc:script file="test/date/datetime.js"/>
+
+</tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/error/display-exception.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/error/display-exception.xhtml
new file mode 100644
index 0000000..85737f8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/error/display-exception.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:box label="An Exception has occured">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;*"/>
+      </f:facet>
+
+      <tc:messages/>
+      <tc:out
+          value="This page will be shown, when an org.apache.myfaces.tobago.example.test.ErrorTestException occures!"/>
+
+    </tc:box>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/error/throw-exception.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/error/throw-exception.xhtml
new file mode 100644
index 0000000..7b42601
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/error/throw-exception.xhtml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:box label="Error Test">
+      <f:facet name="layout">
+        <tc:gridLayout rows="100px;auto"/>
+      </f:facet>
+
+      <tc:panel>
+        Please click the button, that will throw an exception!
+      </tc:panel>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;auto"/>
+        </f:facet>
+
+        <tc:panel/>
+        <tc:button label="Error" action="#{errorTest.error}"/>
+      </tc:panel>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/file/file-markup.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/file/file-markup.xhtml
new file mode 100644
index 0000000..2c0d92b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/file/file-markup.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:file/>
+    <tc:file required="true"/>
+    <tc:file disabled="true"/>
+    <tc:file readonly="true"/>
+    <tc:file markup="info"/>
+    <tc:file markup="warn"/>
+    <tc:file markup="error"/>
+    <tc:file markup="fatal"/>
+    <tc:button label="OK" action="#{upload.upload}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/file/file.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/file/file.xhtml
new file mode 100644
index 0000000..64e7027
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/file/file.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+
+    <tc:messages/>
+
+    <tc:file value="#{upload.file}" required="true"/>
+    <tc:button label="OK" action="#{upload.upload}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-horizontal.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-horizontal.xhtml
new file mode 100644
index 0000000..b05e20e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-horizontal.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:flexLayout columns="*;auto;100px;2*">
+
+      <tc:textarea value="Left 1*"/>
+      <tc:image value="pidgeon-point.jpg"/>
+      <tc:textarea value="100px"/>
+      <tc:textarea value="Right 2*"/>
+
+    </tc:flexLayout>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-simple.xhtml
new file mode 100644
index 0000000..7539acf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-simple.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:flexLayout columns="*;2*">
+      <tc:textarea value="Left"/>
+      <tc:textarea value="Right"/>
+    </tc:flexLayout>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-vertical.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-vertical.xhtml
new file mode 100644
index 0000000..e1f9027
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flexLayout/flexLayout-vertical.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint height="500px"/>
+
+    <tc:flexLayout rows="*;auto;100px;2*">
+
+      <tc:textarea value="Top 1*"/>
+      <tc:image value="pidgeon-point.jpg"/>
+      <tc:textarea value="100px"/>
+      <tc:textarea value="Bottom 2*"/>
+
+    </tc:flexLayout>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flowLayout/flowLayout-textAlign.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flowLayout/flowLayout-textAlign.xhtml
new file mode 100644
index 0000000..c9ecd40
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/flowLayout/flowLayout-textAlign.xhtml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="20px;auto;20px;auto;20px;auto;60px;"/>
+    </f:facet>
+
+    <tc:flowLayout textAlign="left">
+      <tc:out id="left" value="left">
+        <tc:dataAttribute name="assert-left" value="0"/>
+        <tc:dataAttribute name="assert-top" value="0"/>
+        <tc:dataAttribute name="assert-width" value="16"/>
+        <tc:dataAttribute name="assert-height" value="14"/>
+        <tc:dataAttribute name="assert-epsilon" value="1"/>
+      </tc:out>
+    </tc:flowLayout>
+
+    <tc:separator/>
+
+    <tc:flowLayout textAlign="right">
+      <tc:out id="right" value="right">
+        <tc:dataAttribute name="assert-left" value="577"/>
+        <tc:dataAttribute name="assert-top" value="31"/>
+        <tc:dataAttribute name="assert-width" value="23"/>
+        <tc:dataAttribute name="assert-height" value="14"/>
+        <tc:dataAttribute name="assert-epsilon" value="1"/>
+      </tc:out>
+    </tc:flowLayout>
+
+    <tc:separator/>
+
+    <tc:flowLayout textAlign="center">
+      <tc:out id="center" value="center">
+        <tc:dataAttribute name="assert-left" value="283"/>
+        <tc:dataAttribute name="assert-top" value="62"/>
+        <tc:dataAttribute name="assert-width" value="33"/>
+        <tc:dataAttribute name="assert-height" value="14"/>
+        <tc:dataAttribute name="assert-epsilon" value="1"/>
+      </tc:out>
+    </tc:flowLayout>
+
+    <tc:separator/>
+
+    <tc:flowLayout textAlign="justify">
+      1_XXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX XXXXXXXXXXX
+      2_XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX XXXXXXXXXX
+      3_XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX
+      <tc:out id="justify" value="justify">
+        <tc:dataAttribute name="assert-left" value="569"/>
+        <tc:dataAttribute name="assert-top" value="122"/>
+        <tc:dataAttribute name="assert-width" value="31"/>
+        <tc:dataAttribute name="assert-height" value="14"/>
+        <tc:dataAttribute name="assert-epsilon" value="1"/>
+      </tc:out>
+      4_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
+    </tc:flowLayout>
+
+    <!--<tc:script file="script/tobago-assert.js"/>-->
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/footer/footer-fixed.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/footer/footer-fixed.xhtml
new file mode 100644
index 0000000..f018a25
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/footer/footer-fixed.xhtml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns="http://www.w3.org/1999/xhtml">
+
+  <tc:page>
+
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+
+    <tc:footer fixed="true">
+      Fixed Footer
+    </tc:footer>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/footer/footer.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/footer/footer.xhtml
new file mode 100644
index 0000000..bcfde6d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/footer/footer.xhtml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns="http://www.w3.org/1999/xhtml">
+
+  <tc:page>
+
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+
+    <tc:footer>
+      Scrolling Footer
+    </tc:footer>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/dynamic-include.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/dynamic-include.xhtml
new file mode 100644
index 0000000..b4403f8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/dynamic-include.xhtml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<f:view xmlns="http://www.w3.org/1999/xhtml"
+        xmlns:ui="http://java.sun.com/jsf/facelets"
+        xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:h="http://java.sun.com/jsf/html"
+        xmlns:tc="http://myfaces.apache.org/tobago/component"
+            xmlns:c="http://java.sun.com/jsp/jstl/core"
+        xmlns="http://www.w3.org/1999/xhtml">
+
+  <tc:page width="800px" height="800px" label="Dynamic Include">
+    <tc:box label="Dynamic Included Panels">
+      <f:facet name="layout">
+        <tc:gridLayout margin="10px" columns="500px" rows="100px;auto;auto;auto;auto;auto"/>
+      </f:facet>
+      <tc:panel>
+        <p>
+          This example demonstrates dynamic includes with Facelets.
+        </p>
+        <p>
+          <b>Important:</b> Use the "panel" variable only in Facelet Tags like ui:include, not in Components!
+        </p>
+        <p>
+          <b>Important:</b> The action has to return a view-id, and not null,
+          So you ensure you get a new view, and no problems with ids.
+        </p>
+        <p>
+          TODO: Automatic test with Selenium!
+        </p>
+      </tc:panel>
+      <tc:messages/>
+      <c:forEach var="panel" items="#{dynamic.panels}">
+        <ui:include src="#{panel.name}"/>
+      </c:forEach>
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="100px;100px;*" rows="auto"/>
+        </f:facet>
+        <tc:button label="Next" action="#{dynamic.addPanel}"/>
+        <tc:button label="Reset" immediate="true" action="#{dynamic.reset}"/>
+      </tc:panel>
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-one-fragment.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-one-fragment.xhtml
new file mode 100644
index 0000000..e1f2214
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-one-fragment.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<ui:composition
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:tc="http://myfaces.apache.org/tobago/component">
+
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout margin="10px" columns="500px" rows="auto;auto"/>
+    </f:facet>
+    <tc:separator label="Panel One"/>
+    <tc:in label="Value One" value="#{panel1.value}" />
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-three-fragment.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-three-fragment.xhtml
new file mode 100644
index 0000000..06c4c59
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-three-fragment.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<ui:composition
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:tc="http://myfaces.apache.org/tobago/component">
+
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout margin="10px" columns="500px" rows="auto;auto"/>
+    </f:facet>
+    <tc:separator label="Panel Three"/>
+    <tc:in label="Street" value="#{panel3.street}" />
+    <tc:in label="City" value="#{panel3.city}" />
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-two-fragment.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-two-fragment.xhtml
new file mode 100644
index 0000000..9aa0318
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/forEach/panel-two-fragment.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+* Licensed to the Apache Software Foundation (ASF) under one or more
+* contributor license agreements.  See the NOTICE file distributed with
+* this work for additional information regarding copyright ownership.
+* The ASF licenses this file to You under the Apache License, Version 2.0
+* (the "License"); you may not use this file except in compliance with
+* the License.  You may obtain a copy of the License at
+*
+*      http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+-->
+
+<ui:composition
+    xmlns="http://www.w3.org/1999/xhtml"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:tc="http://myfaces.apache.org/tobago/component">
+
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout margin="10px" columns="500px" rows="auto;auto"/>
+    </f:facet>
+    <tc:separator label="Panel Two"/>
+    <tc:in label="First Name" value="#{panel2.firstName}" />
+    <tc:in label="Second Name" value="#{panel2.secondName}" />
+  </tc:panel>
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/auto-vertical-in+in.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/auto-vertical-in+in.xhtml
new file mode 100644
index 0000000..a182002
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/auto-vertical-in+in.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;*"/>
+    </f:facet>
+
+    <tc:in id="in-0" value="0">
+      <tc:gridLayoutConstraint width="60px" height="30px"/>
+    </tc:in>
+    <tc:in id="in-1" value="1"/>
+    <tc:panel/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:in-0', 0, 0, 60, 30);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:in-1', 0, 35, 600, 20);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-border+padding.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-border+padding.xhtml
new file mode 100644
index 0000000..077b231
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-border+padding.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="500px"/>
+
+    <tc:panel id="panel">
+      <tc:gridLayoutConstraint
+          borderLeft="10px" borderRight="20px" borderTop="30px" borderBottom="40px"
+          paddingLeft="50px" paddingRight="60px" paddingTop="70px" paddingBottom="80px"/>
+      <tc:textarea
+          id="text"
+          value="panel has borderLeft='10px' borderRight='20px' borderTop='30px' borderBottom='40px' paddingLeft='50px' paddingRight='60px' paddingTop='70px' paddingBottom='80px'"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:text', 60, 100, 360, 280);"/>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-border.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-border.xhtml
new file mode 100644
index 0000000..ca2259e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-border.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="500px"/>
+
+    <tc:panel id="panel">
+      <tc:gridLayoutConstraint borderLeft="10px" borderRight="20px" borderTop="30px" borderBottom="40px"/>
+      <tc:textarea id="text" 
+                   value="panel has borderLeft='10px' borderRight='20px' borderTop='30px' borderBottom='40px'"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:text', 10, 30, 470, 430);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-padding.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-padding.xhtml
new file mode 100644
index 0000000..36f474a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/constraints-padding.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="500px"/>
+
+    <tc:panel id="panel">
+      <tc:gridLayoutConstraint paddingLeft="10px" paddingRight="20px" paddingTop="30px" paddingBottom="40px"/>
+      <tc:textarea id="text"
+                   value="panel has paddingLeft='10px' paddingRight='20px' paddingTop='30px' paddingBottom='40px'"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:text', 10, 30, 470, 430);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/current-vs-preferred-in-auto.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/current-vs-preferred-in-auto.xhtml
new file mode 100644
index 0000000..60c2c8f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/current-vs-preferred-in-auto.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto" rows="auto"/>
+    </f:facet>
+
+    <tc:button label="looooooooooong">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="0"/>
+      <tc:dataAttribute name="assert-width" value="128"/>
+      <tc:dataAttribute name="assert-height" value="20"/>
+      <tc:dataAttribute name="assert-epsilon" value="20"/>
+    </tc:button>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-asterisk-default.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-asterisk-default.xhtml
new file mode 100644
index 0000000..b091abc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-asterisk-default.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*"/>
+    </f:facet>
+
+    <tc:in id="in" value="Width should be 600px"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertWidth('page:in', 600);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-default-300px.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-default-300px.xhtml
new file mode 100644
index 0000000..d7785a2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-default-300px.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:in id="in" value="Width should be 300px">
+      <tc:gridLayoutConstraint width="300px"/>
+    </tc:in>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertWidth('page:in', 300);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-default-default.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-default-default.xhtml
new file mode 100644
index 0000000..a18ecd3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-600px-default-default.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:in id="in" value="Width should be 600px"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertWidth('page:in', 600);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-default-default-600px.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-default-default-600px.xhtml
new file mode 100644
index 0000000..d508bcf
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/horizontal-default-default-600px.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+
+    <tc:in id="in" value="Width should be 600px">
+      <tc:gridLayoutConstraint width="600px"/>
+    </tc:in>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertWidth('page:in', 600);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/margin-fallback.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/margin-fallback.xhtml
new file mode 100644
index 0000000..d1d3909
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/margin-fallback.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout margin="50"/>
+    </f:facet>
+
+    <tc:image id="id" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:id', 50, 50, 500, 500);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/margin.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/margin.xhtml
new file mode 100644
index 0000000..4fc100b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/margin.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout marginLeft="10" marginTop="20px" marginRight="30" marginBottom="40px"/>
+<!--
+      <tc:gridLayout marginLeft="10" marginTop="20px" marginRight="#{10+20}" marginBottom='#{"40px"}'/>
+-->
+    </f:facet>
+
+    <tc:image id="id" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:id', 10, 20, 560, 540);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-4.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-4.xhtml
new file mode 100644
index 0000000..f2aa32b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-4.xhtml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="220px" height="220px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" rows="*;*" columnSpacing="20px" rowSpacing="20px"/>
+    </f:facet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*" rows="*"/>
+      </f:facet>
+
+      <tc:image id="image-1" value="pidgeon-point.jpg"/>
+
+    </tc:panel>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*" rows="*"/>
+      </f:facet>
+
+      <tc:image id="image-2" value="pidgeon-point.jpg"/>
+
+    </tc:panel>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*" rows="*"/>
+      </f:facet>
+
+      <tc:image id="image-3" value="pidgeon-point.jpg"/>
+
+    </tc:panel>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*" rows="*;*"/>
+      </f:facet>
+
+      <tc:image id="image-41" value="pidgeon-point.jpg"/>
+      <tc:image id="image-42" value="pidgeon-point.jpg"/>
+
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 0, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-2', 120, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-3', 0, 120, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-41', 120, 120, 100, 47);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-42', 120, 172, 100, 48);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-simple.xhtml
new file mode 100644
index 0000000..fe5f463
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-simple.xhtml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="120px" height="180px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*" rows="*"/>
+    </f:facet>
+
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*" rows="*"/>
+      </f:facet>
+
+      <tc:image id="image" value="pidgeon-point.jpg"/>
+
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image', 0, 0, 120, 180);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-v.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-v.xhtml
new file mode 100644
index 0000000..6d44fe3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested-v.xhtml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="500px" height="500px"/>
+
+      <f:facet name="layout">
+        <tc:gridLayout id="page-grid" rows="*;auto"/>
+      </f:facet>
+
+      <tc:textarea id="textarea"/>
+
+      <tc:panel id="panel">
+        <f:facet name="layout">
+          <tc:gridLayout id="panel-grid" columns="*;100px"/>
+        </f:facet>
+        <tc:panel id="cell"/>
+        <tc:button id="button" label="Submit"/>
+      </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:textarea', 0, 0, 500, 475);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:button', 400, 480, 100, 20);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested.xhtml
new file mode 100644
index 0000000..0717cc2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/nested.xhtml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="100px;205px;*;2*" rows="*;*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="650px" height="310px"/>
+
+    <tc:image id="x_5" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="3"/>
+    </tc:image>
+
+    <tc:image id="x_6" value="pidgeon-point.jpg"/>
+
+    <tc:image id="x_13" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+
+    <tc:panel id="x_14">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+      <f:facet name="layout">
+        <tc:gridLayout columns="130px;*"/>
+      </f:facet>
+      <tc:image id="x_14_a" value="pidgeon-point.jpg"/>
+      <tc:image id="x_14_b" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:panel id="x_7">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;2*"/>
+      </f:facet>
+      <tc:image id="x_7_a" value="pidgeon-point.jpg"/>
+      <tc:image id="x_7_b" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:panel id="x_10">
+      <f:facet name="layout">
+        <tc:gridLayout columns="4*;*"/>
+      </f:facet>
+      <tc:image id="x_10_a" value="pidgeon-point.jpg"/>
+      <tc:image id="x_10_b" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:image id="x_17" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:x_5', 0, 0, 100, 310);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:x_6', 105, 0, 205, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:x_13', 315, 0, 110, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:x_14', 430, 0, 220, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:x_14_a', 430, 0, 130, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:x_14_b', 565, 0, 85, 205);"/>
+    <!--todo: test the other controls ...-->
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/not-exact-4x4.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/not-exact-4x4.xhtml
new file mode 100644
index 0000000..f257dda
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/not-exact-4x4.xhtml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="6*;9*;13*;2*" rows="4*;11*;10*;5*"/>
+    </f:facet>
+    <!-- 211 (prime number) + 15px = 226px -->
+    <tc:gridLayoutConstraint width="226px" height="226px"/>
+
+    <tc:image id="image-0" value="pidgeon-point.jpg"/>
+    <tc:image id="image-1" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="image-2" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+    <tc:image id="image-3" value="pidgeon-point.jpg"/>
+    <tc:image id="image-4" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="image-5" value="pidgeon-point.jpg"/>
+    <tc:image id="image-6" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+    <tc:image id="image-7" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="image-8" value="pidgeon-point.jpg"/>
+    <tc:image id="image-9" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 42, 28);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 47, 0, 63, 111);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-2', 115, 0, 111, 28);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-3', 0, 33, 42, 78);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-4', 115, 33, 92, 153);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-5', 212, 33, 14, 78);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-6', 0, 116, 110, 70);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-7', 212, 116, 14, 110);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-8', 0, 191, 42, 35);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-9', 47, 191, 160, 35);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/not-exact.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/not-exact.xhtml
new file mode 100644
index 0000000..85f3aad
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/not-exact.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" columnSpacing="0px"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="201px" height="200px"/>
+
+    <tc:image id="image-0" value="pidgeon-point.jpg"/>
+    <tc:image id="image-1" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 100, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 100, 0, 101, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-1+1x1-span.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-1+1x1-span.xhtml
new file mode 100644
index 0000000..051b556
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-1+1x1-span.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="*" columns="*;*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="610px" height="300px"/>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 405, 300);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 410, 0, 200, 300);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-10x10-span.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-10x10-span.xhtml
new file mode 100644
index 0000000..f9ed9b1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-10x10-span.xhtml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;*;*;*;*;*;*;*;*;*" columns="*;*;*;*;*;*;*;*;*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="1045px" height="1045px"/>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="9"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="9" rowSpan="1"/>
+    </tc:image>
+    <tc:image id="i-2" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="7" rowSpan="1"/>
+    </tc:image>
+    <tc:image id="i-3" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="7"/>
+    </tc:image>
+    <tc:image id="i-4" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="9"/>
+    </tc:image>
+    <tc:image id="i-5" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="7"/>
+    </tc:image>
+    <tc:image id="i-6" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="1"/>
+    </tc:image>
+    <tc:image id="i-7" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-8" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-9" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-10" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-11" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-12" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="1"/>
+    </tc:image>
+    <tc:image id="i-13" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="1"/>
+    </tc:image>
+    <tc:image id="i-14" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-15" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-16" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-17" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="1" rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-18" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2" rowSpan="1"/>
+    </tc:image>
+    <tc:image id="i-19" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="7" rowSpan="1"/>
+    </tc:image>
+    <tc:image id="i-20" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="9" rowSpan="1"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <!--todo-->
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 100, 940);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 105, 0, 940, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 105, 105, 730, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 840, 105, 100, 730);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-4', 945, 105, 100, 940);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-5', 105, 210, 100, 730);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-6', 210, 210, 205, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-7', 420, 210, 100, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-8', 525, 210, 205, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-9', 735, 210, 100, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-10', 210, 315, 205, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-11', 420, 420, 205, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-12', 630, 420, 205, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-13', 210, 525, 205, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-14', 630, 525, 205, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-15', 210, 630, 100, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-16', 315, 630, 205, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-17', 525, 630, 100, 205);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-18', 630, 735, 205, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-19', 210, 840, 730, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-20', 0, 945, 940, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-out.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-out.xhtml
new file mode 100644
index 0000000..1496148
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-out.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+
+    <tc:out id="out-0" value="Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Quisque consequat, libero eget porta mattis, risus velit congue magna, at posuere sem orci vitae turpis. Integer pulvinar. Cras libero. Proin vestibulum tempor urna. Nulla odio nisl, auctor vitae, faucibus pharetra, feugiat eget, justo. Suspendisse at tellus non justo dictum tincidunt."/>
+    <tc:out id="out-1" value="Aenean placerat nunc id tortor. Donec mollis ornare pede. Vestibulum ut arcu et dolor auctor varius. Praesent tincidunt, eros quis vulputate facilisis, orci turpis sollicitudin justo, id faucibus nunc orci sed purus. Proin ligula erat, sollicitudin id, rhoncus eget, nonummy sit amet, risus. Aenean arcu lorem, facilisis et, posuere sed, ultrices tincidunt, nunc. Sed ac massa. Quisque lacinia. Donec quis nibh."/>
+    <tc:out id="out-2" value="Aenean ac diam eget mi feugiat pulvinar. Etiam orci. Aliquam nec arcu nec eros ornare pulvinar. Sed nec velit. Ut ut orci."/>
+    <tc:out id="out-3" value="Nulla varius. Maecenas feugiat. Etiam varius ipsum et orci. Ut consectetuer odio sit amet libero. Nulla iaculis adipiscing purus. Maecenas a sed."/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:out-0', 0, 0, 400, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:out-1', 405, 0, 200, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:out-2', 0, 405, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:out-3', 405, 405, 200, 200);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-bottom.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-bottom.xhtml
new file mode 100644
index 0000000..019bbe6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-bottom.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+    
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 400, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 405, 0, 200, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 405, 605, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-left.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-left.xhtml
new file mode 100644
index 0000000..b5847f8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-left.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 400, 605);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 405, 0, 200, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 405, 405, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-right.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-right.xhtml
new file mode 100644
index 0000000..cdb6398
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-right.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 400, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 405, 0, 200, 605);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 405, 400, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-top.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-top.xhtml
new file mode 100644
index 0000000..f5da01f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2-span-top.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 605, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 0, 405, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 405, 405, 200, 200);"/>
+
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2.xhtml
new file mode 100644
index 0000000..6191196
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-2x2.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*" columnSpacing="0px" rowSpacing="0px"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 400, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 400, 0, 200, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 400, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 400, 400, 200, 200);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-4x4-span-steps.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-4x4-span-steps.xhtml
new file mode 100644
index 0000000..0dfeab6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/position-4x4-span-steps.xhtml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="6*;9*;13*;2*" rows="4*;11*;10*;5*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="315px" height="315px"/>
+
+    <tc:image id="image-0" value="pidgeon-point.jpg"/>
+    <tc:image id="image-1" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="image-2" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+    <tc:image id="image-3" value="pidgeon-point.jpg"/>
+    <tc:image id="image-4" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="image-5" value="pidgeon-point.jpg"/>
+    <tc:image id="image-6" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+    <tc:image id="image-7" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint rowSpan="2"/>
+    </tc:image>
+    <tc:image id="image-8" value="pidgeon-point.jpg"/>
+    <tc:image id="image-9" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <!--todo-->
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 60, 40);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 65, 0, 90, 155);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-2', 160, 0, 155, 40);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-3', 0, 45, 60, 110);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-4', 160, 45, 130, 215);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-5', 295, 45, 20, 110);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-6', 0, 160, 155, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-7', 295, 160, 20, 155);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-8', 0, 265, 60, 50);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-9', 65, 265, 225, 50);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/proportion-versus-minimum.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/proportion-versus-minimum.xhtml
new file mode 100644
index 0000000..76cac3a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/proportion-versus-minimum.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <!-- todo: support the automatical computed width of the scrollbar -->
+    <tc:gridLayoutConstraint width="320px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="100px;auto;*;*" columns="300px"/>
+    </f:facet>
+
+    <tc:textarea
+        readonly="true"
+        value="What happens, when a * is in a columns/rows definition, and the space for the * is too low: The column/row size will be set to the minium."/>
+    <tc:image id="image-1" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint minimumHeight="400px"/>
+    </tc:image>
+    <tc:image id="image-2" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint minimumHeight="400px"/>
+    </tc:image>
+    <tc:image id="image-3" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint minimumHeight="400px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 0, 105, 300, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-2', 0, 510, 300, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-3', 0, 915, 300, 400);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-1-cannot-match.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-1-cannot-match.xhtml
new file mode 100644
index 0000000..29d78fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-1-cannot-match.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="1000px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;*" rows="20px;100px;100px;100px;*"/>
+    </f:facet>
+
+    <tc:label value="one column with 'auto'"/>
+
+    <tc:label value="one column with '*'"/> 
+
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;auto"/>
+      </f:facet>
+
+      <tc:textarea id="a1" value="50/100/150">
+        <tc:gridLayoutConstraint minimumWidth="50px" preferredWidth="100px" maximumWidth="150px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a2" value="200/300/400">
+        <tc:gridLayoutConstraint minimumWidth="200px" preferredWidth="300px" maximumWidth="400px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a3" value="50/100/200">
+        <tc:gridLayoutConstraint minimumWidth="50px" preferredWidth="100px" maximumWidth="200px"/>
+      </tc:textarea>
+
+    </tc:panel>
+
+    <tc:textarea value="rest"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:panel', 0, 25, 510, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a1', 0, 25, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a2', 105, 25, 300, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a3', 410, 25, 100, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-1.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-1.xhtml
new file mode 100644
index 0000000..d928dc4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-1.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="1000px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;*" rows="20px;100px;100px;100px;*"/>
+    </f:facet>
+
+    <tc:label value="one column with 'auto'"/>
+
+    <tc:label value="one column with '*'"/> 
+
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;auto"/>
+      </f:facet>
+
+      <tc:textarea id="a1" value="50/100/150">
+        <tc:gridLayoutConstraint minimumWidth="50px" preferredWidth="100px" maximumWidth="200px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a2" value="200/300/400">
+        <tc:gridLayoutConstraint minimumWidth="50px" preferredWidth="300px" maximumWidth="400px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a3" value="50/100/200">
+        <tc:gridLayoutConstraint minimumWidth="50px" preferredWidth="100px" maximumWidth="200px"/>
+      </tc:textarea>
+
+    </tc:panel>
+
+    <tc:textarea value="rest"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:panel', 0, 25, 510, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a1', 0, 25, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a2', 105, 25, 300, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a3', 410, 25, 100, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-3.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-3.xhtml
new file mode 100644
index 0000000..8e5ee45
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-1-3.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="1000px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;*" rows="20px;100px;100px;100px;*"/>
+    </f:facet>
+
+    <tc:label value="one column with 'auto'"/>
+
+    <tc:label value="one column with '*'"/> 
+
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;3*;auto"/>
+      </f:facet>
+
+      <tc:textarea id="a1" value="100/200/300">
+        <tc:gridLayoutConstraint minimumWidth="100px" preferredWidth="200px" maximumWidth="300px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a2" value="400/500/600">
+        <tc:gridLayoutConstraint minimumWidth="400px" preferredWidth="500px" maximumWidth="600px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a3" value="100/100/100">
+        <tc:gridLayoutConstraint minimumWidth="100px" preferredWidth="100px" maximumWidth="100px"/>
+      </tc:textarea>
+
+    </tc:panel>
+
+    <tc:textarea value="rest" id="rest"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:panel', 0, 25, 810, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a1', 0, 25, 200, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a2', 205, 25, 500, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a3', 710, 25, 100, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-2-columns.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-2-columns.xhtml
new file mode 100644
index 0000000..2abe9d9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-2-columns.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto" rows="auto"/>
+    </f:facet>
+
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*"/>
+      </f:facet>
+
+      <tc:textarea id="a1">
+        <tc:gridLayoutConstraint width="300px" height="300px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a2"/>
+
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:panel', 0, 0, 505, 300);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a1', 0, 0, 300, 300);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a2', 305, 0, 200, 300);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-2-rows.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-2-rows.xhtml
new file mode 100644
index 0000000..cf739d6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/relative-inside-auto-2-rows.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto" rows="auto"/>
+    </f:facet>
+
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;*"/>
+      </f:facet>
+
+      <tc:textarea id="a1">
+        <tc:gridLayoutConstraint width="300px" height="300px"/>
+      </tc:textarea>
+
+      <tc:textarea id="a2"/>
+
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:panel', 0, 0, 300, 338);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a1', 0, 0, 300, 300);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a2', 0, 305, 300, 33);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-1.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-1.xhtml
new file mode 100644
index 0000000..6b2fef2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-1.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto" columns="auto;auto"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="400px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="200px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-2" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="400px" height="200px"/>
+    </tc:image>
+    <tc:image id="i-3" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="200px" height="200px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 405, 0, 200, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 405, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 405, 405, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-2.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-2.xhtml
new file mode 100644
index 0000000..74be4bc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-2.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto" columns="auto;auto"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="400px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="200px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-2" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="400px" height="200px"/>
+    </tc:image>
+    <tc:image id="i-3" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="200px" height="200px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 0, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 405, 0, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-3.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-3.xhtml
new file mode 100644
index 0000000..d2e67cd
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-3.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto" columns="auto;auto"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="400px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="200px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-2" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="400px" height="200px"/>
+    </tc:image>
+    <tc:image id="i-3" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="200px" height="200px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 0, 0, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-4.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-4.xhtml
new file mode 100644
index 0000000..b47c4cc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-auto-2x2-all-but-4.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto" columns="auto;auto"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="400px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="200px" height="400px"/>
+    </tc:image>
+    <tc:image id="i-2" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="400px" height="200px"/>
+    </tc:image>
+    <tc:image id="i-3" value="pidgeon-point.jpg" rendered="false">
+      <tc:gridLayoutConstraint width="200px" height="200px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-2');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-3');"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-combinations-3-images-fragment.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-combinations-3-images-fragment.xhtml
new file mode 100644
index 0000000..d1fa18b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-combinations-3-images-fragment.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ui:composition
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <f:subview id="#{subid}">
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout rows="#{rows}" columns="20px"/>
+      </f:facet>
+      <tc:image id="image-1" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint preferredHeight="100px"/>
+      </tc:image>
+      <tc:image id="image-2" value="pidgeon-point.jpg" rendered="false">
+        <tc:gridLayoutConstraint preferredHeight="100px"/>
+      </tc:image>
+      <tc:image id="image-3" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint preferredHeight="100px"/>
+      </tc:image>
+    </tc:panel>
+
+  </f:subview>
+
+</ui:composition>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-combinations.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-combinations.xhtml
new file mode 100644
index 0000000..968ecb8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-combinations.xhtml
@@ -0,0 +1,284 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="310px"/>
+    <f:facet name="layout">
+      <tc:gridLayout
+          columns="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+    </f:facet>
+
+    <!--
+    Any combination of "100px", "auto" and "*" in the rows attribute,
+    for 3 rows are 3 * 3 * 3 = 27 combinations.
+    The 2nd one is rendered = false.
+    -->
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;100px;100px"/>
+      <ui:param name="subid" value="sub-01"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;100px;auto"/>
+      <ui:param name="subid" value="sub-02"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;100px;*"/>
+      <ui:param name="subid" value="sub-03"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;auto;100px"/>
+      <ui:param name="subid" value="sub-04"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;auto;auto"/>
+      <ui:param name="subid" value="sub-05"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;auto;*"/>
+      <ui:param name="subid" value="sub-06"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;*;100px"/>
+      <ui:param name="subid" value="sub-07"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;*;auto"/>
+      <ui:param name="subid" value="sub-08"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="100px;*;*"/>
+      <ui:param name="subid" value="sub-09"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;100px;100px"/>
+      <ui:param name="subid" value="sub-11"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;100px;auto"/>
+      <ui:param name="subid" value="sub-12"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;100px;*"/>
+      <ui:param name="subid" value="sub-13"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;auto;100px"/>
+      <ui:param name="subid" value="sub-14"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;auto;auto"/>
+      <ui:param name="subid" value="sub-15"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;auto;*"/>
+      <ui:param name="subid" value="sub-16"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;*;100px"/>
+      <ui:param name="subid" value="sub-17"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;*;auto"/>
+      <ui:param name="subid" value="sub-18"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="auto;*;*"/>
+      <ui:param name="subid" value="sub-19"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;100px;100px"/>
+      <ui:param name="subid" value="sub-21"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;100px;auto"/>
+      <ui:param name="subid" value="sub-22"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;100px;*"/>
+      <ui:param name="subid" value="sub-23"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;auto;100px"/>
+      <ui:param name="subid" value="sub-24"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;auto;auto"/>
+      <ui:param name="subid" value="sub-25"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;auto;*"/>
+      <ui:param name="subid" value="sub-26"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;*;100px"/>
+      <ui:param name="subid" value="sub-27"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;*;auto"/>
+      <ui:param name="subid" value="sub-28"/>
+    </ui:include>
+
+    <ui:include src="rendered-combinations-3-images-fragment.xhtml">
+      <ui:param name="rows" value="*;*;*"/>
+      <ui:param name="subid" value="sub-29"/>
+    </ui:include>
+
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-01:image-1', 0, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-01:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-01:image-3', 0, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-02:image-1', 25, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-02:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-02:image-3', 25, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-03:image-1', 50, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-03:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-03:image-3', 50, 105, 20, 205);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-04:image-1', 75, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-04:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-04:image-3', 75, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-05:image-1', 100, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-05:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-05:image-3', 100, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-06:image-1', 125, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-06:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-06:image-3', 125, 105, 20, 205);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-07:image-1', 150, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-07:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-07:image-3', 150, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-08:image-1', 175, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-08:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-08:image-3', 175, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-09:image-1', 200, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-09:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-09:image-3', 200, 105, 20, 205);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-11:image-1', 225, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-11:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-11:image-3', 225, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-12:image-1', 250, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-12:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-12:image-3', 250, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-13:image-1', 275, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-13:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-13:image-3', 275, 105, 20, 205);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-14:image-1', 300, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-14:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-14:image-3', 300, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-15:image-1', 325, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-15:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-15:image-3', 325, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-16:image-1', 350, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-16:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-16:image-3', 350, 105, 20, 205);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-17:image-1', 375, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-17:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-17:image-3', 375, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-18:image-1', 400, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-18:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-18:image-3', 400, 105, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-19:image-1', 425, 0, 20, 100);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-19:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-19:image-3', 425, 105, 20, 205);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-21:image-1', 450, 0, 20, 205);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-21:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-21:image-3', 450, 210, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-22:image-1', 475, 0, 20, 205);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-22:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-22:image-3', 475, 210, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-23:image-1', 500, 0, 20, 152);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-23:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-23:image-3', 500, 157, 20, 153);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-24:image-1', 525, 0, 20, 205);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-24:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-24:image-3', 525, 210, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-25:image-1', 550, 0, 20, 205);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-25:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-25:image-3', 550, 210, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-26:image-1', 575, 0, 20, 152);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-26:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-26:image-3', 575, 157, 20, 153);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-27:image-1', 600, 0, 20, 205);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-27:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-27:image-3', 600, 210, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-28:image-1', 625, 0, 20, 205);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-28:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-28:image-3', 625, 210, 20, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-29:image-1', 650, 0, 20, 152);"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:sub-29:image-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sub-29:image-3', 650, 157, 20, 153);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-1.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-1.xhtml
new file mode 100644
index 0000000..42055b8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-1.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="400px;200px" columns="400px;200px"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 405, 0, 200, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 405, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 405, 405, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-2.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-2.xhtml
new file mode 100644
index 0000000..c54e783
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-2.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="400px;200px" columns="400px;200px"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 0, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 405, 0, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-3.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-3.xhtml
new file mode 100644
index 0000000..99ed30b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-3.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="400px;200px" columns="400px;200px"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 0, 0, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-4.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-4.xhtml
new file mode 100644
index 0000000..185e707
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-pixel-2x2-all-but-4.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="400px;200px" columns="400px;200px"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg" rendered="false"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-2');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-3');"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-1.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-1.xhtml
new file mode 100644
index 0000000..eb8b04b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-1.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 405, 0, 200, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 405, 400, 200);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 405, 405, 200, 200);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-2.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-2.xhtml
new file mode 100644
index 0000000..6e57065
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-2.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 0, 400, 605);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 405, 0, 200, 605);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-3.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-3.xhtml
new file mode 100644
index 0000000..23e2ef7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-3.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-2');"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 0, 0, 605, 605);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-4.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-4.xhtml
new file mode 100644
index 0000000..7834f2a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rendered-prop-2x2-all-but-4.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="605px" height="605px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="2*;*" columns="2*;*"/>
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg" rendered="false"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg" rendered="false"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-0');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-1');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-2');"/>
+    <tc:script onload="TobagoAssert.assertAbsence('page:i-3');"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rigid.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rigid.xhtml
new file mode 100644
index 0000000..7d7b7ef
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/rigid.xhtml
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:script file="script/tobago-assert.js"/>
+
+    <!--
+    width  =  1 + 5 + 101 + 5 + 101 + 5 + 101 + 5 + 2 = 326
+    height = 21 + 5 +  51 + 5 +  51 + 5 +  51 + 5 + 2 = 196
+    -->
+    <f:facet name="layout">
+      <tc:gridLayout rowSpacing="20px" columns="326px" rows="196px;196px;196px"/>
+    </f:facet>
+
+    <tc:box label="1. All rendered">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;*"/>
+      </f:facet>
+
+      <tc:textarea value="1">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="2">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="3">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+
+      <tc:textarea value="4">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="5">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="6">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+
+      <tc:textarea value="7">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="8">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="9">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+    </tc:box>
+
+    <tc:box label="2. Middle row and column are not rendered.">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;*"/>
+      </f:facet>
+
+      <tc:textarea value="1">
+        <tc:dataAttribute name="assert-width" value="154"/>
+        <tc:dataAttribute name="assert-height" value="79"/>
+      </tc:textarea>
+      <tc:textarea value="2" rendered="false"/>
+      <tc:textarea value="3">
+        <tc:dataAttribute name="assert-width" value="154"/>
+        <tc:dataAttribute name="assert-height" value="79"/>
+      </tc:textarea>
+
+      <tc:textarea value="4" rendered="false"/>
+      <tc:textarea value="5" rendered="false"/>
+      <tc:textarea value="6" rendered="false"/>
+
+      <tc:textarea value="7">
+        <tc:dataAttribute name="assert-width" value="154"/>
+        <tc:dataAttribute name="assert-height" value="79"/>
+      </tc:textarea>
+      <tc:textarea value="8" rendered="false"/>
+      <tc:textarea value="9">
+        <tc:dataAttribute name="assert-width" value="154"/>
+        <tc:dataAttribute name="assert-height" value="79"/>
+      </tc:textarea>
+    </tc:box>
+
+    <tc:box label="3. Like 2. but rigid='true'">
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;*" rigid="true"/>
+      </f:facet>
+
+      <tc:textarea value="1">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="2" rendered="false"/>
+      <tc:textarea value="3">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+
+      <tc:textarea value="4" rendered="false"/>
+      <tc:textarea value="5" rendered="false"/>
+      <tc:textarea value="6" rendered="false"/>
+
+      <tc:textarea value="7">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+      <tc:textarea value="8" rendered="false"/>
+      <tc:textarea value="9">
+        <tc:dataAttribute name="assert-width" value="101"/>
+        <tc:dataAttribute name="assert-height" value="51"/>
+      </tc:textarea>
+    </tc:box>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-2-levels.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-2-levels.xhtml
new file mode 100644
index 0000000..1114784
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-2-levels.xhtml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="300px" height="600px"/>
+    <tc:box label="Scrolling test in a box" id="box">
+      <tc:gridLayoutConstraint width="300px" height="600px"/>
+      <f:facet name="layout">
+        <tc:gridLayout rows="100px;*"/>
+      </f:facet>
+
+      <tc:textarea id="text"/>
+
+
+      <tc:box label="Scrolling test in a box" id="box-2">
+        <f:facet name="layout">
+          <tc:gridLayout rows="100px;*"/>
+        </f:facet>
+
+        <tc:textarea id="text-2"/>
+
+        <tc:image id="image-1" value="pidgeon-point.jpg">
+          <tc:gridLayoutConstraint minimumHeight="600px"/>
+        </tc:image>
+
+      </tc:box>
+
+
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:box', 0, 0, 300, 600);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 6, 26, 287, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-2', 6, 431, 287, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-3', 6, 836, 287, 400);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-box.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-box.xhtml
new file mode 100644
index 0000000..9a7919f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-box.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="300px" height="600px"/>
+    <tc:box label="Scrolling test in a box" id="box">
+      <tc:gridLayoutConstraint width="300px" height="600px"/>
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto"/>
+      </f:facet>
+
+      <tc:image id="image-1" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+      <tc:image id="image-2" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+      <tc:image id="image-3" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+
+      <tc:script file="script/tobago-assert.js"/>
+
+      <tc:script onload="TobagoAssert.assertLayout('page:box', 0, 0, 300, 600);"/>
+
+      <tc:script onload="TobagoAssert.assertLayout('page:image-1', 6, 26, 287, 400);"/>
+      <tc:script onload="TobagoAssert.assertLayout('page:image-2', 6, 431, 287, 400);"/>
+      <tc:script onload="TobagoAssert.assertLayout('page:image-3', 6, 836, 287, 400);"/>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-page.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-page.xhtml
new file mode 100644
index 0000000..df2b8bc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-page.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page" width="300px" height="600px">
+    <tc:gridLayoutConstraint width="300px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto"/>
+    </f:facet>
+
+    <tc:image id="image-1" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint minimumHeight="400px"/>
+    </tc:image>
+    <tc:image id="image-2" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint minimumHeight="400px"/>
+    </tc:image>
+    <tc:image id="image-3" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint minimumHeight="400px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page::content', 0, 0, 300, 600);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 0, 0, 300, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-2', 0, 405, 300, 400);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-3', 0, 810, 300, 400);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-panel-with-border.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-panel-with-border.xhtml
new file mode 100644
index 0000000..5bd8a03
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-panel-with-border.xhtml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="300px" height="600px"/>
+    <tc:panel id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto"/>
+      </f:facet>
+      <tc:gridLayoutConstraint width="300px" height="600px"
+                               borderLeft="10px" borderRight="10px" borderTop="10px" borderBottom="10px"/>
+
+      <tc:image id="image-1" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+      <tc:image id="image-2" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+      <tc:image id="image-3" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+
+      <tc:script file="script/tobago-assert.js"/>
+
+      <tc:script onload="TobagoAssert.assertLayout('page:panel', 0, 0, 300, 600);"/>
+
+      <tc:script onload="TobagoAssert.assertLayout('page:image-1', 10, 10, 280, 400);"/>
+      <tc:script onload="TobagoAssert.assertLayout('page:image-2', 10, 415, 280, 400);"/>
+      <tc:script onload="TobagoAssert.assertLayout('page:image-3', 10, 820, 280, 400);"/>
+
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-panel.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-panel.xhtml
new file mode 100644
index 0000000..24ca20b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-panel.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="300px" height="600px"/>
+    <tc:panel id="panel">
+      <tc:gridLayoutConstraint width="300px" height="600px"/>
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto"/>
+      </f:facet>
+
+      <tc:image id="image-1" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+      <tc:image id="image-2" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+      <tc:image id="image-3" value="pidgeon-point.jpg">
+        <tc:gridLayoutConstraint minimumHeight="400px"/>
+      </tc:image>
+
+      <tc:script file="script/tobago-assert.js"/>
+
+      <tc:script onload="TobagoAssert.assertLayout('page:panel', 0, 0, 300, 600);"/>
+
+      <tc:script onload="TobagoAssert.assertLayout('page:image-1', 0, 0, 300, 400);"/>
+      <tc:script onload="TobagoAssert.assertLayout('page:image-2', 0, 405, 300, 400);"/>
+      <tc:script onload="TobagoAssert.assertLayout('page:image-3', 0, 810, 300, 400);"/>
+
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-tab.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-tab.xhtml
new file mode 100644
index 0000000..9fbbc25
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/scrolling-tab.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="300px" height="600px"/>
+    <tc:tabGroup>
+      <tc:tab label="Scrolling test in a tab" id="tab1">
+        <tc:gridLayoutConstraint width="300px" height="600px"/>
+        <f:facet name="layout">
+          <tc:gridLayout rows="auto;auto;auto"/>
+        </f:facet>
+
+        <tc:image id="image-1" value="pidgeon-point.jpg">
+          <tc:gridLayoutConstraint minimumHeight="400px"/>
+        </tc:image>
+        <tc:image id="image-2" value="pidgeon-point.jpg">
+          <tc:gridLayoutConstraint minimumHeight="400px"/>
+        </tc:image>
+        <tc:image id="image-3" value="pidgeon-point.jpg">
+          <tc:gridLayoutConstraint minimumHeight="400px"/>
+        </tc:image>
+
+        <tc:script file="script/tobago-assert.js"/>
+
+        <tc:script onload="TobagoAssert.assertLayout('page:tab1::content', 0, 21, 300, 579);"/>
+
+        <!-- todo: Test result is 4 instead of 6. Why? -->
+        <tc:script onload="TobagoAssert.assertLayout('page:tab1:image-1', 6, 26, 288, 400);"/>
+        <!-- todo: Test result is 4 instead of 6. Why? -->
+        <tc:script onload="TobagoAssert.assertLayout('page:tab1:image-2', 6, 431, 288, 400);"/>
+        <!-- todo: Test result is 4 instead of 6. Why? -->
+        <tc:script onload="TobagoAssert.assertLayout('page:tab1:image-3', 6, 836, 288, 400);"/>
+
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-auto.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-auto.xhtml
new file mode 100644
index 0000000..c58dada
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-auto.xhtml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page" label="Detect size of an image (not yet implemented)">
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto" rows="auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="400px" height="400px"/>
+
+    <!--todo: not implmented yet-->
+
+    <tc:image id="image-0" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="120px" height="180px"/>
+    </tc:image>
+
+    <tc:out value="TODO: The values doesn't come directly from the image in the moment."/>
+
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 120, 180);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-maximum.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-maximum.xhtml
new file mode 100644
index 0000000..3051be0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-maximum.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="*" rows="*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="200px" height="200px"/>
+
+    <tc:image id="image-0" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint maximumWidth="100px" maximumHeight="100px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 100, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-minimum.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-minimum.xhtml
new file mode 100644
index 0000000..efb30d7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-minimum.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="*" rows="*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="200px" height="200px"/>
+
+    <tc:image id="image-0" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint minimumWidth="300px" minimumHeight="300px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 300, 300);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-preferred.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-preferred.xhtml
new file mode 100644
index 0000000..8ba6508
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-preferred.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto" rows="auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="200px" height="200px"/>
+
+    <tc:image id="image-0" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint preferredWidth="100px" preferredHeight="100px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 100, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-set.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-set.xhtml
new file mode 100644
index 0000000..62dffe3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/size-set.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="200px" height="200px"/>
+
+    <tc:image id="image-0" value="pidgeon-point.jpg">
+      <tc:gridLayoutConstraint width="120px" height="180px"/>
+    </tc:image>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 120, 180);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/spacing-nested.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/spacing-nested.xhtml
new file mode 100644
index 0000000..82eb0d6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/spacing-nested.xhtml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+  
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <!--
+  Test page for spacing:
+  1. spacing attributes
+  2. theme defaults
+  3. only columnSpacing
+  4. only rowSpacing
+  -->
+
+  <tc:page id="page" label="Spacing Test">
+    <tc:gridLayoutConstraint width="670px" height="670px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" rows="*;*" columnSpacing="50px" rowSpacing="50px"/>
+    </f:facet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;*" rows="*;*;*" columnSpacing="5px" rowSpacing="5px"/>
+      </f:facet>
+
+      <tc:image id="a_NW" value="pidgeon-point.jpg"/>
+      <tc:image id="a_N" value="pidgeon-point.jpg"/>
+      <tc:image id="a_NE" value="pidgeon-point.jpg"/>
+      <tc:image id="a_W" value="pidgeon-point.jpg"/>
+      <tc:image id="a_C" value="pidgeon-point.jpg"/>
+      <tc:image id="a_E" value="pidgeon-point.jpg"/>
+      <tc:image id="a_SW" value="pidgeon-point.jpg"/>
+      <tc:image id="a_S" value="pidgeon-point.jpg"/>
+      <tc:image id="a_SE" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;*" rows="*;*;*"/>
+      </f:facet>
+
+      <tc:image id="b_NW" value="pidgeon-point.jpg"/>
+      <tc:image id="b_N" value="pidgeon-point.jpg"/>
+      <tc:image id="b_NE" value="pidgeon-point.jpg"/>
+      <tc:image id="b_W" value="pidgeon-point.jpg"/>
+      <tc:image id="b_C" value="pidgeon-point.jpg"/>
+      <tc:image id="b_E" value="pidgeon-point.jpg"/>
+      <tc:image id="b_SW" value="pidgeon-point.jpg"/>
+      <tc:image id="b_S" value="pidgeon-point.jpg"/>
+      <tc:image id="b_SE" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*" rows="*;*" columnSpacing="0px"/>
+      </f:facet>
+
+      <tc:image id="c_NW" value="pidgeon-point.jpg"/>
+      <tc:image id="c_NE" value="pidgeon-point.jpg"/>
+      <tc:image id="c_SW" value="pidgeon-point.jpg"/>
+      <tc:image id="c_SE" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*" rows="*;*" rowSpacing="0px"/>
+      </f:facet>
+
+      <tc:image id="d_NW" value="pidgeon-point.jpg"/>
+      <tc:image id="d_NE" value="pidgeon-point.jpg"/>
+      <tc:image id="d_SW" value="pidgeon-point.jpg"/>
+      <tc:image id="d_SE" value="pidgeon-point.jpg"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:a_NW', 0, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_N', 105, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_NE', 210, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_W', 0, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_C', 105, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_E', 210, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_SW', 0, 210, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_S', 105, 210, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:a_SE', 210, 210, 100, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:b_NW', 360, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_N', 465, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_NE', 570, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_W', 360, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_C', 465, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_E', 570, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_SW', 360, 210, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_S', 465, 210, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:b_SE', 570, 210, 100, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:c_NW', 0, 360, 155, 152);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:c_NE', 155, 360, 155, 152);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:c_SW', 0, 517, 155, 153);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:c_SE', 155, 517, 155, 153);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:d_NW', 360, 360, 152, 155);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:d_NE', 517, 360, 153, 155);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:d_SW', 360, 515, 152, 155);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:d_SE', 517, 515, 153, 155);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/spacing-simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/spacing-simple.xhtml
new file mode 100644
index 0000000..5dd6db3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/spacing-simple.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <!--
+  Test page for spacing:
+  1. spacing attributes
+  2. theme defaults
+  3. only columnSpacing
+  4. only rowSpacing
+  -->
+
+  <tc:page id="page" label="Spacing Test">
+    <tc:gridLayoutConstraint width="310px" height="310px"/>
+
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" rows="*;*" columnSpacing="0px"/>
+    </f:facet>
+
+    <tc:image id="c_NW" value="pidgeon-point.jpg"/>
+    <tc:image id="c_NE" value="pidgeon-point.jpg"/>
+    <tc:image id="c_SW" value="pidgeon-point.jpg"/>
+    <tc:image id="c_SE" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:c_NW', 0, 0, 155, 152);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:c_NE', 155, 0, 155, 152);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:c_SW', 0, 157, 155, 153);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:c_SE', 155, 157, 155, 153);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-auto-auto.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-auto-auto.xhtml
new file mode 100644
index 0000000..d3dafaa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-auto-auto.xhtml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:h="http://java.sun.com/jsf/html"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto" columns="auto"/>
+    </f:facet>
+
+    <tc:tabGroup id="tabGroup">
+      <tc:tab label="Rows" id="rows">
+        <f:facet name="layout">
+          <tc:gridLayout rows="auto;auto"/>
+        </f:facet>
+        <tc:textarea id="a-1">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+        <tc:textarea id="a-2">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+      </tc:tab>
+      <tc:tab label="Columns" id="columns">
+        <f:facet name="layout">
+          <tc:gridLayout columns="auto;auto"/>
+        </f:facet>
+        <tc:textarea id="a-3">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+        <tc:textarea id="a-4">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+
+      </tc:tab>
+    </tc:tabGroup>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <!-- Todo: gererally all tabs should have the same size? -->
+
+    <tc:script onload="TobagoAssert.assertLayout('page:rows:a-1', 6, 26, 100, 50);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:rows:a-2', 6, 81, 100, 50);"/>
+
+    <!--click the tab to display the elements, they can only be measured if they are not hidden.-->
+    <tc:script onload="jQuery(Tobago.Utils.escapeClientId('page:tabGroup')).find('.tobago-tab[tabgroupindex=1]').click();"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:columns:a-3', 6, 26, 100, 50);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:columns:a-4', 111, 26, 100, 50);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-auto.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-auto.xhtml
new file mode 100644
index 0000000..c562e17
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-auto.xhtml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:h="http://java.sun.com/jsf/html"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto" columns="auto"/>
+    </f:facet>
+
+    <tc:tabGroup id="tabGroup">
+      <tc:tab label="Rows" id="rows">
+        <f:facet name="layout">
+          <tc:gridLayout rows="*;*"/>
+        </f:facet>
+        <tc:textarea id="a-1">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+        <tc:textarea id="a-2">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+      </tc:tab>
+      <tc:tab label="Columns" id="columns">
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;*"/>
+        </f:facet>
+        <tc:textarea id="a-3">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+        <tc:textarea id="a-4">
+          <tc:gridLayoutConstraint width="100px" height="50px"/>
+        </tc:textarea>
+
+      </tc:tab>
+    </tc:tabGroup>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <!-- Todo: gererally all tabs should have the same size? -->
+
+    <tc:script onload="TobagoAssert.assertLayout('page:rows:a-1', 6, 26, 100, 50);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:rows:a-2', 6, 81, 100, 50);"/>
+
+    <!--click the tab to display the elements, they can only be measured if they are not hidden.-->
+    <tc:script onload="jQuery(Tobago.Utils.escapeClientId('page:tabGroup')).find('.tobago-tab[tabgroupindex=1]').click();"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:columns:a-3', 6, 26, 100, 50);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:columns:a-4', 111, 26, 100, 50);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-relative.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-relative.xhtml
new file mode 100644
index 0000000..cd478a7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tabGroup-relative.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+ 
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:h="http://java.sun.com/jsf/html"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:tabGroup id="tabGroup">
+      <tc:tab label="Rows" id="rows">
+        <f:facet name="layout">
+          <tc:gridLayout rows="*;*"/>
+        </f:facet>
+        <tc:textarea id="a-1" />
+        <tc:textarea id="a-2" />
+      </tc:tab>
+      <tc:tab label="Columns" id="columns">
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;*" />
+        </f:facet>
+        <tc:textarea id="a-3" />
+        <tc:textarea id="a-4" />
+      </tc:tab>
+    </tc:tabGroup>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:rows:a-1', 6, 26, 588, 131);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:rows:a-2', 6, 162, 588, 132);"/>
+
+    <!--click the tab to display the elements, they can only be measured if they are not hidden.-->
+    <tc:script onload="jQuery(Tobago.Utils.escapeClientId('page:tabGroup')).find('.tobago-tab[tabgroupindex=1]').click();"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:columns:a-3', 6, 26, 291, 268);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:columns:a-4', 302, 26, 292, 268);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tobago-1239.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tobago-1239.xhtml
new file mode 100644
index 0000000..bff9ef0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tobago-1239.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="300px" height="500px"/>
+
+    <tc:box id="box" label="Testing the Bug TOBAGO-1239 ">
+      <f:facet name="layout">
+        <tc:gridLayout rows="50px;50px"/>
+      </f:facet>
+      <tc:textarea id="i1" value="this is rendered"/>
+      <tc:textarea id="i2" rendered="false" value="this not"/>
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:box', 0, 0, 300, 83);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tobago-1243.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tobago-1243.xhtml
new file mode 100644
index 0000000..9ce49ad
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/tobago-1243.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page">
+
+    <f:facet name="layout">
+      <tc:gridLayout rows="50px;*;*"/>
+    </f:facet>
+
+    <tc:out value="Test, if EL bindings to non initialized beans are not called, when rendererd = false."/>
+
+    <tc:box id="box-1" label="Empty, because rendered=false">
+        <tc:sheet var="row" rendered="false">
+          <tc:column label="Label">
+            <tc:out/>
+          </tc:column>
+        </tc:sheet>
+    </tc:box>
+
+    <tc:box id="box-2" label="A simple box, to test the layout bank assignment">
+      <f:facet name="layout">
+        <tc:gridLayout rows="100px;*"/>
+      </f:facet>
+
+      <tc:textarea value="test 1" id="test-1" rendered="false"/>
+      <tc:textarea value="test 2" id="test-2"/>
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:test-2', 6, 440, 1011, 321);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-empty.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-empty.xhtml
new file mode 100644
index 0000000..1614b48
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-empty.xhtml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+ 
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="100px" height="205px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*" rows="*;*" />
+    </f:facet>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-horizontal-6.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-horizontal-6.xhtml
new file mode 100644
index 0000000..08da8c9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-horizontal-6.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+ 
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="310px" height="100px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*;*;*;*;*" rows="*" />
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 105, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 210, 0, 100, 100);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-horizontal.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-horizontal.xhtml
new file mode 100644
index 0000000..232fa66
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-horizontal.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+  
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="100px" height="100px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" rows="*" />
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 100, 100);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-vertical-6.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-vertical-6.xhtml
new file mode 100644
index 0000000..17b996b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-vertical-6.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+ 
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="100px" height="310px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*" rows="*;*;*;*;*;*" />
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 0, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 210, 100, 100);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-vertical.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-vertical.xhtml
new file mode 100644
index 0000000..c9162f6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-less-components-vertical.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+ 
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="100px" height="100px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*" rows="*;*" />
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 100, 100);"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-much-components.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-much-components.xhtml
new file mode 100644
index 0000000..4548aff
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/too-much-components.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+  
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="205px" height="205px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" rows="*" />
+    </f:facet>
+
+    <tc:image id="i-0" value="pidgeon-point.jpg"/>
+    <tc:image id="i-1" value="pidgeon-point.jpg"/>
+    <tc:image id="i-2" value="pidgeon-point.jpg"/>
+    <tc:image id="i-3" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-0', 0, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-1', 105, 0, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-2', 0, 105, 100, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:i-3', 105, 105, 100, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/transparent-for-layout-fragment.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/transparent-for-layout-fragment.xhtml
new file mode 100644
index 0000000..a261424
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/transparent-for-layout-fragment.xhtml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+    <!--
+    The upper <?xml ... &> declaration creates a component, which must not be layed out!
+    -->
+
+<tc:image
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    id="image-0"
+    value="pidgeon-point.jpg"/>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/transparent-for-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/transparent-for-layout.xhtml
new file mode 100644
index 0000000..b50a231
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/gridLayout/transparent-for-layout.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page" width="200px" height="205px">
+    <f:facet name="layout">
+      <tc:gridLayout />
+    </f:facet>
+
+    <!-- style must not be layed out -->
+    <tc:style>/* only a test */</tc:style>
+
+    <!-- script must not be layed out -->
+    <tc:script>/* only a test */</tc:script>
+
+    <ui:include src="transparent-for-layout-fragment.xhtml"/>
+
+    <!-- hidden must not be layed out -->
+    <tc:hidden id="h"/>
+
+    <!-- param must not be layed out -->
+    <f:param id="foo" value="bar"/>
+
+    <!-- debug must not be layed out -->
+    <ui:debug />
+
+    <tc:image id="image-1" value="pidgeon-point.jpg"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:image-0', 0, 0, 200, 100);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:image-1', 0, 105, 200, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/header/header-fixed.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/header/header-fixed.xhtml
new file mode 100644
index 0000000..d8a1d32
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/header/header-fixed.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns="http://www.w3.org/1999/xhtml">
+
+  <tc:page>
+    <tc:header fixed="true" label="Test the header">
+      Fixed Header
+    </tc:header>
+
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/header/header.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/header/header.xhtml
new file mode 100644
index 0000000..abf415c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/header/header.xhtml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns="http://www.w3.org/1999/xhtml">
+
+  <tc:page>
+    <tc:header label="Test the header">
+      Scrolling Header
+    </tc:header>
+
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+    <p>
+      Lore ipsum.
+    </p>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/hidden/hidden.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/hidden/hidden.xhtml
new file mode 100644
index 0000000..9e69ede
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/hidden/hidden.xhtml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:out value="Click 'fill' and than 'submit' and check that the 2. field has not modified, because the hidden field 2 has rendered=false"/>
+    
+    <tc:hidden id="h1" value="#{hidden.value1}"/>
+    <tc:in label="Value of the hidden field 1 on server"
+           labelWidth="350px" value="#{hidden.value1}" disabled="true"/>
+    
+    <tc:hidden id="h2" value="#{hidden.value2}" rendered="false"/>
+    <tc:in label="Value of the hidden field 2 on server (rendered=false)"
+           labelWidth="350px" value="#{hidden.value2}" disabled="true"/>
+    
+    <tc:hidden id="h3" value="#{hidden.value3}" rendered="true"/>
+    <tc:in label="Value of the hidden field 3 on server (rendered=true)"
+           labelWidth="350px" value="#{hidden.value3}" disabled="true"/>
+    
+    <tc:button id="fill" label="1. fill hidden fields" onclick="fillHiddenFields();"/>
+    <tc:button label="2. submit hidden fields..."/>
+
+    <tc:panel/>
+    
+    <tc:script>
+
+      function fillHiddenFields() {
+        jQuery('#page\\:h1').val("new " + jQuery('#page\\:h1').val());
+        jQuery('#page\\:h2').val("new " + jQuery('#page\\:h2').val());
+        jQuery('#page\\:h3').val("new " + jQuery('#page\\:h3').val());
+      }
+      
+      // todo: the test code is not full automated
+    </tc:script>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/alphaBlendingBug.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/alphaBlendingBug.xhtml
new file mode 100644
index 0000000..9952941
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/alphaBlendingBug.xhtml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="400px" height="400px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" />
+    </f:facet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;*;auto"/>
+      </f:facet>
+
+      <tc:image value="image/feather-leaf.png"/>
+
+      <tc:out value="The part of the image, where is no feather should be grey like the background. (There is a Bug in old IE.)"/>
+
+      <tc:button label="full reload"/>
+    </tc:panel>
+
+    <tc:panel id="ajax">
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;*;auto"/>
+      </f:facet>
+
+      <tc:image value="image/feather-leaf.png"/>
+
+      <tc:out value="Images loaded with AJAX must also be fixed."/>
+
+      <tc:button label="partial reload (right)">
+        <f:ajax render="ajax" execute="ajax"/>
+      </tc:button>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/disabled.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/disabled.xhtml
new file mode 100644
index 0000000..6a9d07e
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/disabled.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page" width="600px" height="600px">
+
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" rows="auto;auto;auto;auto;*"/>
+    </f:facet>
+
+    <tc:label id="label" value="normal"/>
+    <tc:label id="label-d" value="disabled"/>
+
+    <tc:image id="image" value="image/foo.png">
+      <tc:gridLayoutConstraint width="16px" height="16px"/>
+    </tc:image>
+    <tc:image id="image-d" value="image/foo.png" disabled="true">
+      <tc:gridLayoutConstraint width="16px" height="16px"/>
+    </tc:image>
+
+    <tc:button id="button" image="image/foo.png" label="button"/>
+    <tc:button id="button-d" image="image/foo.png" label="button" disabled="true"/>
+
+    <tc:link id="link" image="image/foo.png" label="link"/>
+    <tc:link id="link-d" image="image/foo.png" label="link" disabled="true"/>
+
+    <tc:link id="gif" image="image/foo.gif" label="link (gif)"/>
+    <tc:link id="gif-d" image="image/foo.gif" label="link (gif)" disabled="true"/>
+
+    <tc:panel/>
+    <tc:panel/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/image.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/image.xhtml
new file mode 100644
index 0000000..07955b4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/image/image.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:out value="requested with extension: pidgeon-point.jpg"/>
+
+    <tc:image value="pidgeon-point.jpg"/>
+
+    <tc:out value="requested without extension: pidgeon-point"/>
+
+    <tc:image value="pidgeon-point"/>
+
+    <tc:out value="font awesome icon: flag"/>
+
+    <tc:image value="fa-flag"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/id-and-fieldId.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/id-and-fieldId.js
new file mode 100644
index 0000000..af5abd1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/id-and-fieldId.js
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+jQuery(document).ready(function() {
+
+  fillIdDisplay("0", ".tobago-in");
+  fillIdDisplay("1", ".tobago-in");
+  fillIdDisplay("2", ".tobago-in");
+  fillIdDisplay("3", ".tobago-in");
+  fillIdDisplay("4", ".tobago-in");
+  fillIdDisplay("5", ".tobago-date");
+//  fillIdDisplay("6", ".tobago-time");
+  fillIdDisplay("7", ".tobago-file");
+  fillIdDisplay("8", ".tobago-textarea");
+  fillIdDisplay("9", ".tobago-selectBooleanCheckbox");
+  fillIdDisplay("10", ".tobago-selectManyCheckbox");
+  fillIdDisplay("11", ".tobago-selectManyListbox");
+  fillIdDisplay("12", ".tobago-selectOneChoice");
+  fillIdDisplay("13", ".tobago-selectOneListbox");
+  fillIdDisplay("14", ".tobago-selectOneRadio");
+
+  test("page:panel2", "page:alpha");
+  test("page:field3", "page:beta");
+  test("page:panel4", "page:gamma");
+  test("page:field4", "page:delta");
+  test("page:panel5", "page:datePanel");
+  test("page:field5", "page:dateField");
+  test("page:panel6", "page:timePanel");
+  test("page:field6", "page:timeField");
+  test("page:panel7", "page:filePanel");
+  test("page:field7", "page:fileField");
+  test("page:panel8", "page:textareaPanel");
+  test("page:field8", "page:textareaField");
+  test("page:panel9", "page:selectBooleanCheckboxPanel");
+  test("page:field9", "page:selectBooleanCheckboxField");
+  test("page:panel10", "page:selectManyCheckboxPanel");
+  test("page:field10", "page:selectManyCheckboxField");
+  test("page:panel11", "page:selectManyListboxPanel");
+  test("page:field11", "page:selectManyListboxField");
+  test("page:panel12", "page:selectOneChoicePanel");
+  test("page:field12", "page:selectOneChoiceField");
+  test("page:panel13", "page:selectOneListboxPanel");
+  test("page:field13", "page:selectOneListboxField");
+  test("page:panel14", "page:selectOneRadioPanel");
+  test("page:field14", "page:selectOneRadioField");
+
+});
+
+function fillIdDisplay(i, fieldClass) {
+  var panelIn = jQuery(Tobago.Utils.escapeClientId("page:panel" + i));
+  var labelIn = jQuery(Tobago.Utils.escapeClientId("page:label" + i));
+  var fieldIn = jQuery(Tobago.Utils.escapeClientId("page:field" + i));
+
+  var panel = panelIn.prev();
+  var label = panel.children(".tobago-label");
+  var field = panel.children(fieldClass);
+
+  if (fieldClass == ".tobago-selectBooleanCheckbox") { // special
+    field = field.find("input:first");
+  }
+
+  panelIn.val(panel.attr("id"));
+  labelIn.val(label.attr("id"));
+  fieldIn.val(field.attr("id"));
+}
+
+function test(testId, expected) {
+  var element = jQuery(Tobago.Utils.escapeClientId(testId));
+  if (element.val() != expected) {
+    element.addClass("tobago-in-markup-error");
+    element.attr("title", "expected: '" + expected + "'");
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/id-and-fieldId.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/id-and-fieldId.xhtml
new file mode 100644
index 0000000..860e671
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/id-and-fieldId.xhtml
@@ -0,0 +1,139 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout
+          columns="3*;*;*;*"
+          rows="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="900px" height="700px"/>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="4"/>
+    </tc:messages>
+
+    <tc:label value="Test Tag"/>
+    <tc:label value="Panel Id"/>
+    <tc:label value="Label Id"/>
+    <tc:label value="Field Id"/>
+
+    <tc:in label="auto id" required="true"/>
+    <tc:in id="panel0"/>
+    <tc:in id="label0"/>
+    <tc:in id="field0"/>
+
+    <tc:in label="auto id"/>
+    <tc:in id="panel1"/>
+    <tc:in id="label1"/>
+    <tc:in id="field1"/>
+
+    <tc:in label="id" id="alpha"/>
+    <tc:in id="panel2"/>
+    <tc:in id="label2"/>
+    <tc:in id="field2"/>
+
+    <tc:in label="fieldId" fieldId="beta"/>
+    <tc:in id="panel3"/>
+    <tc:in id="label3"/>
+    <tc:in id="field3"/>
+
+    <tc:in label="id and fieldId" id="gamma" fieldId="delta"/>
+    <tc:in id="panel4"/>
+    <tc:in id="label4"/>
+    <tc:in id="field4"/>
+
+    <tc:date label="date" id="datePanel" fieldId="dateField"/>
+    <tc:in id="panel5"/>
+    <tc:in id="label5"/>
+    <tc:in id="field5"/>
+
+    <tc:time label="time" id="timePanel" fieldId="timeField"/>
+    <tc:in id="panel6"/>
+    <tc:in id="label6"/>
+    <tc:in id="field6"/>
+
+    <tc:file label="file" id="filePanel" fieldId="fileField"/>
+    <tc:in id="panel7"/>
+    <tc:in id="label7"/>
+    <tc:in id="field7"/>
+
+    <tc:textarea label="textarea" id="textareaPanel" fieldId="textareaField"/>
+    <tc:in id="panel8"/>
+    <tc:in id="label8"/>
+    <tc:in id="field8"/>
+
+    <tc:selectBooleanCheckbox label="selectBooleanCheckbox" id="selectBooleanCheckboxPanel" fieldId="selectBooleanCheckboxField"/>
+    <tc:in id="panel9"/>
+    <tc:in id="label9"/>
+    <tc:in id="field9"/>
+
+    <tc:selectManyCheckbox label="selectManyCheckbox" id="selectManyCheckboxPanel" fieldId="selectManyCheckboxField">
+      <tc:selectItem itemLabel="A"/>
+      <tc:selectItem itemLabel="B"/>
+    </tc:selectManyCheckbox>
+    <tc:in id="panel10"/>
+    <tc:in id="label10"/>
+    <tc:in id="field10"/>
+
+    <tc:selectManyListbox label="selectManyListbox" id="selectManyListboxPanel" fieldId="selectManyListboxField">
+      <tc:selectItem itemLabel="A"/>
+      <tc:selectItem itemLabel="B"/>
+    </tc:selectManyListbox>
+    <tc:in id="panel11"/>
+    <tc:in id="label11"/>
+    <tc:in id="field11"/>
+
+    <tc:selectOneChoice label="selectOneChoice" id="selectOneChoicePanel" fieldId="selectOneChoiceField">
+      <tc:selectItem itemLabel="A"/>
+      <tc:selectItem itemLabel="B"/>
+    </tc:selectOneChoice>
+    <tc:in id="panel12"/>
+    <tc:in id="label12"/>
+    <tc:in id="field12"/>
+
+    <tc:selectOneListbox label="selectOneListbox" id="selectOneListboxPanel" fieldId="selectOneListboxField">
+      <tc:selectItem itemLabel="A"/>
+      <tc:selectItem itemLabel="B"/>
+    </tc:selectOneListbox>
+    <tc:in id="panel13"/>
+    <tc:in id="label13"/>
+    <tc:in id="field13"/>
+
+    <tc:selectOneRadio label="selectOneRadio" id="selectOneRadioPanel" fieldId="selectOneRadioField">
+      <tc:selectItem itemLabel="A"/>
+      <tc:selectItem itemLabel="B"/>
+    </tc:selectOneRadio>
+    <tc:in id="panel14"/>
+    <tc:in id="label14"/>
+    <tc:in id="field14"/>
+
+    <tc:panel/>
+    <tc:panel/>
+    <tc:panel/>
+    <tc:button label="Reload"/>
+
+    <tc:script file="test/in/id-and-fieldId.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in-layout.xhtml
new file mode 100644
index 0000000..25761c8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in-layout.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:in value="a" id="s1"/>
+    <tc:in value="b" label="normal" id="s2"/>
+    <tc:out/>
+    <tc:in value="c" label="normal breiter als breit als breit" id="s3"/>
+
+    <tc:in value="a new" id="sn1"/>
+    <tc:in value="b new" label="normal&lt;b>b&lt;/b>" id="sn2"/>
+    <tc:out/>
+    <tc:in value="c new" label="normal breiter als breit als breit" id="sn3"/>
+
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in-tx.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in-tx.xhtml
new file mode 100644
index 0000000..e35d351
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in-tx.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto;auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:messages/>
+
+    <tc:in label="Label 1" value="Some Value 1" fieldId="in1" id="panel1"/>
+    <tc:in label="Label 2 (required)" value="Some Value 2" fieldId="in2" id="panel2" required="true"/>
+    <tc:in label="Label 3 (readonly)" value="Some Value 3" fieldId="in3" id="panel3" readonly="true"/>
+    <tc:in label="Label 4 (disabled)" value="Some Value 4" fieldId="in4" id="panel4" disabled="true"/>
+
+    <tc:button label="Submit" defaultCommand="true"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in.xhtml
new file mode 100644
index 0000000..373bf67
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/in/in.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+
+    <tc:messages/>
+
+    <tc:segmentLayout large="8;4">
+
+      <tc:in label="First Value" value="#{in.first}"/>
+      <tc:in label="Second Value (Required)" value="#{in.second}" required="true"/>
+      <tc:date label="Second Value (Required)" value="#{in.second}" required="true"/>
+
+      <tc:button label="submit"/>
+
+    </tc:segmentLayout>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/for-auto.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/for-auto.xhtml
new file mode 100644
index 0000000..666cf9d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/for-auto.xhtml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto"/>
+    </f:facet>
+    <tc:box label="Related to TOBAGO-1136: for='@auto' attribute">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+      </f:facet>
+
+      <tc:in label="tx:in" id="in_panel" fieldId="in"/>
+
+      <tc:textarea label="tx:textarea" id="textarea_panel" fieldId="textarea"/>
+
+      <tc:time label="tx:time" id="time_panel" fieldId="time"/>
+
+      <tc:date label="tx:date" id="date_panel" fieldId="date"/>
+
+      <tc:selectBooleanCheckbox label="tx:selectBooleanCheckbox" id="check_panel" fieldId="check"/>
+
+      <tc:selectManyCheckbox label="tx:selectManyCheckbox" id="mcheck_panel" fieldId="mcheck">
+        <tc:selectItem itemLabel="Test 1" itemValue="1"/>
+        <tc:selectItem itemLabel="Test 2" itemValue="2"/>
+      </tc:selectManyCheckbox>
+
+      <tc:selectManyListbox label="tx:selectManyListbox" id="mlist_panel" fieldId="mlist">
+        <tc:selectItem itemLabel="Test"/>
+      </tc:selectManyListbox>
+
+      <tc:selectManyShuttle label="tx:selectManyShuttle" id="shuttle_panel" fieldId="shuttle">
+        <tc:selectItem itemLabel="Test 1"/>
+        <tc:selectItem itemLabel="Test 2"/>
+      </tc:selectManyShuttle>
+
+      <tc:selectOneChoice label="tx:selectOneChoice" id="choice_panel" fieldId="choice">
+        <tc:selectItem itemLabel="Test"/>
+      </tc:selectOneChoice>
+
+      <tc:selectOneListbox label="tx:selectOneListbox" id="list_panel" fieldId="list">
+        <tc:selectItem itemLabel="Test"/>
+      </tc:selectOneListbox>
+
+      <tc:selectOneRadio label="tx:selectOneRadio" id="radio_panel" fieldId="radio">
+        <tc:selectItem itemLabel="Test 1" itemValue="1"/>
+        <tc:selectItem itemLabel="Test 2" itemValue="2"/>
+      </tc:selectOneRadio>
+
+      <tc:file label="tx:file" id="file_panel" fieldId="file"/>
+
+      <tc:panel id="tc_in_panel">
+        <f:facet name="layout">
+          <tc:gridLayout columns="200px;*"/>
+        </f:facet>
+
+        <tc:label value="tc:in" for="@auto"/>
+        <tc:in id="tc_in"/>
+      </tc:panel>
+
+    </tc:box>
+
+    <tc:script onload="check()">
+
+      function check() {
+        checkForLabel("page:in_panel", "page:in");
+        checkForLabel("page:textarea_panel", "page:textarea");
+        checkForLabel("page:time_panel", "page:time");
+        checkForLabel("page:date_panel", "page:date");
+        checkForLabel("page:check_panel", "page:check");
+        checkForLabel("page:mcheck_panel", "page:mcheck");
+        checkForLabel("page:mlist_panel", "page:mlist");
+        checkForLabel("page:shuttle_panel", "page:shuttle");
+        checkForLabel("page:choice_panel", "page:choice");
+        checkForLabel("page:list_panel", "page:list");
+        checkForLabel("page:radio_panel", "page:radio");
+        checkForLabel("page:file_panel", "page:file");
+        checkForLabel("page:tc_in_panel", "page:tc_in");
+      }
+
+      function checkForLabel(labelId, componentId) {
+        var label = jQuery(Tobago.Utils.escapeClientId(labelId)).children("label");
+        var component = jQuery(Tobago.Utils.escapeClientId(componentId));
+        if (label.size() != 1) {
+          LOG.error("Label not found with id: '" + labelId + "'");
+        }
+        if (component.size() != 1) {
+          LOG.error("Component not found with id: '" + componentId + "'");
+        }
+        if (label.attr('for') != component.attr('id')) {
+          LOG.error("Missing for attribute for component with id: '" + componentId + "'");
+        }
+      }
+
+    </tc:script>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/label-tx.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/label-tx.xhtml
new file mode 100644
index 0000000..a86d277
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/label-tx.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <!-- todo: facelet not working yet TOBAGO-993 -->
+
+    <tc:label value="label">
+      <tc:in value="value"/>
+    </tc:label>
+
+    <tc:out value="tx:label should not be used directly, because it is not working with facelets, only with JSP" />
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/label.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/label.xhtml
new file mode 100644
index 0000000..b855b40
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/label/label.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;*" rows="auto"/>
+    </f:facet>
+
+    <tc:label value="Label"/>
+    <tc:in value="In"/>
+
+    <tc:panel>
+    <f:facet name="layout">
+    <tc:gridLayout columns="170px;1*" rows="50px" border="0" />
+    </f:facet>
+    <tc:panel>
+    <tc:label value="Very very very very long label that is very long">
+        <tc:out value="XXX"/>
+      </tc:label>
+    </tc:panel>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/link/link-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/link/link-layout.xhtml
new file mode 100644
index 0000000..23f71ab
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/link/link-layout.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+        xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:f="http://java.sun.com/jsf/core">
+
+    <tc:page id="page">
+        <f:facet name="layout">
+            <tc:gridLayout rows="auto" columns="auto"/>
+        </f:facet>
+        <tc:box label="Tests the layout of links">
+
+            <f:facet name="layout">
+                <tc:gridLayout columns="auto;auto;auto;auto;auto;auto;auto"/>
+            </f:facet>
+
+            <tc:link id="l1" label="l" tip="3px"/>
+            <tc:link id="l2" label="g" tip="7px"/>
+            <tc:link id="l3" label="W" tip="11px"/>
+
+            <tc:link id="l4" label="l" image="image/feather-leaf.png" tip="16px + 4px + 3px"/>
+            <tc:link id="l5" label="g" image="image/feather-leaf.png" tip="16px + 4px + 7px"/>
+            <tc:link id="l6" label="W" image="image/feather-leaf.png" tip="16px + 4px + 11px"/>
+
+            <tc:link id="l7" image="image/feather-leaf.png" tip="16px"/>
+
+            <tc:out value="[2nd row]">
+                <tc:gridLayoutConstraint columnSpan="10"/>
+            </tc:out>
+
+        </tc:box>
+
+        <tc:script file="script/tobago-assert.js"/>
+        <tc:script onload="TobagoAssert.assertLayout('page:l1', 6, 26, 4, 14);"/>
+        <tc:script onload="TobagoAssert.assertLayout('page:l2', 15, 26, 8, 14);"/>
+        <tc:script onload="TobagoAssert.assertLayout('page:l3', 28, 26, 12, 14);"/>
+        <tc:script onload="TobagoAssert.assertLayout('page:l4', 45, 26, 24, 14);"/>
+        <tc:script onload="TobagoAssert.assertLayout('page:l5', 74, 26, 28, 14);"/>
+        <tc:script onload="TobagoAssert.assertLayout('page:l6', 107, 26, 32, 14);"/>
+        <tc:script onload="TobagoAssert.assertLayout('page:l7', 144, 26, 16, 14);"/>
+
+    </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/markup/tobago-1215.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/markup/tobago-1215.selenium.html
new file mode 100644
index 0000000..4342922
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/markup/tobago-1215.selenium.html
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/markup/tobago-1215.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>assertElementHeight</td>
+	<td>//img</td>
+	<td>200</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:button</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForValue</td>
+	<td>page:counter</td>
+	<td>1</td>
+</tr>
+<tr>
+	<td>assertElementHeight</td>
+	<td>//img</td>
+	<td>200</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/markup/tobago-1215.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/markup/tobago-1215.xhtml
new file mode 100644
index 0000000..b31202f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/markup/tobago-1215.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="page" width="300px" height="600px">
+    <tc:panel id="panel">
+
+      <f:facet name="layout">
+        <tc:gridLayout rows="50px;auto;auto;auto;auto" />
+      </f:facet>
+
+      <tc:out value="An image with the preferred height of 200, to test Bug TOBAGO-1215. The test is successful, if the image has the same height of 200 after the reload."/>
+
+      <tc:image markup="double" value="pidgeon-point.jpg" id="image"/>
+
+      <tc:in label="Counter" fieldId="counter" value="#{reload.counter}" readonly="true"/>
+
+      <tc:button label="Reload (AJAX)" id="button" action="#{reload.tick}">
+        <f:ajax render="panel" execute="panel"/>
+      </tc:button>
+
+      <tc:button label="Reset Counter" action="#{reload.reset}"/>
+
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/messages/messages-confirmation.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/messages/messages-confirmation.xhtml
new file mode 100644
index 0000000..44fc296
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/messages/messages-confirmation.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:box label="Messages must be confirmed here">
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;*"/>
+      </f:facet>
+
+      <tc:messages id="mymessages" confirmation="true"/>
+
+      <tc:button label="Please click to show the messages" action="#{messages.createMessages}"/>
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/messages/messages.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/messages/messages.xhtml
new file mode 100644
index 0000000..77c1f61
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/messages/messages.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*;auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:messages/>
+    <tc:textarea required="true"/>
+    <tc:button label="submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/object/object-full.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/object/object-full.xhtml
new file mode 100644
index 0000000..bdad532
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/object/object-full.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:object src="http://www.apache.org/"/>
+
+    <tc:script>
+
+      /* XXX This is a one possible workaround to make the content resizable.
+       * XXX We may find a better solution (e. g. partially switch off layout)
+       */
+
+      jQuery(document).ready(function () {
+        jQuery("form").css("width", "100%");
+        jQuery("form").css("height", "100%");
+        jQuery(".tobago-page-content").css("width", "100%");
+        jQuery(".tobago-page-content").css("height", "100%");
+        jQuery("iframe").css("width", "100%");
+        jQuery("iframe").css("height", "100%");
+      });
+    </tc:script>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/page/html.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/page/html.xhtml
new file mode 100644
index 0000000..47732ea
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/page/html.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns="http://www.w3.org/1999/xhtml">
+
+  <tc:page>
+
+    <ol>
+      <li>
+        One
+      </li>
+      <li>
+        Two
+      </li>
+      <li>
+        Three
+      </li>
+    </ol>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/page/page.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/page/page.xhtml
new file mode 100644
index 0000000..3b15ea7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/page/page.xhtml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:textarea value="this is to test the size"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1091.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1091.selenium.html
new file mode 100644
index 0000000..20829b3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1091.selenium.html
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/" />
+<title>Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/popup/popup-bug-tobago-1091.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:check</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:open</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:popup:close</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:check</td>
+	<td>on</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1091.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1091.xhtml
new file mode 100644
index 0000000..3418329
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1091.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page width="800px" height="300px" id="page">
+
+    <tc:box label="TOBAGO-1091">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;*;auto;auto;auto"/>
+      </f:facet>
+      <tc:link
+          label="Bug-Tracking: TOBAGO-1091" link="https://issues.apache.org/jira/browse/TOBAGO-1091"/>
+      <tc:out escape="false" value="Close popup with defaultCommand uncheckes a checkbox on main page.
+      &lt;br/>Checklist:
+      &lt;ol>
+      &lt;li>Check: checkbox is checked&lt;/li>
+      &lt;li>Click on the open button&lt;/li>
+      &lt;li>Click on the close button&lt;/li>
+      &lt;li>Check: checkbox is checked&lt;/li>
+      &lt;/ol>"/>
+
+      <tc:in label="Input" value="test" fieldId="in"/>
+      <tc:selectBooleanCheckbox label="Checkbox" value="true" fieldId="check"/>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="auto;*"/>
+        </f:facet>
+        <tc:button label="Open Popup" id="open">
+          <f:facet name="popup">
+            <tc:popup width="100px" height="100px" id="popup">
+              <tc:box label="Popup" id="box">
+                <f:facet name="layout">
+                  <tc:gridLayout rows="*;auto"/>
+                </f:facet>
+                <tc:panel/>
+                <tc:button label="Close" id="close" defaultCommand="true">
+                  <tc:attribute name="popupClose" value="afterSubmit"/>
+                </tc:button>
+              </tc:box>
+            </tc:popup>
+          </f:facet>
+        </tc:button>
+      </tc:panel>
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1103.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1103.selenium.html
new file mode 100644
index 0000000..7a4ffe7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1103.selenium.html
@@ -0,0 +1,157 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/popup/popup-bug-tobago-1103.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:open-0</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>id=page:popup-1:open-1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:open-1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>id=page:popup-1:popup-2:form:picker</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:popup-2:form:picker</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>id=page:popup-1:popup-2:form:pickerpopup:cancel</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:popup-2:form:pickerpopup:cancel</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>id=page:popup-1:popup-2:form:pickerpopup</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:popup-2:close-2</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>id=page:popup-1:popup-2</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:close-1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>id=page:popup-1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:open-0</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>id=page:popup-1:open-1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:open-1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>id=page:popup-1:popup-2:form:picker</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:popup-2:open-2</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementPresent</td>
+	<td>id=page:popup-1:popup-2:popup-3:close-3</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:popup-2:popup-3:close-3</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>id=page:popup-1:popup-2:popup-3</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:popup-2:close-2</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>id=page:popup-1:popup-2</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup-1:close-1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>id=page:popup-1</td>
+	<td></td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1103.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1103.xhtml
new file mode 100644
index 0000000..4cc40a2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-bug-tobago-1103.xhtml
@@ -0,0 +1,97 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page width="600px" height="350px" id="page">
+
+    <f:facet name="layout">
+      <tc:gridLayout margin="100px"/>
+    </f:facet>
+
+    <tc:box label="Page">
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;auto"/>
+      </f:facet>
+      <tc:out value="Test: Open all popups (also the date picker). Then try to close all."/>
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="auto;*"/>
+        </f:facet>
+        <tc:button label="Open Popup (AJAX)" id="open-0">
+          <f:ajax render="popup-1" execute="popup-1"/>
+          <f:facet name="popup">
+            <tc:popup width="400px" height="150px" left="150px" top="150px" id="popup-1">
+              <tc:box label="Popup Level 1" id="box-1">
+                <f:facet name="layout">
+                  <tc:gridLayout rows="auto;auto;*;auto"/>
+                </f:facet>
+                <tc:panel>
+                  <f:facet name="layout">
+                    <tc:gridLayout columns="*;*;*;*"/>
+                  </f:facet>
+                  <tc:button label="Open Sub Popup (AJAX)" id="open-1">
+                    <f:ajax render="popup-2" execute="popup-2"/>
+                    <f:facet name="popup">
+                      <tc:popup width="400px" height="150px" left="200px" top="200px" id="popup-2">
+                        <tc:box label="Popup Level 2" id="box-2">
+                          <f:facet name="layout">
+                            <tc:gridLayout rows="auto;auto"/>
+                          </f:facet>
+                          <tc:date label="Date" id="txdate" fieldId="date" pickerId="picker" formId="form">
+                            <f:convertDateTime pattern="dd/MM/yyyy"/>
+                          </tc:date>
+                          <tc:button label="Open Sub Popup (AJAX)" id="open-2">
+                            <f:ajax render="popup-3" execute="popup-3"/>
+                            <f:facet name="popup">
+                              <tc:popup modal="false" width="200px" height="53px" left="250px" top="250px" id="popup-3">
+                                <tc:box label="Popup Level 3 (non modal)" id="box-3">
+                                  <f:facet name="layout">
+                                    <tc:gridLayout rows="auto;*"/>
+                                  </f:facet>
+                                  <tc:button label="Cancel" id="close-3">
+                                    <tc:attribute name="popupClose" value="immediate"/>
+                                  </tc:button>
+                                  <tc:panel/>
+                                </tc:box>
+                              </tc:popup>
+                            </f:facet>
+                          </tc:button>
+                          <tc:button label="Cancel" id="close-2">
+                            <tc:attribute name="popupClose" value="immediate"/>
+                          </tc:button>
+                          <tc:panel/>
+                        </tc:box>
+                      </tc:popup>
+                    </f:facet>
+                  </tc:button>
+                  <tc:button label="Cancel" id="close-1">
+                    <tc:attribute name="popupClose" value="immediate"/>
+                  </tc:button>
+                </tc:panel>
+              </tc:box>
+            </tc:popup>
+          </f:facet>
+        </tc:button>
+      </tc:panel>
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-close-after-submit-and-ajax.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-close-after-submit-and-ajax.selenium.html
new file mode 100644
index 0000000..d66b099
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-close-after-submit-and-ajax.selenium.html
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/" />
+<title>Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/popup/popup-close-after-submit-and-ajax.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:readonly</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:open</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>id=page:popup:in</td>
+	<td>foo bar</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:popup:close</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>id=page:popup:close</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:readonly</td>
+	<td>foo bar</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-close-after-submit-and-ajax.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-close-after-submit-and-ajax.xhtml
new file mode 100644
index 0000000..8eadd76
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-close-after-submit-and-ajax.xhtml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page width="800px" height="300px" id="page">
+
+    <tc:box label="Popup close after submit and AJAX" id="global">
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;auto;auto"/>
+      </f:facet>
+      <tc:out escape="false" value="Test: Close popup partially after the submit.
+      &lt;br/>Checklist:
+      &lt;ol>
+      &lt;li>Check the Readonly Value&lt;/li>
+      &lt;li>Click on the OPEN button&lt;/li>
+      &lt;li>Edit the value in the popup&lt;/li>
+      &lt;li>Click on the SAVE button&lt;/li>
+      &lt;li>Check if popup is closed (&lt;b>fails in the moment!!! The popup wouldn't close&lt;/b>)&lt;/li>
+      &lt;li>Check if the readonly value has been changed&lt;/li>
+      &lt;/ol>"/>
+
+      <tc:in label="Readonly Value" value="#{popupData.value}" readonly="true" fieldId="readonly"/>
+
+      <tc:panel>
+        <f:facet name="layout">
+          <tc:gridLayout columns="auto;*"/>
+        </f:facet>
+        <tc:button label="Open Popup" id="open">
+          <f:facet name="popup">
+            <tc:popup width="200px" height="100px" id="popup">
+              <tc:box label="Popup" id="box">
+                <f:facet name="layout">
+                  <tc:gridLayout rows="*;auto"/>
+                </f:facet>
+                <tc:in label="Edit Value" value="#{popupData.value}" fieldId="in"/>
+                <tc:button label="Save and Close" id="close">
+                  <f:ajax render=":page:global" execute=":page:global"/>
+                  <tc:attribute name="popupClose" value="afterSubmit"/>
+                </tc:button>
+              </tc:box>
+            </tc:popup>
+          </f:facet>
+        </tc:button>
+      </tc:panel>
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-draggable.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-draggable.selenium.html
new file mode 100644
index 0000000..1220d43
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-draggable.selenium.html
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/popup/popup-draggable.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:open</td>
+	<td></td>
+</tr>
+<tr>
+	<td>assertElementPositionLeft</td>
+	<td>//div[@id='page:popup:box']/div/div/div</td>
+	<td>350</td>
+</tr>
+<tr>
+	<td>assertElementPositionTop</td>
+	<td>//div[@id='page:popup:box']/div/div/div</td>
+	<td>100</td>
+</tr>
+<tr>
+	<td>dragAndDrop</td>
+	<td>//div[@id='page:popup:box']/div/div/div</td>
+	<td>-150,50</td>
+</tr>
+<tr>
+	<td>assertElementPositionLeft</td>
+	<td>//div[@id='page:popup:box']/div/div/div</td>
+	<td>200</td>
+</tr>
+<tr>
+	<td>assertElementPositionTop</td>
+	<td>//div[@id='page:popup:box']/div/div/div</td>
+	<td>150</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-draggable.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-draggable.xhtml
new file mode 100644
index 0000000..a1519b7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-draggable.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page width="800px" height="300px" id="page">
+
+    <tc:box label="Popup draggable">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;*;auto;auto;auto"/>
+      </f:facet>
+
+      <tc:button label="Open Popup" id="open">
+        <f:facet name="popup">
+          <tc:popup width="100px" height="100px" id="popup">
+            <tc:box label="Popup" id="box">
+              <f:facet name="layout">
+                <tc:gridLayout rows="*;auto"/>
+              </f:facet>
+              <tc:panel/>
+              <tc:button label="Close" id="close" defaultCommand="true">
+                <tc:attribute name="popupClose" value="afterSubmit"/>
+              </tc:button>
+            </tc:box>
+          </tc:popup>
+        </f:facet>
+      </tc:button>
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-in-sheet.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-in-sheet.xhtml
new file mode 100644
index 0000000..5b02e82
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/popup-in-sheet.xhtml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page width="800px" height="300px" id="page">
+    <tc:box label="Popups inside sheet">
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;0px;0px"/>
+      </f:facet>
+
+      <tc:sheet id="sheet"
+                var="entry" columns="1*;1*;1*;1*" value="#{popupReference.sheet}">
+
+        <tc:column label="Column 1">
+          <tc:link label="#{entry.column1}" actionListener="#{popupReference.selectEntry}">
+            <f:ajax render=":page:popup1" execute=":page:popup1"/>
+            <tc:popupReference for=":page:popup1"/>
+          </tc:link>
+        </tc:column>
+
+        <tc:column label="Column 2">
+          <tc:out value="#{entry.column2}"/>
+        </tc:column>
+
+        <tc:column label="Column 3">
+          <tc:out value="#{entry.column3}"/>
+        </tc:column>
+
+        <tc:column label="Edit">
+          <tc:button label="Edit" actionListener="#{popupReference.selectEntry}">
+            <f:ajax render=":page:popup2" execute=":page:popup2"/>
+            <tc:popupReference for=":page:popup2"/>
+          </tc:button>
+        </tc:column>
+
+      </tc:sheet>
+
+      <tc:popup id="popup1" width="300px" height="100px">
+        <!-- the clientId of this popup is "page:sheet:popup1" -->
+        <tc:box label="Popup1">
+          <f:facet name="layout">
+            <tc:gridLayout rows="auto;1*;auto"/>
+          </f:facet>
+          <tc:in label="column 1 value:" value="#{popupReference.entry.column1}"/>
+          <tc:panel/>
+          <tc:panel>
+            <f:facet name="layout">
+              <tc:gridLayout columns="1*;auto;auto"/>
+            </f:facet>
+            <tc:panel/>
+            <tc:button label="Save" actionListener="#{popupReference.saveChanges}">
+              <f:ajax render=":page:sheet" execute=":page:sheet"/>
+              <tc:attribute name="popupClose" value="afterSubmit"/>
+            </tc:button>
+            <tc:button label="Cancel">
+              <tc:attribute name="popupClose" value="immediate"/>
+            </tc:button>
+          </tc:panel>
+        </tc:box>
+      </tc:popup>
+
+      <tc:popup id="popup2" width="300px" height="150px">
+        <!-- the clientId of this popup is "page:sheet:popup2" -->
+        <tc:box label="Popup1">
+          <f:facet name="layout">
+            <tc:gridLayout rows="auto;auto;auto;1*;auto"/>
+          </f:facet>
+          <tc:in label="column 1 value:" value="#{popupReference.entry.column1}"/>
+          <tc:in label="column 2 value:" value="#{popupReference.entry.column2}"/>
+          <tc:in label="column 3 value:" value="#{popupReference.entry.column3}"/>
+          <tc:panel/>
+          <tc:panel>
+            <f:facet name="layout">
+              <tc:gridLayout columns="1*;auto;auto"/>
+            </f:facet>
+            <tc:panel/>
+            <tc:button label="Save" actionListener="#{popupReference.saveChanges}">
+              <f:ajax render=":page:sheet" execute=":page:sheet"/>
+              <tc:attribute name="popupClose" value="afterSubmit"/>
+            </tc:button>
+            <tc:button label="Cancel">
+              <tc:attribute name="popupClose" value="immediate"/>
+            </tc:button>
+          </tc:panel>
+        </tc:box>
+      </tc:popup>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/z-index.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/z-index.xhtml
new file mode 100644
index 0000000..8b2a959
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/popup/z-index.xhtml
@@ -0,0 +1,388 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+<tc:page width="800px" height="600px" id="page">
+<f:facet name="menuBar">
+<tc:bar>
+<tc:link label="space -> space -> space"/>
+
+<tc:link label="Help">
+<tc:link label="Help 1">
+  <tc:link label="Help 1 1">
+  </tc:link>
+  <tc:separator/>
+  <tc:link label="Help 1 2">
+  </tc:link>
+  <tc:link label="Help 1 3">
+  </tc:link>
+  <tc:link label="Help 1 4">
+  </tc:link>
+  <tc:separator/>
+  <tc:link label="Help 1 5">
+  </tc:link>
+  <tc:link label="Help 1 6">
+  </tc:link>
+  <tc:link label="Help 1 7">
+  </tc:link>
+  <tc:separator/>
+  <tc:link label="Help 1 8">
+  </tc:link>
+  <tc:link label="Help 1 9">
+  </tc:link>
+  <tc:link label="Help 1 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 2">
+  <tc:link label="Help 2 1">
+  </tc:link>
+  <tc:link label="Help 2 2">
+  </tc:link>
+  <tc:link label="Help 2 3">
+  </tc:link>
+  <tc:link label="Help 2 4">
+  </tc:link>
+  <tc:link label="Help 2 5">
+  </tc:link>
+  <tc:link label="Help 2 6">
+  </tc:link>
+  <tc:link label="Help 2 7">
+  </tc:link>
+  <tc:link label="Help 2 8">
+  </tc:link>
+  <tc:link label="Help 2 9">
+  </tc:link>
+  <tc:link label="Help 2 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 3">
+  <tc:link label="Help 3 1">
+  </tc:link>
+  <tc:link label="Help 3 2">
+  </tc:link>
+  <tc:link label="Help 3 3">
+  </tc:link>
+  <tc:link label="Help 3 4">
+  </tc:link>
+  <tc:link label="Help 3 5">
+  </tc:link>
+  <tc:link label="Help 3 6">
+  </tc:link>
+  <tc:link label="Help 3 7">
+  </tc:link>
+  <tc:link label="Help 3 8">
+  </tc:link>
+  <tc:link label="Help 3 9">
+  </tc:link>
+  <tc:link label="Help 3 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 4">
+  <tc:link label="Help 4 1">
+  </tc:link>
+  <tc:link label="Help 4 2">
+  </tc:link>
+  <tc:link label="Help 4 3">
+  </tc:link>
+  <tc:link label="Help 4 4">
+  </tc:link>
+  <tc:link label="Help 4 5">
+  </tc:link>
+  <tc:link label="Help 4 6">
+  </tc:link>
+  <tc:link label="Help 4 7">
+  </tc:link>
+  <tc:link label="Help 4 8">
+  </tc:link>
+  <tc:link label="Help 4 9">
+  </tc:link>
+  <tc:link label="Help 4 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 5">
+  <tc:link label="Help 5 1">
+  </tc:link>
+  <tc:link label="Help 5 2">
+  </tc:link>
+  <tc:link label="Help 5 3">
+  </tc:link>
+  <tc:link label="Help 5 4">
+  </tc:link>
+  <tc:link label="Help 5 5">
+  </tc:link>
+  <tc:link label="Help 5 6">
+  </tc:link>
+  <tc:link label="Help 5 7">
+  </tc:link>
+  <tc:link label="Help 5 8">
+  </tc:link>
+  <tc:link label="Help 5 9">
+  </tc:link>
+  <tc:link label="Help 5 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 6">
+  <tc:link label="Help 6 1">
+  </tc:link>
+  <tc:link label="Help 6 2">
+  </tc:link>
+  <tc:link label="Help 6 3">
+  </tc:link>
+  <tc:link label="Help 6 4">
+  </tc:link>
+  <tc:link label="Help 6 5">
+  </tc:link>
+  <tc:link label="Help 6 6">
+  </tc:link>
+  <tc:link label="Help 6 7">
+  </tc:link>
+  <tc:link label="Help 6 8">
+  </tc:link>
+  <tc:link label="Help 6 9">
+  </tc:link>
+  <tc:link label="Help 6 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 7">
+  <tc:link label="Help 7 1">
+  </tc:link>
+  <tc:link label="Help 7 2">
+  </tc:link>
+  <tc:link label="Help 7 3">
+  </tc:link>
+  <tc:link label="Help 7 4">
+  </tc:link>
+  <tc:link label="Help 7 5">
+  </tc:link>
+  <tc:link label="Help 7 6">
+  </tc:link>
+  <tc:link label="Help 7 7">
+  </tc:link>
+  <tc:link label="Help 7 8">
+  </tc:link>
+  <tc:link label="Help 7 9">
+  </tc:link>
+  <tc:link label="Help 7 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 8">
+  <tc:link label="Help 8 1">
+  </tc:link>
+  <tc:link label="Help 8 2">
+  </tc:link>
+  <tc:link label="Help 8 3">
+  </tc:link>
+  <tc:link label="Help 8 4">
+  </tc:link>
+  <tc:link label="Help 8 5">
+  </tc:link>
+  <tc:link label="Help 8 6">
+  </tc:link>
+  <tc:link label="Help 8 7">
+  </tc:link>
+  <tc:link label="Help 8 8">
+  </tc:link>
+  <tc:link label="Help 8 9">
+  </tc:link>
+  <tc:link label="Help 8 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 9">
+  <tc:link label="Help 9 1">
+  </tc:link>
+  <tc:link label="Help 9 2">
+  </tc:link>
+  <tc:link label="Help 9 3">
+  </tc:link>
+  <tc:link label="Help 9 4">
+  </tc:link>
+  <tc:link label="Help 9 5">
+  </tc:link>
+  <tc:link label="Help 9 6">
+  </tc:link>
+  <tc:link label="Help 9 7">
+  </tc:link>
+  <tc:link label="Help 9 8">
+  </tc:link>
+  <tc:link label="Help 9 9">
+  </tc:link>
+  <tc:link label="Help 9 10">
+  </tc:link>
+</tc:link>
+<tc:link label="Help 10">
+  <tc:link label="Help 10 1">
+  </tc:link>
+  <tc:link label="Help 10 2">
+  </tc:link>
+  <tc:link label="Help 10 3">
+  </tc:link>
+  <tc:link label="Help 10 4">
+  </tc:link>
+  <tc:link label="Help 10 5">
+  </tc:link>
+  <tc:link label="Help 10 6">
+  </tc:link>
+  <tc:link label="Help 10 7">
+  </tc:link>
+  <tc:link label="Help 10 8">
+  </tc:link>
+  <tc:link label="Help 10 9">
+  </tc:link>
+  <tc:link label="Help 10 10">
+  </tc:link>
+</tc:link>
+</tc:link>
+</tc:bar>
+
+</f:facet>
+
+<tc:box label="Page (z-index = 0)">
+  <f:facet name="layout">
+    <tc:gridLayout rows="60px;auto;auto;*;auto;auto"/>
+  </f:facet>
+  <tc:out
+      value="This page is to check, if the layered presentation is corret. It will be usually defined by setting
+           the z-index in CSS or by the order of rendering in the document. The footer and header of the sheet
+           also have the z-index set in the common renderer."/>
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;4*"/>
+    </f:facet>
+
+    <tc:link label="Link to Apache" link="http://www.apache.org/"/>
+    <tc:date label="Date">
+      <f:convertDateTime pattern="dd/MM/yyyy"/>
+    </tc:date>
+  </tc:panel>
+  <tc:selectOneChoice>
+    <tc:selectItem itemLabel="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" itemValue="A"/>
+    <tc:selectItem itemLabel="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" itemValue="B"/>
+    <tc:selectItem itemLabel="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" itemValue="C"/>
+  </tc:selectOneChoice>
+  <tc:sheet var="v1" columns="*;*;*" showRowRange="left" showPageRange="right" showDirectLinks="center">
+    <tc:column label="Column 1"/>
+    <tc:column label="Column 2"/>
+    <tc:column label="Column 3"/>
+  </tc:sheet>
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*"/>
+    </f:facet>
+    <tc:selectBooleanCheckbox label="1st Popup Modal" value="#{zIndex.modal1}" id="modal1st"/>
+    <tc:panel/>
+    <tc:selectBooleanCheckbox label="2nd Popup Modal" value="#{zIndex.modal2}"/>
+    <tc:panel/>
+  </tc:panel>
+  <tc:panel>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto;auto;*"/>
+    </f:facet>
+    <tc:button label="Open Popup">
+      <f:facet name="popup">
+        <tc:popup width="600px" height="470px" left="100px" top="100px" id="popup-1" modal="#{zIndex.modal1}">
+          <tc:box label="Popup (z-index = 1 (TODO))" id="box-1">
+            <f:facet name="layout">
+              <tc:gridLayout rows="auto;auto;*;auto"/>
+            </f:facet>
+            <tc:date label="Date">
+              <f:convertDateTime pattern="dd/MM/yyyy"/>
+            </tc:date>
+            <tc:selectOneChoice>
+              <tc:selectItem itemLabel="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" itemValue="A"/>
+              <tc:selectItem itemLabel="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" itemValue="B"/>
+              <tc:selectItem itemLabel="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" itemValue="C"/>
+            </tc:selectOneChoice>
+            <tc:sheet var="v1" columns="*;*;*" showRowRange="left" showPageRange="right" showDirectLinks="center">
+              <tc:column label="Column 1"/>
+              <tc:column label="Column 2"/>
+              <tc:column label="Column 3"/>
+            </tc:sheet>
+            <tc:panel>
+              <f:facet name="layout">
+                <tc:gridLayout columns="*;*;*;*"/>
+              </f:facet>
+              <tc:button label="Open Sub Popup">
+                <f:facet name="popup">
+                  <tc:popup width="400px" height="500px" left="200px" top="50px" id="popup-2" modal="#{zIndex.modal2}">
+                    <tc:box label="Popup (z-index = 2 (TODO))" id="box-2">
+                      <f:facet name="layout">
+                        <tc:gridLayout rows="auto;auto;*;auto"/>
+                      </f:facet>
+                      <tc:date label="Date">
+                        <f:convertDateTime pattern="dd/MM/yyyy"/>
+                      </tc:date>
+                      <tc:selectOneChoice>
+                        <tc:selectItem itemLabel="AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" itemValue="A"/>
+                        <tc:selectItem itemLabel="BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB" itemValue="B"/>
+                        <tc:selectItem itemLabel="CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC" itemValue="C"/>
+                      </tc:selectOneChoice>
+                      <tc:sheet var="v1" columns="*;*;*" showRowRange="left" showPageRange="right"
+                                showDirectLinks="center">
+                        <tc:column label="Column 1"/>
+                        <tc:column label="Column 2"/>
+                        <tc:column label="Column 3"/>
+                      </tc:sheet>
+                      <tc:panel>
+                        <f:facet name="layout">
+                          <tc:gridLayout columns="*;*;*"/>
+                        </f:facet>
+                        <tc:button label="Cancel">
+                          <tc:attribute name="popupClose" value="immediate"/>
+                        </tc:button>
+                        <tc:button label="Redisplay">
+                          <f:ajax render="box-2" execute="box-2"/>
+                        </tc:button>
+                        <tc:button label="Ok">
+                          <tc:attribute name="popupClose" value="afterSubmit"/>
+                        </tc:button>
+                      </tc:panel>
+                    </tc:box>
+                  </tc:popup>
+                </f:facet>
+              </tc:button>
+              <tc:button label="Open Popup (AJAX)">
+                <f:ajax render="popup-2" execute="popup-2"/>
+                <tc:popupReference for="popup-2"/>
+              </tc:button>
+              <tc:button label="Cancel">
+                <tc:attribute name="popupClose" value="immediate"/>
+              </tc:button>
+              <tc:button label="Redisplay">
+                <f:ajax render="box-1" execute="box-1"/>
+              </tc:button>
+              <tc:button label="Ok">
+                <tc:attribute name="popupClose" value="afterSubmit"/>
+              </tc:button>
+            </tc:panel>
+          </tc:box>
+        </tc:popup>
+      </f:facet>
+    </tc:button>
+    <tc:button label="Open Popup (AJAX)">
+      <f:ajax render="popup-1" execute="popup-1"/>
+      <tc:popupReference for="popup-1"/>
+    </tc:button>
+    <tc:button label="Update"/>
+  </tc:panel>
+</tc:box>
+</tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/progress/progress-tobago-1218.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/progress/progress-tobago-1218.xhtml
new file mode 100644
index 0000000..7e16a28
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/progress/progress-tobago-1218.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="1000px" height="100px"/>
+    <f:facet name="layout">
+      <tc:gridLayout margin="20px" />
+    </f:facet>
+
+    <tc:progress value="#{progress.emptyRange}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/progress/progress.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/progress/progress.xhtml
new file mode 100644
index 0000000..67867a1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/progress/progress.xhtml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="1000px" height="100px"/>
+    <f:facet name="layout">
+      <tc:gridLayout margin="20px" />
+    </f:facet>
+
+    <tc:progress value="#{progress.range}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/reload/tip.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/reload/tip.xhtml
new file mode 100644
index 0000000..b54a725
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/reload/tip.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view xmlns:tc="http://myfaces.apache.org/tobago/component"
+            xmlns:ui="http://java.sun.com/jsf/facelets"
+        xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <tc:separator label="Reload test for tips."/>
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout margin="10px" rows="20px;auto;20px;auto;" columns="300px"/>
+      </f:facet>
+      <f:facet name="reload">
+        <tc:reload frequency="5000" update="#{reload.reload}"/>
+      </f:facet>
+
+      <tc:out value="This panel will be reloaded every 5 seconds."/>
+
+      <tc:in value="#{reload.counter}" readonly="true" tip="Test of &quot; (quotation mark)"/>
+
+      <tc:label value="Label" tip="Test of &quot; (quotation mark)"/>
+
+      <tc:selectOneChoice tip="Test of &quot; (quotation mark)">
+        <tc:selectItem itemValue="a" itemLabel="A Value"/>
+        <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+      </tc:selectOneChoice>
+    </tc:panel>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/resource/resource-manager.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/resource/resource-manager.xhtml
new file mode 100644
index 0000000..503ee5d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/resource/resource-manager.xhtml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:in label="Fails" markup="#{resourceBean.fails == 2 ? '' : 'error' }"
+           value="#{resourceBean.fails}" tip="expected are 2"/>
+
+    <tc:messages/>
+
+    <tc:sheet columns="3*;*;*;3*" value="#{resourceBean.resultList}" var="item">
+      <tc:column label="Name">
+        <tc:out value="#{item.name}"/>
+      </tc:column>
+      <tc:column label="Type">
+        <tc:out value="#{item.type}"/>
+      </tc:column>
+      <tc:column label="Valid">
+        <tc:out value="#{item.valid}"/>
+      </tc:column>
+      <tc:column label="Comment">
+        <tc:out value="#{item.comment}"/>
+      </tc:column>
+    </tc:sheet>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/resource/tobago-694.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/resource/tobago-694.xhtml
new file mode 100644
index 0000000..37f0fca
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/resource/tobago-694.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto;*" columns="auto"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:messages/>
+
+    <tc:image value="image/wait/cat.jpg">
+      <tc:gridLayoutConstraint width="100px" height="106px"/>
+    </tc:image>
+
+    <tc:in label="Counter:" value="#{reload.counter}" readonly="true"/>
+
+    <tc:button label="submit" action="#{reload.isReload}"/>
+
+    <tc:panel/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/script/script-event.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/script/script-event.js
new file mode 100644
index 0000000..be990a4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/script/script-event.js
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+ScriptEvent = {};
+
+ScriptEvent.onload = function() {
+  jQuery.ajax({url:"/ScriptEventServlet?event=onload",async:false});
+};
+
+ScriptEvent.onunload = function() {
+  jQuery.ajax({url:"/ScriptEventServlet?event=onunload",async:false});
+};
+
+ScriptEvent.onexit = function() {
+  jQuery.ajax({url:"/ScriptEventServlet?event=onexit",async:false});
+};
+
+function showTime() {
+  jQuery(Tobago.Utils.escapeClientId("page:list")).find(".tobago-box-header").html(formatDate(new Date(), "hh:mm:ss"));
+  setTimeout(showTime, 500);
+}
+
+setTimeout(showTime, 0);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/script/script-event.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/script/script-event.xhtml
new file mode 100644
index 0000000..ade9b22
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/script/script-event.xhtml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;*" rows="auto;*"/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2" />
+    </tc:messages>
+
+    <tc:box id="panel">
+      <f:facet name="layout">
+        <tc:gridLayout rows="*;auto;auto;auto"/>
+      </f:facet>
+
+      <tc:script
+          file="test/script/script-event.js"
+          onload="ScriptEvent.onload();"
+          onunload="ScriptEvent.onunload();"
+          onexit="ScriptEvent.onexit();">
+      </tc:script>
+
+      <tc:out value="TODO: write an automated tests."/>
+
+      <tc:button label="No Action"/>
+      <tc:button label="Action" action="#{scriptEvent.action}"/>
+      <tc:button label="External link" link="http://www.apache.org" target="_blank"/>
+
+    </tc:box>
+
+    <tc:box id="list" label="time">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;*"/>
+      </f:facet>
+
+      <tc:button label="Reload List">
+        <f:ajax render="list" execute="list"/>
+      </tc:button>
+
+      <tc:sheet value="#{scriptEvent.items}" var="item">
+        <tc:column label="Event">
+          <tc:out value="#{item.name}"/>
+        </tc:column>
+        <tc:column label="Time">
+          <tc:out value="#{item.time}">
+            <f:convertDateTime timeStyle="long" type="time"/>
+          </tc:out>
+        </tc:column>
+      </tc:sheet>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/section/section.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/section/section.xhtml
new file mode 100644
index 0000000..825a31c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/section/section.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:flowLayout>
+
+      <tc:section label="Main Section" image="fa-heart">
+        <tc:section label="1st Sub-Section">
+          1st content
+        </tc:section>
+        <tc:section>
+          2nd content (title has no label nor image)
+        </tc:section>
+        <tc:section label="3rd Sub-Section with image" image="fa-star">
+          3rd content
+        </tc:section>
+        <tc:section image="fa-star-o">
+          4th content (title has only an image)
+          <tc:section label="Sub-Sub-Section" image="fa-star-o">
+            <tc:section label="Sub-Sub-Sub-Section" image="fa-star-o">
+              <tc:section label="Sub-Sub-Sub-Sub-Section" image="fa-star-o">
+                <tc:section label="Sub-Sub-Sub-Sub-Sub-Section" image="fa-star-o">
+                  Level 6
+                </tc:section>
+              </tc:section>
+            </tc:section>
+          </tc:section>
+        </tc:section>
+
+      </tc:section>
+    </tc:flowLayout>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/buttons-with-image.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/buttons-with-image.xhtml
new file mode 100644
index 0000000..2754e81
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/buttons-with-image.xhtml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+
+    <tc:segmentLayout large="1;1;1;1;1;1;1;1;1;1;1;1" medium="3;3;3;3">
+
+      <tc:button image="fa-remove" label="1a Abbrechen" />
+      <tc:button image="fa-refresh" label="1b Aktualisieren" />
+      <tc:button image="fa-paperclip" label="1c Anhang" />
+      <tc:button image="fa-sign-in" label="1d Anmelden" />
+
+      <!-- XXX here is a problem in Firefox 40 and IE 11 when rendering.
+      XXX In Chrome and Safari the page is okay.
+      The image="image/feather-leaf" will create an <img> tag in HTML. This will break the
+      12 column layout:
+      The next line begins after this button, and not in the first column.
+
+      The reason is, that the image is slightly higher than the icon
+      -->
+      <tc:button image="image/feather-leaf" label="2a Ansicht öffnen" />
+      <tc:button image="fa-eye-close" label="2b Ansicht schließen" />
+      <tc:button image="fa-tasks" label="2c Aufgabe" />
+      <tc:button image="fa-scissors" label="2d Ausschneiden" />
+
+      <tc:button image="fa-pencil" label="3a Bearbeiten" />
+      <tc:button image="fa-sign-out" label="3b Beenden" />
+      <tc:button image="fa-bookmark" label="3c Bookmark" />
+      <tc:button image="fa-asterisk" label="3d Clear" />
+
+      <tc:button image="fa-export" label="4a Dateiexport" />
+      <tc:button image="fa-th-list" label="4b Detail" />
+      <tc:button image="fa-stats" label="4c Diagramm" />
+      <tc:button image="fa-modal-window" label="4d Display" />
+
+      <tc:button image="fa-file" label="5a Dokument" />
+      <tc:button image="fa-envelope" label="5b Email" />
+      <tc:button image="fa-minus" label="5c Entfernen" />
+      <tc:button image="fa-ok" label="5d Fertig" />
+
+      <tc:button image="fa-filter" label="6a Filtern" />
+      <tc:button image="image/feather-leaf" label="6b Gruppe" />
+      <tc:button image="fa-question-circle" label="6c Hilfe" />
+      <tc:button image="fa-plus" label="6d Hinzufügen" />
+
+      <tc:button image="fa-home" label="7a Home" />
+      <tc:button image="fa-calendar" label="7b Kalender" />
+      <tc:button image="fa-copy" label="7c Kopieren" />
+      <tc:button image="fa-trash" label="7d Löschen" />
+
+      <tc:button image="fa-resize-full" label="8a Maximieren" />
+      <tc:button image="fa-resize-small" label="8b Minimieren" />
+      <tc:button image="fa-file" label="8c Neu" />
+      <tc:button image="fa-folder-open" label="8d Öffnen" />
+
+      <tc:button image="fa-undo" label="9a Rückgängig" />
+      <tc:button image="fa-lock" label="9b Sicherheit" />
+      <tc:button image="fa-save" label="9c Sichern" />
+      <tc:button image="fa-search" label="9d Suchen" />
+
+      <tc:button image="fa-clock-o" label="10a Uhrzeit" />
+      <tc:button image="fa-forward" label="10b Weiter" />
+      <tc:button image="fa-repeat" label="10c Erneut" />
+      <tc:button image="fa-backward" label="10d Zurück" />
+
+      <tc:button image="fa-import" label="11a Dateiimport" />
+      <tc:button image="fa-link" label="11b Link" />
+      <tc:button image="fa-folder-close" label="11c Ordner schließen" />
+      <tc:button image="fa-folder-open" label="11d Ordner öffnen" />
+
+      <tc:button image="fa-print" label="12a Drucken" />
+      <tc:button image="fa-th" label="12b Berechnen" />
+      <tc:button image="fa-eur" label="12c Umrechnungskurs" />
+      <tc:button image="fa-check" label="12d Prüfen" />
+    </tc:segmentLayout>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-1.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-1.xhtml
new file mode 100644
index 0000000..17799f5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-1.xhtml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page" label="Layout">
+    <tc:segmentLayout medium="2;4;2;4" small="6;6">
+      <tc:label value="1st label"/>
+      <tc:in value="a aa aaa aaaa aaaaa" labelLayout="none"/>
+      <tc:in label="2nd label" value="b bb bbb bbbb bbbbb b bb bbb bbbb bbbbb b bb bbb bbbb bbb bbbb bbbbb "
+             labelLayout="segmentLeft"/>
+      <tc:textarea label="3rd label" value="c cc ccc cccc ccccc" labelLayout="segmentLeft"/>
+      <tc:textarea label="4th label" value="d dd ddd dddd ddddd" labelLayout="segmentLeft"/>
+    </tc:segmentLayout>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-2.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-2.xhtml
new file mode 100644
index 0000000..4b46792
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-2.xhtml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <!--
+  same as simple-1.xhtml, but here are two panels, which contains the controls.
+  -->
+
+  <tc:page id="page">
+    <tc:segmentLayout medium="2;4;2;4" small="6;6">
+      <tc:in label="1st label" value="a aa aaa aaaa aaaaa" labelLayout="segmentLeft"/>
+      <tc:in label="2nd label" value="b bb bbb bbbb bbbbb b bb bbb bbbb bbbbb b bb bbb bbbb bbb bbbb bbbbb "
+             labelLayout="segmentLeft"/>
+    </tc:segmentLayout>
+    <tc:segmentLayout medium="2;4;2;4" small="6;6">
+      <tc:textarea label="3rd label" value="c cc ccc cccc ccccc" labelLayout="segmentLeft"/>
+      <tc:textarea label="4th label" value="d dd ddd dddd ddddd" labelLayout="segmentLeft"/>
+    </tc:segmentLayout>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-3.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-3.xhtml
new file mode 100644
index 0000000..d02ef61
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/segmentLayout/simple-3.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+
+    <tc:segmentLayout medium="2;4;2;4" small="6;6">
+      <tc:in label="1st label" value="#{bootstrap.value}" labelLayout="segmentLeft"/>
+      <tc:in label="2nd label" value="b bb bbb bbbb bbbbb b bb bbb bbbb bbbbb b bb bbb bbbb bbb bbbb bbbbb "
+             labelLayout="segmentLeft"/>
+    </tc:segmentLayout>
+
+    <tc:segmentLayout medium="2;4;2;4" small="6;6">
+      <tc:textarea label="3rd label" value="c cc ccc cccc ccccc" labelLayout="segmentLeft"/>
+      <tc:textarea label="4th label" value="d dd ddd dddd ddddd" labelLayout="segmentLeft"/>
+    </tc:segmentLayout>
+
+    <tc:segmentLayout medium="1;1;1" extraSmall="4;4;4">
+      <tc:button id="cancel" label="Cancel" action="#{bootstrap.reset}"/>
+      <tc:button id="save" label="Save" action="#{bootstrap.save}"/>
+      <tc:button id="delete" label="Delete" action="#{bootstrap.delete}"/>
+    </tc:segmentLayout>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/checkbox-bug-tobago-1041.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/checkbox-bug-tobago-1041.xhtml
new file mode 100644
index 0000000..6334a75
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/checkbox-bug-tobago-1041.xhtml
@@ -0,0 +1,181 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="1000px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout
+          rows="0px;auto;auto"
+          margin="30px"/>
+    </f:facet>
+
+    <!-- XXX hack -->
+    <tc:out value="#{tobago1041.hackFacesMessages}"/>
+
+    <tc:box label="test labels with literals">
+
+      <f:facet name="layout">
+        <tc:gridLayout columns="2*;*;2*"
+                       rows="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+      </f:facet>
+
+      <tc:label value="tag"/>
+      <tc:label value="rendered as"/>
+      <tc:label value="label used for messages"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox label='A' itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox id="literal-tc-both" label="A" itemLabel="B"/>
+      <tc:messages for="page:literal-tc-both"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox id="literal-tc-item" itemLabel="B"/>
+      <tc:messages for="page:literal-tc-item"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox label='A' /> (compatibility)"/>
+      <tc:selectBooleanCheckbox id="literal-tc-label" label="A"/>
+      <tc:messages for="page:literal-tc-label"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox/>"/>
+      <tc:selectBooleanCheckbox id="literal-tc-no"/>
+      <tc:messages for="page:literal-tc-no"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox label='A' itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox fieldId="literal-tx-both" label="A" itemLabel="B"/>
+      <tc:messages for="page:literal-tx-both"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox fieldId="literal-tx-item" itemLabel="B"/>
+      <tc:messages for="page:literal-tx-item"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox label='A' />"/>
+      <tc:selectBooleanCheckbox fieldId="literal-tx-label" label="A"/>
+      <tc:messages for="page:literal-tx-label"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox/>"/>
+      <tc:selectBooleanCheckbox fieldId="literal-tx-no"/>
+      <tc:messages for="page:literal-tx-no"/>
+    </tc:box>
+
+    <tc:box label="same with value expressions">
+
+      <f:facet name="layout">
+      <tc:gridLayout columns="2*;*;2*"
+                     rows="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+      </f:facet>
+
+      <tc:label value="tag"/>
+      <tc:label value="rendered as"/>
+      <tc:label value="label used for messages"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox label='A' itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox id="expression-tc-both" label="A" itemLabel="B"/>
+      <tc:messages for="page:expression-tc-both"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox id="expression-tc-item" itemLabel="B"/>
+      <tc:messages for="page:expression-tc-item"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox label='A' /> (compatibility)"/>
+      <tc:selectBooleanCheckbox id="expression-tc-label" label="A"/>
+      <tc:messages for="page:expression-tc-label"/>
+
+      <tc:out value="&lt;tc:selectBooleanCheckbox/>"/>
+      <tc:selectBooleanCheckbox id="expression-tc-no"/>
+      <tc:messages for="page:expression-tc-no"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox label='A' itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox fieldId="expression-tx-both" label="A" itemLabel="B"/>
+      <tc:messages for="page:expression-tx-both"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox itemLabel='B' />"/>
+      <tc:selectBooleanCheckbox fieldId="expression-tx-item" itemLabel="B"/>
+      <tc:messages for="page:expression-tx-item"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox label='A' />"/>
+      <tc:selectBooleanCheckbox fieldId="expression-tx-label" label="A"/>
+      <tc:messages for="page:expression-tx-label"/>
+
+      <tc:out value="&lt;tx:selectBooleanCheckbox/>"/>
+      <tc:selectBooleanCheckbox fieldId="expression-tx-no"/>
+      <tc:messages for="page:expression-tx-no"/>
+    </tc:box>
+
+    <tc:script onload="check();">
+      function check() {
+        checkLabel("page:literal-tc-both", "B");
+        checkLabel("page:literal-tc-item", "B");
+        checkLabel("page:literal-tc-label", "A");
+        checkLabel("page:literal-tc-no", null);
+        checkLabel("page:literal-tx-both", "B");
+        checkLabel("page:literal-tx-item", "B");
+        checkLabel("page:literal-tx-label", "");
+        checkLabel("page:literal-tx-no", "");
+
+        checkMessage("page:literal-tc-both", "A");
+        checkMessage("page:literal-tc-item", "-");
+        checkMessage("page:literal-tc-label", "A");
+        checkMessage("page:literal-tc-no", "-");
+        checkMessage("page:literal-tx-both", "A");
+        checkMessage("page:literal-tx-item", "-");
+        checkMessage("page:literal-tx-label", "A");
+        checkMessage("page:literal-tx-no", "-");
+
+        checkLabel("page:expression-tc-both", "B");
+        checkLabel("page:expression-tc-item", "B");
+        checkLabel("page:expression-tc-label", "A");
+        checkLabel("page:expression-tc-no", null);
+        checkLabel("page:expression-tx-both", "B");
+        checkLabel("page:expression-tx-item", "B");
+        checkLabel("page:expression-tx-label", "");
+        checkLabel("page:expression-tx-no", "");
+
+        checkMessage("page:expression-tc-both", "A");
+        checkMessage("page:expression-tc-item", "-");
+        checkMessage("page:expression-tc-label", "A");
+        checkMessage("page:expression-tc-no", "-");
+        checkMessage("page:expression-tx-both", "A");
+        checkMessage("page:expression-tx-item", "-");
+        checkMessage("page:expression-tx-label", "A");
+        checkMessage("page:expression-tx-no", "-");
+      }
+
+      function checkLabel(id, estimate) {
+        var label = jQuery(Tobago.Utils.escapeClientId(id)).next("label");
+        if (estimate != label.html()) {
+          LOG.error("Wrong label (" + id + "). Estimate='" + estimate + "' found='" + label.html() + "'.");
+//        } else {
+//          LOG.info("Correct label (" + id + "). Estimate='" + estimate + "' found='" + label.html() + "'.");
+        }
+      }
+
+      function checkMessage(id, estimate) {
+        var label = jQuery(".tobago-messages label[for='" + id + "']");
+        if (estimate != label.html()) {
+          LOG.error("Wrong message (" + id + "). Estimate='" + estimate + "' found='" + label.html() + "'.");
+//        } else {
+//          LOG.info("Correct label (" + id + "). Estimate='" + estimate + "' found='" + label.html() + "'.");
+        }
+      }
+    </tc:script>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/selectBooleanCheckbox-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/selectBooleanCheckbox-layout.xhtml
new file mode 100644
index 0000000..eac2377
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/selectBooleanCheckbox-layout.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectBooleanCheckbox value="true" id="s1" label="A Value">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="25"/>
+      <tc:dataAttribute name="assert-width" value="200"/>
+      <tc:dataAttribute name="assert-height" value="19"/>
+    </tc:selectBooleanCheckbox>
+    <tc:selectBooleanCheckbox value="true" label="normal" fieldId="s2" itemLabel="A Value">
+      <tc:dataAttribute name="assert-left" value="330"/>
+      <tc:dataAttribute name="assert-top" value="25"/>
+      <tc:dataAttribute name="assert-width" value="200"/>
+      <tc:dataAttribute name="assert-height" value="19"/>
+    </tc:selectBooleanCheckbox>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/selectBooleanCheckbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/selectBooleanCheckbox.xhtml
new file mode 100644
index 0000000..2be64fe
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectBooleanCheckbox/selectBooleanCheckbox.xhtml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <!-- fixme: rows="20px" -->
+      <tc:gridLayout columns="*;2*;2*" rows="auto;20px" columnSpacing="30px"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="3"/>
+    </tc:messages>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+    <tc:label value="tx with item label"/>
+
+    <tc:selectBooleanCheckbox id="n1" value="true" label="normal"/>
+    <tc:selectBooleanCheckbox id="n2" value="true" label="normal"/>
+    <tc:selectBooleanCheckbox id="n3" value="true" label="normal" itemLabel="item label"/>
+
+    <tc:selectBooleanCheckbox id="r1" value="false" label="readonly" readonly="true"/>
+    <tc:selectBooleanCheckbox id="r2" value="false" label="readonly" readonly="true"/>
+    <tc:selectBooleanCheckbox id="r3" value="false" label="readonly" readonly="true" itemLabel="item label"/>
+
+    <tc:selectBooleanCheckbox id="d1" value="true" label="disabled" disabled="true"/>
+    <tc:selectBooleanCheckbox id="d2" value="true" label="disabled" disabled="true"/>
+    <tc:selectBooleanCheckbox id="d3" value="true" label="disabled" disabled="true" itemLabel="item label"/>
+
+    <tc:selectBooleanCheckbox id="t1" value="false" label="tip" tip="tip"/>
+    <tc:selectBooleanCheckbox id="t2" value="false" label="tip" tip="tip"/>
+    <tc:selectBooleanCheckbox id="t3" value="false" label="tip" tip="tip" itemLabel="item label"/>
+
+    <tc:selectBooleanCheckbox id="e1" value="true" label="escape &lt;hr/>"/>
+    <tc:selectBooleanCheckbox id="e2" value="true" label="escape &lt;hr/>"/>
+    <tc:selectBooleanCheckbox id="e3" value="true" label="escape &lt;hr/>" itemLabel="item label &lt;hr/>"/>
+
+    <tc:selectBooleanCheckbox id="i1" value="#{selectBooleanCheckboxBean.value0}" label="edit"/>
+    <tc:selectBooleanCheckbox id="i2" value="#{selectBooleanCheckboxBean.value1}" label="edit"/>
+    <tc:selectBooleanCheckbox id="i3" value="#{selectBooleanCheckboxBean.value2}" label="edit" itemLabel="item label"/>
+
+    <tc:selectBooleanCheckbox id="q1" label="required" required="true"/>
+    <tc:selectBooleanCheckbox id="q2" label="required" required="true"/>
+    <tc:selectBooleanCheckbox id="q3" label="required" required="true" itemLabel="item label"/>
+
+    <tc:selectBooleanCheckbox id="b1" value="#{selectBooleanCheckboxBean.required0}" label="required/edit"
+                              required="true"/>
+    <tc:selectBooleanCheckbox id="b2" value="#{selectBooleanCheckboxBean.required1}" label="required/edit"
+                              required="true"/>
+    <tc:selectBooleanCheckbox id="b3" value="#{selectBooleanCheckboxBean.required2}" label="required/edit"
+                              required="true" itemLabel="item label"/>
+
+    <tc:selectBooleanCheckbox id="x1"/>
+    <tc:selectBooleanCheckbox id="x2"/>
+    <tc:selectBooleanCheckbox id="x3"/>
+
+    <tc:button label="submit"/>
+
+    <tc:script file="script/tobago-assert.js">
+
+      function checkTcItemLabel(id, value) {
+        TobagoAssert.assertContent(
+            jQuery(Tobago.Utils.escapeClientId(id)).next('label'), value);
+      }
+
+      function checkTxItemLabelEmpty(id) {
+        TobagoAssert.assertContent(
+            jQuery(Tobago.Utils.escapeClientId(id)).children('div').children('label'), '');
+      }
+
+      function checkTxItemLabel(id, value) {
+        TobagoAssert.assertContent(
+            jQuery(Tobago.Utils.escapeClientId(id)).children('div').children('label'), value);
+      }
+
+    </tc:script>
+
+    <tc:script onload="checkTcItemLabel('page:n1', 'normal');"/>
+    <tc:script onload="checkTcItemLabel('page:r1', 'readonly');"/>
+    <tc:script onload="checkTcItemLabel('page:d1', 'disabled');"/>
+    <tc:script onload="checkTcItemLabel('page:t1', 'tip');"/>
+    <tc:script onload="checkTcItemLabel('page:e1', 'escape &amp;lt;hr/&amp;gt;');"/>
+    <tc:script onload="checkTcItemLabel('page:i1', 'edit');"/>
+    <tc:script onload="checkTcItemLabel('page:q1', 'required');"/>
+    <tc:script onload="checkTcItemLabel('page:b1', 'required/edit');"/>
+    <tc:script onload="checkTcItemLabel('page:x1', undefined);"/>
+
+    <!-- All tx tags without item label shouldn't have an item label rendered -->
+    <tc:script onload="checkTxItemLabelEmpty('page:n2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:r2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:d2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:t2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:e2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:i2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:q2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:b2');"/>
+    <tc:script onload="checkTxItemLabelEmpty('page:x2');"/>
+
+    <tc:script onload="checkTxItemLabel('page:n3', 'item label');"/>
+    <tc:script onload="checkTxItemLabel('page:r3', 'item label');"/>
+    <tc:script onload="checkTxItemLabel('page:d3', 'item label');"/>
+    <tc:script onload="checkTxItemLabel('page:t3', 'item label');"/>
+    <tc:script onload="checkTxItemLabel('page:e3', 'item label &amp;lt;hr/&amp;gt;');"/>
+    <tc:script onload="checkTxItemLabel('page:i3', 'item label');"/>
+    <tc:script onload="checkTxItemLabel('page:q3', 'item label');"/>
+    <tc:script onload="checkTxItemLabel('page:b3', 'item label');"/>
+    <tc:script onload="checkTxItemLabel('page:x3', '');"/>
+
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyCheckbox/selectManyCheckbox-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyCheckbox/selectManyCheckbox-layout.xhtml
new file mode 100644
index 0000000..cb090f3
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyCheckbox/selectManyCheckbox-layout.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectManyCheckbox id="s1">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox label="normal" fieldId="s2">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 200, 40);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 330, 25, 200, 40);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyCheckbox/selectManyCheckbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyCheckbox/selectManyCheckbox.xhtml
new file mode 100644
index 0000000..9d38712
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyCheckbox/selectManyCheckbox.xhtml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <!-- fixme: rows="20px" -->
+      <tc:gridLayout columns="*;2*" rows="auto;20px;auto;auto;auto;auto;auto;auto;auto" columnSpacing="30px"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:messages>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectManyCheckbox>
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox label="normal">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+
+    <tc:selectManyCheckbox readonly="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox readonly="true" label="readonly">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+
+    <tc:selectManyCheckbox disabled="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox disabled="true" label="disabled">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+
+    <tc:selectManyCheckbox tip="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox tip="tip" label="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+
+    <tc:selectManyCheckbox inline="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox inline="true" label="inline">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+
+    <tc:selectManyCheckbox required="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+    <tc:selectManyCheckbox required="true" label="required">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyCheckbox>
+
+
+    <tc:button label="submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox-layout.xhtml
new file mode 100644
index 0000000..110da90
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox-layout.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectManyListbox id="s1">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox label="normal" fieldId="s2">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 200, 75);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 330, 25, 200, 75);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox-value.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox-value.xhtml
new file mode 100644
index 0000000..0c53ca9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox-value.xhtml
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="630px" height="800px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="20px;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:messages>
+
+    <tc:out value="The value attribute of the component has different type in this example:"/>
+
+    <tc:label value="&lt;tx:selectManyListbox>"/>
+
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringList}" label="list of strings">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringArray}" label="array of strings">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringSet}" label="set of strings">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringCollection}" label="collection of strings">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+
+    <tc:label value="&lt;tx:selectManyListbox> width java.util.Currency as value"/>
+
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringList}" label="list of currencies">
+      <tc:selectItems value="#{selectManyListboxBean.currencyItems}"
+                      var="currency" itemValue="#{currency.currencyCode}" itemLabel="#{currency.displayName}"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringArray}" label="array of currencies">
+      <tc:selectItems value="#{selectManyListboxBean.currencyItems}"
+                      var="currency" itemValue="#{currency.currencyCode}" itemLabel="#{currency.displayName}"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringSet}" label="set of currencies">
+      <tc:selectItems value="#{selectManyListboxBean.currencyItems}"
+                      var="currency" itemValue="#{currency.currencyCode}" itemLabel="#{currency.displayName}"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox value="#{selectManyListboxBean.stringCollection}" label="collection of currencies">
+      <tc:selectItems value="#{selectManyListboxBean.currencyItems}"
+                      var="currency" itemValue="#{currency.currencyCode}" itemLabel="#{currency.displayName}"/>
+    </tc:selectManyListbox>
+
+    <tc:button label="submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox.xhtml
new file mode 100644
index 0000000..822e0fb
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyListbox/selectManyListbox.xhtml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="630px" height="600px"/>
+    <f:facet name="layout">
+      <!-- fixme: rows="20px" -->
+      <tc:gridLayout columns="*;2*" rows="auto;20px;auto;auto;auto;auto;auto;auto" columnSpacing="30px"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:messages>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectManyListbox>
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox label="normal">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+
+    <tc:selectManyListbox readonly="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox readonly="true" label="readonly">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+
+    <tc:selectManyListbox disabled="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox disabled="true" label="disabled">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+
+    <tc:selectManyListbox tip="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox tip="tip" label="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+
+    <tc:selectManyListbox required="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+    <tc:selectManyListbox required="true" label="required">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyListbox>
+
+    <tc:button label="submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-layout.xhtml
new file mode 100644
index 0000000..4b740d2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-layout.xhtml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="*;2*" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectManyShuttle id="s1">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle label="normal" fieldId="s2">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+<!-- TODO
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 200, 40);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 330, 25, 200, 40);"/>
+-->
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-value.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-value.selenium.html
new file mode 100644
index 0000000..6fef2a2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-value.selenium.html
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+  <link rel="selenium.base" href="http://localhost:8080/" />
+  <title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+  <thead>
+  <tr><td rowspan="1" colspan="3">New Test</td></tr>
+  </thead><tbody>
+<tr>
+  <td>open</td>
+  <td>/faces/test/selectManyShuttle/selectManyShuttle-value.xhtml</td>
+  <td></td>
+</tr>
+<tr>
+  <td>addSelection</td>
+  <td>id=page:shuttle::unselected</td>
+  <td>label=B</td>
+</tr>
+<tr>
+  <td>click</td>
+  <td>id=page:shuttle::add</td>
+  <td></td>
+</tr>
+<tr>
+  <td>addSelection</td>
+  <td>id=page:shuttle::unselected</td>
+  <td>label=E (disabled)</td>
+</tr>
+<tr>
+  <td>click</td>
+  <td>id=page:shuttle::add</td>
+  <td></td>
+</tr>
+<tr>
+  <td>addSelection</td>
+  <td>id=page:shuttle::unselected</td>
+  <td>label=Y</td>
+</tr>
+<tr>
+  <td>click</td>
+  <td>id=page:shuttle::add</td>
+  <td></td>
+</tr>
+<tr>
+  <td>clickAndWait</td>
+	<td>id=page:submit</td>
+  <td></td>
+</tr>
+<tr>
+  <td>verifyValue</td>
+	<td>id=page:valueOnServer</td>
+  <td>b,y</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-value.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-value.xhtml
new file mode 100644
index 0000000..6b63c73
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle-value.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="400px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*;auto;auto"/>
+    </f:facet>
+
+    <tc:messages/>
+
+    <tc:selectManyShuttle value="#{shuttle.value}" id="shuttle">
+      <tc:selectItem itemValue="a" itemLabel="A (disabled)" itemDisabled="true"/>
+      <tc:selectItem itemValue="b" itemLabel="B"/>
+      <tc:selectItem itemValue="c" itemLabel="C"/>
+      <tc:selectItem itemValue="d" itemLabel="D"/>
+      <tc:selectItem itemValue="e" itemLabel="E (disabled)" itemDisabled="true"/>
+      <tc:selectItem itemValue="f" itemLabel="F"/>
+      <tc:selectItem itemValue="g" itemLabel="G"/>
+      <tc:selectItem itemValue="h" itemLabel="H"/>
+      <tc:selectItem itemValue="i" itemLabel="I (disabled)" itemDisabled="true"/>
+      <tc:selectItem itemValue="j" itemLabel="J"/>
+      <tc:selectItem itemValue="k" itemLabel="K"/>
+      <tc:selectItem itemValue="l" itemLabel="L"/>
+      <tc:selectItem itemValue="m" itemLabel="M"/>
+      <tc:selectItem itemValue="n" itemLabel="N"/>
+      <tc:selectItem itemValue="o" itemLabel="O (disabled)" itemDisabled="true"/>
+      <tc:selectItem itemValue="p" itemLabel="P"/>
+      <tc:selectItem itemValue="q" itemLabel="Q"/>
+      <tc:selectItem itemValue="r" itemLabel="R"/>
+      <tc:selectItem itemValue="s" itemLabel="S"/>
+      <tc:selectItem itemValue="t" itemLabel="T"/>
+      <tc:selectItem itemValue="u" itemLabel="U (disabled)" itemDisabled="true"/>
+      <tc:selectItem itemValue="v" itemLabel="V"/>
+      <tc:selectItem itemValue="w" itemLabel="W"/>
+      <tc:selectItem itemValue="x" itemLabel="X"/>
+      <tc:selectItem itemValue="y" itemLabel="Y"/>
+      <tc:selectItem itemValue="z" itemLabel="Z"/>
+    </tc:selectManyShuttle>
+
+    <tc:button label="submit" id="submit"/>
+
+    <tc:in label="on server" value="#{shuttle.result}" readonly="true" fieldId="valueOnServer"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle.xhtml
new file mode 100644
index 0000000..65a4377
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectManyShuttle/selectManyShuttle.xhtml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <!-- fixme: rows="20px" -->
+      <tc:gridLayout columns="*;2*" rows="auto;20px;auto;auto;auto;auto;auto;auto" columnSpacing="30px"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:messages>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectManyShuttle>
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle label="normal">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+
+    <tc:selectManyShuttle readonly="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle readonly="true" label="readonly">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+
+    <tc:selectManyShuttle disabled="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle disabled="true" label="disabled">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+
+    <tc:selectManyShuttle tip="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle tip="tip" label="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+
+    <tc:selectManyShuttle required="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+    <tc:selectManyShuttle required="true" label="required">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectManyShuttle>
+
+
+    <tc:button label="submit"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneChoice/selectOneChoice-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneChoice/selectOneChoice-layout.xhtml
new file mode 100644
index 0000000..e482d50
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneChoice/selectOneChoice-layout.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectOneChoice value="a" id="s1">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice value="b" label="normal" fieldId="s2">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 200, 20);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 330, 25, 200, 20);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneChoice/selectOneChoice.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneChoice/selectOneChoice.xhtml
new file mode 100644
index 0000000..3a692db
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneChoice/selectOneChoice.xhtml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <!-- fixme: rows="20px" -->
+      <tc:gridLayout columns="*;2*" rows="auto;20px" columnSpacing="30px"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:messages>
+    
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+    
+    <tc:selectOneChoice value="a">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice value="b" label="normal">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+
+    <tc:selectOneChoice value="a" readonly="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice value="b" readonly="true" label="readonly">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+
+    <tc:selectOneChoice value="a" disabled="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice value="b" disabled="true" label="disabled">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+
+    <tc:selectOneChoice value="a" tip="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice value="b" tip="tip" label="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneChoice>
+
+    <tc:selectOneChoice required="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+      <tc:selectItem itemLabel="&lt;no value>"/>
+    </tc:selectOneChoice>
+    <tc:selectOneChoice required="true" label="required">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+      <tc:selectItem itemLabel="&lt;no value>"/>
+    </tc:selectOneChoice>
+    
+    <tc:button label="submit"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneListbox/selectOneListbox-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneListbox/selectOneListbox-layout.xhtml
new file mode 100644
index 0000000..54e2948
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneListbox/selectOneListbox-layout.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectOneListbox value="a" id="s1">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox value="b" label="normal" fieldId="s2">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 200, 75);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 330, 25, 200, 75);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneListbox/selectOneListbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneListbox/selectOneListbox.xhtml
new file mode 100644
index 0000000..4dc4ec6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneListbox/selectOneListbox.xhtml
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <!-- fixme: rows="20px" -->
+      <tc:gridLayout columns="*;2*" rows="auto;20px;*;*;*;*;*;auto" columnSpacing="30px"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:messages>
+    
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+    
+    <tc:selectOneListbox value="a">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox value="b" label="normal">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+
+    <tc:selectOneListbox value="a" readonly="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox value="b" readonly="true" label="readonly">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+
+    <tc:selectOneListbox value="a" disabled="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox value="b" disabled="true" label="disabled">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+
+    <tc:selectOneListbox value="a" tip="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox value="b" tip="tip" label="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+
+    <tc:selectOneListbox required="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+    <tc:selectOneListbox required="true" label="required">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneListbox>
+    
+    <tc:button label="submit"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneRadio/selectOneRadio-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneRadio/selectOneRadio-layout.xhtml
new file mode 100644
index 0000000..9d9f8db
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneRadio/selectOneRadio-layout.xhtml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:selectOneRadio value="a" id="s1">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+    <tc:selectOneRadio value="b" label="normal" fieldId="s2">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 200, 40);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 330, 25, 200, 40);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneRadio/selectOneRadio.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneRadio/selectOneRadio.xhtml
new file mode 100644
index 0000000..46d02e9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/selectOneRadio/selectOneRadio.xhtml
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <!-- fixme: rows="20px" -->
+      <tc:gridLayout columns="*;2*" rows="auto;20px;auto;auto;auto;auto;auto;auto;auto" columnSpacing="30px"/>
+    </f:facet>
+
+    <tc:messages>
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:messages>
+    
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+    
+    <tc:selectOneRadio value="a">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+    <tc:selectOneRadio value="b" label="normal">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+
+    <tc:selectOneRadio value="a" readonly="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+    <tc:selectOneRadio value="b" readonly="true" label="readonly">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+
+    <tc:selectOneRadio value="a" disabled="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+    <tc:selectOneRadio value="b" disabled="true" label="disabled">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+
+    <tc:selectOneRadio value="a" tip="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+    <tc:selectOneRadio value="b" tip="tip" label="tip">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+
+    <tc:selectOneRadio value="a" inline="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+    <tc:selectOneRadio value="b" inline="true" label="inline">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+
+    <tc:selectOneRadio required="true">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+    <tc:selectOneRadio required="true" label="required">
+      <tc:selectItem itemValue="a" itemLabel="A Value"/>
+      <tc:selectItem itemValue="b" itemLabel="An Alternative"/>
+    </tc:selectOneRadio>
+
+    
+    <tc:button label="submit"/>
+    
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-with-label-facet.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-with-label-facet.xhtml
new file mode 100644
index 0000000..3a2fe3b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-with-label-facet.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:separator id="sep-0">
+      <f:facet name="label">
+        <tc:label value="Label (Ög) is deprecated"/>
+      </f:facet>
+    </tc:separator>
+    <tc:panel/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sep-0', 0, 0, 600, 14);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-with-label.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-with-label.xhtml
new file mode 100644
index 0000000..dc6fb66
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-with-label.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:separator label="Label (Ög)" id="sep-0"/>
+    <tc:panel/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sep-0', 0, 0, 600, 14);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-without-label.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-without-label.xhtml
new file mode 100644
index 0000000..37f8453
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/separator/separator-without-label.xhtml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:separator id="sep-0"/>
+    <tc:panel/>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:sep-0', 0, 0, 600, 1);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-height-header-footer.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-height-header-footer.xhtml
new file mode 100644
index 0000000..8c9bdb8
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-height-header-footer.xhtml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px"/>
+
+    <tc:box>
+
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto;auto" rowSpacing="50px" margin="50px"/>
+      </f:facet>
+
+      <!--
+        haeder: false
+        footer: false
+       -->
+      <tc:sheet value="#{sheet.solarArray3}" id="sheet1" columns="*;*" var="luminary" rows="3"
+                showHeader="false">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+      <!--
+        haeder: true
+        footer: false
+       -->
+      <tc:sheet value="#{sheet.solarArray3}" id="sheet2" columns="*;*" var="luminary" rows="3"
+                showHeader="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+      <!--
+        haeder: false
+        footer: true
+       -->
+      <tc:sheet value="#{sheet.solarArray3}" id="sheet3" columns="*;*" var="luminary" rows="3"
+                showHeader="false" showPagingAlways="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+      <!--
+        haeder: true
+        footer: true
+       -->
+      <tc:sheet value="#{sheet.solarArray3}" id="sheet4" columns="*;*" var="luminary" rows="3"
+                showHeader="true" showPagingAlways="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+    </tc:box>
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script>
+      jQuery(document).ready(function () {
+        jQuery("td>span").css("background-color", "white");
+        jQuery("td:odd").css("background-color", "#ffbbff");
+        jQuery("td:even").css("background-color", "#bbffbb");
+        jQuery(".tobago-sheet-body").css("border-color", "Black");
+      });
+    </tc:script>
+
+    <!--
+    left: 56 = 0 + 6 (box) + 50 (margin)
+    top: 76 = 0 + 26 + 50
+    width: 487 = 600 - 13 (box) - 2*50 margin
+    height: 63 = (3 * (20 (line-height) + 1 (line-distance)) - 1) + 1 (border)
+    -->
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet1', 56, 76, 487, 63);"/>
+
+    <!--
+    height of sheet1 + 21
+    -->
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet2', 56, 189, 487, 84);"/>
+
+    <!--
+    height of sheet1 + 16
+    -->
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet3', 56, 323, 487, 79);"/>
+
+    <!--
+    height of sheet1 + 16 + 21
+    -->
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet4', 56, 452, 487, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-height-rows.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-height-rows.xhtml
new file mode 100644
index 0000000..5b9d00a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-height-rows.xhtml
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px"/>
+
+    <tc:box>
+
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;auto;auto;100px" rowSpacing="50px" margin="50px"/>
+      </f:facet>
+
+      <!-- fixed rows = 3 - show exactly 3 rows, but have more -->
+      <tc:sheet value="#{sheet.solarArray}" id="sheet1" columns="*;*" var="luminary" rows="3"
+                showHeader="true" showPagingAlways="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+      <!-- rows = undefined (default 0), data model has 3 => show all = 3 -->
+      <tc:sheet value="#{sheet.solarArray3}" id="sheet2" columns="*;*" var="luminary"
+                showHeader="true" showPagingAlways="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+      <!-- data-model has undefined rowCount, rows=3 -->
+      <tc:sheet value="#{sheet.undefined}" id="sheet3" columns="*;*" var="luminary" rows="3"
+                showHeader="true" showPagingAlways="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+      <!-- data-model has undefined rowCount, rows = undefined -->
+      <tc:sheet value="#{sheet.undefined}" id="sheet4" columns="*;*" var="luminary"
+                showHeader="true" showPagingAlways="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+    </tc:box>
+    <tc:script file="script/tobago-assert.js"/>
+
+    <!--
+    left: 56 = 0 + 6 (box) + 50 (margin)
+    top: 76 = 0 + 26 + 50
+    width: 487 = 600 - 13 (box) - 2*50 margin
+    height: 100 = (3 * (20 (line-height) + 1 (line-distance)) - 1) + 1 (border) + 16 + 21
+    -->
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet1', 56, 76, 487, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet2', 56, 226, 487, 100);"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet3', 56, 376, 487, 100);"/>
+
+    <!--
+     height: sheet1 + 7 * (20 + 1)
+    -->
+    <tc:script onload="TobagoAssert.assertLayout('page:sheet4', 56, 526, 487, 100);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-width.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-width.xhtml
new file mode 100644
index 0000000..9595c03
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-auto-width.xhtml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint />
+
+    <tc:box label="NOT IMPLEMENTED (TODO)">
+
+      <f:facet name="layout">
+        <tc:gridLayout columns="auto" rows="auto"/>
+      </f:facet>
+
+      <tc:sheet value="#{sheet.solarArray}" id="sheet1" columns="*;*" var="luminary" rows="3"
+                showHeader="true" showPagingAlways="true">
+        <tc:column label="Name" id="name" sortable="true">
+          <tc:out value="#{luminary.name}"/>
+        </tc:column>
+        <tc:column label="Orbit Of" id="orbit">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+
+        <!-- fixme: implement it and set the value 500 to the correct value -->
+        <tc:dataAttribute name="assert-width" value="500"/>
+
+      </tc:sheet>
+
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-bug-tobago-1090.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-bug-tobago-1090.selenium.html
new file mode 100644
index 0000000..b02a2b2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-bug-tobago-1090.selenium.html
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/sheet/sheet-bug-tobago-1090.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet:2:name</td>
+	<td></td>
+</tr>
+<tr>
+	<td>assertValue</td>
+	<td>page:sheet::selected</td>
+	<td>,2,</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet::pagingPages::pagingArrows::Next</td><!-- XXX link id was changed in Tobago 3.0 -->
+	<td></td>
+</tr>
+<tr>
+	<td>assertValue</td>
+	<td>page:sheet::selected</td>
+	<td>,2,</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet:6:name</td>
+	<td></td>
+</tr>
+<tr>
+	<td>assertValue</td>
+	<td>page:sheet::selected</td>
+	<td>,6,</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet::pagingPages::pagingArrows::Prev</td>
+	<td></td>
+</tr>
+<tr>
+	<td>assertValue</td>
+	<td>page:sheet::selected</td>
+	<td>,6,</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet::pagingPages::pagingArrows::Next</td>
+	<td></td>
+</tr>
+<tr>
+	<td>assertValue</td>
+	<td>page:sheet::selected</td>
+	<td>,6,</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-bug-tobago-1090.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-bug-tobago-1090.xhtml
new file mode 100644
index 0000000..61edfcc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-bug-tobago-1090.xhtml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page width="800px" height="400px" id="page">
+
+    <tc:box label="TOBAGO-1090">
+      <f:facet name="layout">
+        <tc:gridLayout rows="auto;*;auto"/>
+      </f:facet>
+      <tc:link
+          label="Bug-Tracking: TOBAGO-1090" link="https://issues.apache.org/jira/browse/TOBAGO-1090"/>
+      <tc:out escape="false" value="Single select in the sheet doesn't respect paging.
+            &lt;br/>Checklist:
+            &lt;ol>
+            &lt;li>Click on the 3rd row (Venus)&lt;/li>
+            &lt;li>Click on button for next page&lt;/li>
+            &lt;li>Click on the 2nd row (Saturn)&lt;/li>
+            &lt;li>Click on button for previous page&lt;/li>
+            &lt;li>Check: 3rd row (Venus) must not be selected&lt;/li>
+            &lt;li>Click on button for next page&lt;/li>
+            &lt;li>Check: 2nd row (Saturn) must be selected&lt;/li>
+            &lt;/ol>"/>
+
+      <tc:sheet value="#{sheet.solarArray}" id="sheet" columns="*;*" var="luminary" rows="5" selectable="single">
+        <tc:column label="Name" sortable="true">
+          <tc:out value="#{luminary.name}" id="name"/>
+        </tc:column>
+        <tc:column label="Orbit Of">
+          <tc:out value="#{luminary.orbit}"/>
+        </tc:column>
+      </tc:sheet>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-large.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-large.js
new file mode 100644
index 0000000..796121b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-large.js
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+TestSheet = {};
+
+TestSheet.init = function() {
+
+  jQuery("[data-clickrow]").click(function() {
+    var rowIndex = jQuery(this).data("clickrow");
+    var row = jQuery(".tobago-sheet-body tr").eq(rowIndex);
+    var status = jQuery(this).prev().find("input");
+    status.val("processing ...");
+    var start = new Date();
+    row.click();
+    var end = new Date();
+    status.val(end.getTime() - start.getTime() + " ms");
+  });
+};
+
+Tobago.registerListener(TestSheet.init, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-large.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-large.xhtml
new file mode 100644
index 0000000..ff5c317
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-large.xhtml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;auto"/>
+    </f:facet>
+
+    <tc:sheet value="#{sheet.localeList}" id="sheet" columns="auto;5*;5*;5*;*" var="entry" rows="1000">
+      <tc:columnSelector disabled="#{entry.disabled}"/>
+      <tc:column label="Locale" id="l" sortable="true">
+        <tc:out value="#{entry.locale}"/>
+      </tc:column>
+      <tc:column label="Display Locale" id="d" sortable="true">
+        <tc:out value="#{entry.displayLocale}"/>
+      </tc:column>
+      <tc:column label="Country" id="c" sortable="true">
+        <tc:out value="#{entry.country}"/>
+      </tc:column>
+      <tc:column label="Language" id="a" sortable="true">
+        <tc:out value="#{entry.language}"/>
+      </tc:column>
+    </tc:sheet>
+
+    <tc:box label="Performance test">
+      <f:facet name="layout">
+        <tc:gridLayout columns="2*;*"/>
+      </f:facet>
+      <tc:in readonly="true" label="Select 1st row"/>
+      <tc:button label="Run" omit="true">
+        <tc:dataAttribute name="clickrow" value="0"/>
+      </tc:button>
+      <tc:in readonly="true" label="Select 2nd row"/>
+      <tc:button label="Run" omit="true">
+        <tc:dataAttribute name="clickrow" value="1"/>
+      </tc:button>
+    </tc:box>
+
+    <tc:script file="test/sheet/sheet-large.js"/>
+    <tc:script file="script/tobago-assert.js"/>
+    <!--todo-->
+    <!--<tc:script onload="TobagoAssert.assertLayout('page:todo', 0, 0, 600, 14);"/>-->
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-multi-header.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-multi-header.xhtml
new file mode 100644
index 0000000..21f5dc1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-multi-header.xhtml
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="802px" height="230px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*;auto"/>
+    </f:facet>
+
+    <tc:script>
+
+      initMultiHeader = function() {
+        jQuery("td>span").css("background-color", "white");
+        jQuery("td:odd").css("background-color", "#ffbbff");
+        jQuery("td:even").css("background-color", "#bbffbb");
+
+        jQuery(".tobago-sheet-headerResize").css({
+              "background-color":"red",
+              "opacity":0.3
+            }
+        );
+      };
+
+<!--
+      Tobago.registerListener(initMultiHeader, Tobago.Phase.DOCUMENT_READY);
+      Tobago.registerListener(initMultiHeader, Tobago.Phase.AFTER_UPDATE);
+-->
+
+    </tc:script>
+
+    <tc:messages />
+
+    <tc:sheet value="#{sheet.solarArray}" id="sheet" columns="*;*;*;*" var="luminary" showRoot="true"
+        showRowRange="left" rows="5">
+
+      <f:facet name="header">
+        <tc:panel>
+          <tc:in value="Single 1"/>
+          <tc:out value="Group 2+3">
+            <tc:gridLayoutConstraint columnSpan="2"/>
+          </tc:out>
+          <tc:out value="Rows 4+4">
+            <tc:gridLayoutConstraint rowSpan="2"/>
+          </tc:out>
+          <tc:out value="Group 1+2">
+            <tc:gridLayoutConstraint columnSpan="2"/>
+          </tc:out>
+          <tc:selectOneChoice value="Single 3">
+            <tc:selectItem itemLabel="first" itemValue="Single 3"/>
+            <tc:selectItem itemLabel="second"/>
+            <tc:selectItem itemLabel="third"/>
+          </tc:selectOneChoice>
+        </tc:panel>
+      </f:facet>
+
+      <tc:column label="Name" id="name">
+        <tc:in value="#{luminary.name}"/>
+      </tc:column>
+
+      <tc:column label="Discoverer" id="discoverer" sortable="true">
+        <tc:out value="#{luminary.discoverer}"/>
+      </tc:column>
+
+      <tc:column label="Discover Year" id="discoverYear" sortable="true">
+        <tc:out value="#{luminary.discoverYear}"/>
+      </tc:column>
+
+      <tc:column label="Orbit Of" id="orbit" sortable="true">
+        <tc:out value="#{luminary.orbit}"/>
+      </tc:column>
+
+    </tc:sheet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto"/>
+      </f:facet>
+
+      <tc:panel/>
+      <tc:button label="Submit" id="submit"/>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-1.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-1.selenium.html
new file mode 100644
index 0000000..2568230
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-1.selenium.html
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/sheet/sheet-paging-1.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>css=.tobago-sheet-footer</td>
+	<td>Zeile 1 von 88123456789...Seite 1 von 88</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-1.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-1.xhtml
new file mode 100644
index 0000000..5e875da
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-1.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:sheet value="#{sheet.solarArray}" id="s3" columns="*;*" var="luminary" rows="1">
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{luminary.name}"/>
+      </tc:column>
+      <tc:column label="Orbit Of" id="orbit">
+        <tc:out value="#{luminary.orbit}"/>
+      </tc:column>
+    </tc:sheet>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-11.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-11.selenium.html
new file mode 100644
index 0000000..18eb158
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-11.selenium.html
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/sheet/sheet-paging-11.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>css=.tobago-sheet-footer</td>
+	<td>Zeilen 1 bis 11 von 8812345678Seite 1 von 8</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-11.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-11.xhtml
new file mode 100644
index 0000000..c86330a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-11.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="100px"/>
+    </f:facet>
+
+    <tc:sheet value="#{sheet.solarArray}" id="s2" columns="*;*" var="luminary" rows="11">
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{luminary.name}"/>
+      </tc:column>
+      <tc:column label="Orbit Of" id="orbit">
+        <tc:out value="#{luminary.orbit}"/>
+      </tc:column>
+    </tc:sheet>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-20.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-20.selenium.html
new file mode 100644
index 0000000..f594701
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-20.selenium.html
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/sheet/sheet-paging-20.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>css=.tobago-sheet-footer</td>
+	<td>Zeilen 1 bis 20 von 8812345Seite 1 von 5</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-20.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-20.xhtml
new file mode 100644
index 0000000..7444fc5
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-paging-20.xhtml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:sheet value="#{sheet.solarArray}" id="s1" columns="*;*" var="luminary" rows="20">
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{luminary.name}"/>
+      </tc:column>
+      <tc:column label="Orbit Of" id="orbit">
+        <tc:out value="#{luminary.orbit}"/>
+      </tc:column>
+    </tc:sheet>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-reload.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-reload.js
new file mode 100644
index 0000000..ee24e53
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-reload.js
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+TestSheetReload = {};
+
+TestSheetReload.init = function() {
+
+  setTimeout(function() {
+    var value = jQuery(".tobago-sheet-body td").eq(1).find("span").html();
+    if (value != "0") {
+      console.error("expect '0' not '" + value + "'");
+    }
+  }, 3000);
+
+  setTimeout(function() {
+    var value = jQuery(".tobago-sheet-body td").eq(1).find("span").html();
+    if (value != "2") {
+      console.error("expect '2' not '" + value + "'");
+    }
+  }, 5000);
+
+};
+
+Tobago.registerListener(TestSheetReload.init, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-reload.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-reload.xhtml
new file mode 100644
index 0000000..99785b6
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-reload.xhtml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="40px;auto;auto;*"/>
+    </f:facet>
+
+    <tc:out value="Starting by 0 every 2 seconds the page will be reloaded. The counter on the server will
+    be incremented every reload, but odd values will send a 304 (not modified) to the client, so that
+    the sheet must not be updated."/>
+    <tc:out value="After 3 seconds there must only a 304 (not modified) reload, so we expect 0 as value."/>
+    <tc:out value="After 5 seconds there must be a normal reload, so we expect 2 as value."/>
+
+    <tc:sheet value="#{sheet.solarArray}" id="sheet" columns="*;*" var="luminary" rows="5">
+
+      <f:facet name="reload">
+        <tc:reload frequency="2000" update="#{reload.onlyEven}" />
+      </f:facet>
+
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{luminary.name}"/>
+      </tc:column>
+      <tc:column label="Reload" id="reload">
+        <tc:out value="#{reload.counter}"/>
+      </tc:column>
+    </tc:sheet>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script file="test/sheet/sheet-reload.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-selector.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-selector.selenium.html
new file mode 100644
index 0000000..1bf09d7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-selector.selenium.html
@@ -0,0 +1,354 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/tc/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/sheet/sheet-selector.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>css=img</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>link=Alles markieren</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_0</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_1</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_9</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_10</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_19</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[1]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd tobago-sheet-row-markup-selected</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[2]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[10]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[11]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd tobago-sheet-row-markup-selected</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[20]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even tobago-sheet-row-markup-selected</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>css=img</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>link=Markierungen löschen</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_0</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_1</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_9</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_10</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_19</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[1]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[2]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[10]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[11]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[20]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet_data_row_selector_0</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet_data_row_selector_1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet_data_row_selector_10</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_0</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_1</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_9</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_10</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_19</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[1]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd tobago-sheet-row-markup-selected</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[2]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[10]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[11]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd tobago-sheet-row-markup-selected</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[20]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>css=img</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>link=Markierung umkehren</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_0</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_1</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_9</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_10</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_19</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[1]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[2]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[10]@class</td>
+    <td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[11]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[20]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even tobago-sheet-row-markup-selected</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet:ToPage::link_2</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForAttribute</td>
+	<td>//div[@class='tobago-sheet']@data-tobago-first</td>
+	<td>20</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:sheet:ToPage::link_1</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForAttribute</td>
+	<td>//div[@class='tobago-sheet']@data-tobago-first</td>
+	<td>0</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_0</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_1</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_9</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_10</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:sheet_data_row_selector_19</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[1]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[2]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[10]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[11]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-odd</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//table[@class='tobago-sheet-bodyTable']/tbody/tr[20]@class</td>
+	<td>tobago-sheet-row tobago-sheet-row-markup-even tobago-sheet-row-markup-selected</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-selector.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-selector.xhtml
new file mode 100644
index 0000000..6455ade
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-selector.xhtml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core"
+    xmlns="http://www.w3.org/1999/xhtml">
+
+  <tc:page id="page">
+    <f:facet name="layout">
+      <tc:gridLayout rows="160px;auto" columns="600px"/>
+    </f:facet>
+
+    <tc:flowLayout>
+
+      <ul>
+        <li>
+          <tc:out value="Selection in a sheet."/>
+        </li>
+        <li>
+          <tc:out value="Planets aren't selectable."/>
+        </li>
+      </ul>
+
+      <ol>
+        <li>
+          <tc:out value="Select all"/>
+        </li>
+        <li>
+          <tc:out value="Unselect all"/>
+        </li>
+        <li>
+          <tc:out value="Select 1st, 2nd (disabled) and 11th row"/>
+        </li>
+        <li>
+          <tc:out value="Toggle all"/>
+        </li>
+        <li>
+          <tc:out value="Go to the 2nd page"/>
+        </li>
+        <li>
+          <tc:out value="Go back to the 1st page"/>
+        </li>
+      </ol>
+
+    </tc:flowLayout>
+
+    <tc:sheet value="#{sheet.solarArray}" id="sheet" columns="auto;*;*" var="luminary" rows="20">
+
+      <tc:columnSelector disabled="#{luminary.orbit == 'Sun'}"/>
+
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{luminary.name}"/>
+      </tc:column>
+
+      <tc:column label="Orbit Of" id="orbit">
+        <tc:out value="#{luminary.orbit}"/>
+      </tc:column>
+    </tc:sheet>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-simple.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-simple.js
new file mode 100644
index 0000000..d11c48f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-simple.js
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function test_colorize() {
+  jQuery("td>span,th>span").css("background-color", "white");
+  jQuery("td:odd").css("background-color", "#ffbbff");
+  jQuery("td:even").css("background-color", "#bbffbb");
+  jQuery("th:odd").css("background-color", "#dd99dd");
+  jQuery("th:even").css("background-color", "#99dd99");
+}
+
+Tobago.registerListener(test_colorize, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(test_colorize, Tobago.Phase.AFTER_UPDATE);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-simple.xhtml
new file mode 100644
index 0000000..18bb9c2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-simple.xhtml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:sheet value="#{sheet.solarArray}" id="sheet" columns="*;*" var="luminary" rows="5">
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{luminary.name}"/>
+      </tc:column>
+      <tc:column label="Orbit Of" id="orbit">
+        <tc:out value="#{luminary.orbit}"/>
+      </tc:column>
+    </tc:sheet>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <!--todo-->
+    <!--<tc:script onload="TobagoAssert.assertLayout('page:todo', 0, 0, 600, 14);"/>-->
+
+    <tc:script file="test/sheet/sheet-simple.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-sort.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-sort.selenium.html
new file mode 100644
index 0000000..13d6204
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-sort.selenium.html
@@ -0,0 +1,219 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/sheet/sheet-sort.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[1]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>A</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[1]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>Z</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[2]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>Z</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[2]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>Y</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[3]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>Y</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[3]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>X</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[4]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>X</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[4]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>W</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[5]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>W</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[5]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>V</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[6]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>V</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//table[@class='tobago-sheet-headerTable']/tbody/tr/td[6]/div/span</td>
+	<td></td>
+</tr>
+<tr>
+	<td>waitForElementNotPresent</td>
+	<td>css=.tobago-page-overlay</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyText</td>
+	<td>id=page:sheet:0:out</td>
+	<td>U</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-sort.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-sort.xhtml
new file mode 100644
index 0000000..fa1a00b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-sort.xhtml
@@ -0,0 +1,58 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:sheet value="#{sort.list}" id="sheet" columns="*;*;*;*;*;*" var="entry">
+      <tc:column label="tc:out" id="first" sortable="true">
+        <tc:out value="#{entry.first}" id="out"/>
+      </tc:column>
+      <tc:column label="tc:in" id="second" sortable="true">
+        <tc:in value="#{entry.second}" id="in" readonly="true"/>
+      </tc:column>
+      <tc:column label="tc:link" id="third" sortable="true">
+        <tc:link label="#{entry.third}"  id="link"/>
+      </tc:column>
+      <tc:column label="tc:button" id="fourth" sortable="true">
+        <tc:button label="#{entry.fourth}" id="button"/>
+      </tc:column>
+      <tc:column label="tc:date" id="fifth" sortable="true">
+        <tc:date value="#{entry.fifth}" id="date">
+          <f:convertDateTime timeZone="UTC" pattern="dd. MMM yyyy"/>
+        </tc:date>
+      </tc:column>
+      <tc:column label="tc:link -> tc:out" id="sixth" sortable="true">
+        <tc:link id="link2">
+          <tc:out value="#{entry.sixth}" id="out2"/>
+        </tc:link>
+      </tc:column>
+    </tc:sheet>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertContent('page:sheet:0:out', 'A');"/>
+    <tc:script onload="TobagoAssert.assertContent('page:sheet:1:out', 'B');"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-tree.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-tree.xhtml
new file mode 100644
index 0000000..921eca1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-tree.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="900px" height="500px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;auto"/>
+    </f:facet>
+
+    <tc:sheet value="#{tree.tree}" id="sheet" columns="*;*" var="row" showRoot="true" showRootJunction="true">
+
+      <tc:columnNode label="Tree" id="tree">
+        <tc:treeIndent/>
+        <tc:treeLabel value="#{row.userObject.name}"/>
+      </tc:columnNode>
+
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{row.userObject.name}"/>
+      </tc:column>
+
+      <tc:column label="Orbit Of" id="orbit">
+        <tc:out value="Tip: #{row.userObject.tip}"/>
+      </tc:column>
+
+    </tc:sheet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto"/>
+      </f:facet>
+
+      <tc:panel/>
+      <tc:button label="Submit" id="submit"/>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-unknown-row-count.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-unknown-row-count.xhtml
new file mode 100644
index 0000000..52112f4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-unknown-row-count.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="600px"/>
+    </f:facet>
+
+    <tc:sheet value="#{sheet.undefined}" id="sheet" columns="*;*" var="luminary" rows="20">
+      <tc:column label="Name" id="name" sortable="true">
+        <tc:out value="#{luminary.name}"/>
+      </tc:column>
+      <tc:column label="Orbit Of" id="orbit">
+        <tc:out value="#{luminary.orbit}"/>
+      </tc:column>
+    </tc:sheet>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-without-columns-definition.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-without-columns-definition.xhtml
new file mode 100644
index 0000000..04e4154
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/sheet/sheet-without-columns-definition.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+
+    <tc:sheet var="luminary">
+      <tc:column label="Name">
+      </tc:column>
+      <tc:column label="Orbit Of">
+      </tc:column>
+    </tc:sheet>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/suggest/tc-in-suggest.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/suggest/tc-in-suggest.xhtml
new file mode 100644
index 0000000..c51c63c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/suggest/tc-in-suggest.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+        xmlns:tc="http://myfaces.apache.org/tobago/component"
+        xmlns:ui="http://java.sun.com/jsf/facelets"
+        xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:in value="some value" required="true" tabIndex="1"
+           tip="test" suggestMethod="#{inputSuggest.inputSuggestItems}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/suggest/tx-in-suggest.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/suggest/tx-in-suggest.xhtml
new file mode 100644
index 0000000..dab6f68
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/suggest/tx-in-suggest.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+   
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <f:facet name="layout">
+      <tc:gridLayout/>
+    </f:facet>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:in value="some value" required="true" label="Suggest"
+           tip="test" suggestMethod="#{inputSuggest.inputSuggestItems}"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/client.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/client.xhtml
new file mode 100644
index 0000000..6f151e7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/client.xhtml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:h="http://java.sun.com/jsf/html"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:box label="la">
+
+      <tc:tabGroup switchType="client">
+      <tc:gridLayoutConstraint height="350px"/>
+      <tc:tab label="Tab 0">
+        <tc:textarea readonly="true" value="#{reload.counter}"/>
+      </tc:tab>
+      <tc:tab label="Tab 1 (disabled)" disabled="true">
+        <tc:textarea value="Tab 1" />
+      </tc:tab>
+      <tc:tab label="Tab 2 (not rendered)" rendered="false">
+        <tc:textarea value="Tab 2" />
+      </tc:tab>
+      <tc:tab label="Tab 3 (error)" markup="error">
+        <tc:textarea value="Tab 3"/>
+      </tc:tab>
+<!--
+      <tc:tab label="Tab 4">
+        <tc:textarea value="Tab 4" />
+      </tc:tab>
+-->
+    </tc:tabGroup>
+      
+    </tc:box>
+
+    <tc:button onclick="jQuery('.tobago-tabGroup').hide()" label="hide"/>
+    <tc:button onclick="jQuery('.tobago-tabGroup').show()" label="show"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/selectedIndexWithoutSetter.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/selectedIndexWithoutSetter.xhtml
new file mode 100644
index 0000000..2c27592
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/selectedIndexWithoutSetter.xhtml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:h="http://java.sun.com/jsf/html"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page>
+
+    <tc:tabGroup selectedIndex="1" switchType="reloadPage">
+      <tc:tab label="0">
+        <tc:out value="0"/>
+      </tc:tab>
+      <tc:tab label="1">
+        <tc:out value="1"/>
+      </tc:tab>
+    </tc:tabGroup>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/simple.xhtml
new file mode 100644
index 0000000..e118a4f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/simple.xhtml
@@ -0,0 +1,102 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:h="http://java.sun.com/jsf/html"
+    xmlns:f="http://java.sun.com/jsf/core">
+  <tc:page id="p">
+    <tc:gridLayoutConstraint width="1000px" height="300px" paddingLeft="400px"/>
+
+    <tc:tabGroup id="t1" switchType="client" selectedIndex="6">
+      <tc:gridLayoutConstraint paddingTop="25px"/>
+      <tc:tab label="Tab 0">
+        <tc:textarea readonly="true" value="#{reload.counter}"/>
+      </tc:tab>
+      <tc:tab label="Tab 1">
+        <f:facet name="layout">
+          <tc:gridLayout columns="*;*" rows="*;*"/>
+        </f:facet>
+        <tc:textarea />
+        <tc:textarea />
+        <tc:textarea />
+      </tc:tab>
+      <tc:tab label="Tab 2">
+        <tc:textarea />
+      </tc:tab>
+      <tc:tab label="Tab 3">
+        <tc:textarea />
+      </tc:tab>
+      <tc:tab label="Tab 4">
+        <tc:textarea />
+      </tc:tab>
+      <tc:tab label="Tab 5 abcdefghijklmnopqrstuvmxyz">
+        <tc:textarea />
+      </tc:tab>
+      <tc:tab label="Tab 6 abcdefghijklmnopqrstuvmxyz">
+        <tc:textarea />
+      </tc:tab>
+      <tc:tab label="Tab 7 abcdefghijklmnopqrstuvmxyz">
+        <tc:textarea />
+      </tc:tab>
+      <tc:tab label="Tab 8">
+        <tc:textarea />
+      </tc:tab>
+    </tc:tabGroup>
+
+    <f:subview id="s">
+      <tc:tabGroup id="t2" switchType="client" selectedIndex="7">
+        <tc:gridLayoutConstraint paddingTop="25px"/>
+        <tc:tab label="Tab 0">
+          <tc:textarea readonly="true" value="#{reload.counter}"/>
+        </tc:tab>
+        <tc:tab label="Tab 1">
+          <f:facet name="layout">
+            <tc:gridLayout columns="*;*" rows="*;*"/>
+          </f:facet>
+          <tc:textarea />
+          <tc:textarea />
+          <tc:textarea />
+        </tc:tab>
+        <tc:tab label="Tab 2">
+          <tc:textarea />
+        </tc:tab>
+        <tc:tab label="Tab 3">
+          <tc:textarea />
+        </tc:tab>
+        <tc:tab label="Tab 4">
+          <tc:textarea />
+        </tc:tab>
+        <tc:tab label="Tab 5 abcdefghijklmnopqrstuvmxyz">
+          <tc:textarea />
+        </tc:tab>
+        <tc:tab label="Tab 6 abcdefghijklmnopqrstuvmxyz">
+          <tc:textarea />
+        </tc:tab>
+        <tc:tab label="Tab 7 abcdefghijklmnopqrstuvmxyz">
+          <tc:textarea />
+        </tc:tab>
+        <tc:tab label="Tab 8">
+          <tc:textarea />
+        </tc:tab>
+      </tc:tabGroup>
+    </f:subview>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/tabGroup-layout-1164.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/tabGroup-layout-1164.xhtml
new file mode 100644
index 0000000..d10ba5a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tabGroup/tabGroup-layout-1164.xhtml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto" rows="auto"/>
+    </f:facet>
+
+    <tc:tabGroup>
+      <tc:tab label="Some Tab" id="tab">
+
+        <tc:label id="label" value="Some Component 400px x 400px">
+          <tc:gridLayoutConstraint preferredWidth="400px" preferredHeight="400px"/>
+        </tc:label>
+
+      </tc:tab>
+    </tc:tabGroup>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:tab:label', 6, 26, 400, 400);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/text/textarea-layout.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/text/textarea-layout.xhtml
new file mode 100644
index 0000000..9850e57
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/text/textarea-layout.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout columns="auto;auto" rows="auto;auto"/>
+    </f:facet>
+
+    <tc:label value="tc"/>
+    <tc:label value="tx"/>
+
+    <tc:textarea value="a" id="s1"/>
+    <tc:textarea value="b" label="normal" fieldId="s2"/>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+    <tc:script onload="TobagoAssert.assertLayout('page:s1', 0, 25, 200, 33);"/>
+    <tc:script onload="TobagoAssert.assertLayout('page:s2', 330, 25, 200, 33);"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/time/time.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/time/time.xhtml
new file mode 100644
index 0000000..615d06c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/time/time.xhtml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:box>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;*;*" rows="auto;auto;auto;auto;auto;auto;auto;auto;*;auto"/>
+      </f:facet>
+      <tc:gridLayoutConstraint width="900px" height="300px" marginLeft="10px" marginTop="10px" marginRight="10px"/>
+
+      <tc:date>
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date>
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only"/>
+
+      <tc:date readonly="true">
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date readonly="true">
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only" readonly="true"/>
+
+      <tc:date disabled="true">
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date disabled="true">
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only" disabled="true"/>
+
+      <tc:date markup="error">
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date markup="error">
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in value="for comparison only" markup="error"/>
+
+      <tc:date label="Label">
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date label="Label">
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="Label" value="for comparison only"/>
+
+      <tc:date label="Label" readonly="true">
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date label="Label" readonly="true">
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="Label" value="for comparison only" readonly="true"/>
+
+      <tc:date label="Label" disabled="true">
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date label="Label" disabled="true">
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="Label" value="for comparison only" disabled="true"/>
+
+      <tc:date label="Label" markup="error">
+        <f:convertDateTime type="time"/>
+      </tc:date>
+      <tc:date label="Label" markup="error">
+        <f:convertDateTime type="time" pattern="HH:mm:ss"/>
+      </tc:date>
+      <tc:in label="Label" value="for comparison only" markup="error"/>
+
+      <tc:panel/>
+      <tc:panel/>
+      <tc:panel/>
+
+      <tc:panel/>
+      <tc:panel/>
+      <tc:button label="Submit"/>
+
+    </tc:box>
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-command.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-command.xhtml
new file mode 100644
index 0000000..4d99469
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-command.xhtml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:out value="Tree with commands as nodes:"/>
+
+    <tc:tree id="tree" value="#{tree.tree}" var="node" showRoot="true" showRootJunction="true">
+      <tc:treeNode id="node">
+        <tc:treeIndent/>
+        <tc:treeCommand label="#{node.userObject.name}" action="#{node.userObject.action}"/>
+      </tc:treeNode>
+    </tc:tree>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-expanded.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-expanded.selenium.html
new file mode 100644
index 0000000..97e25c2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-expanded.selenium.html
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/tree/tree-expanded.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:reset</td>
+	<td></td>
+</tr>
+<!--node expanded-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:8:node']@class</td>
+	<td>tobago-treeNode tobago-treeNode-markup-expanded tobago-treeNode-markup-folder</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>//span[@id='page:tree:8:indent']/img[2]</td>
+	<td></td>
+</tr>
+<!--node expanded-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:8:node']@class</td>
+	<td>tobago-treeNode tobago-treeNode-markup-folder</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:tree:7:command</td>
+	<td></td>
+</tr>
+<!--node collapsed-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:8:node']@class</td>
+	<td>tobago-treeNode tobago-treeNode-markup-folder</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-expanded.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-expanded.xhtml
new file mode 100644
index 0000000..aed633a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-expanded.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;*"/>
+    </f:facet>
+
+    <tc:out value="Test expanded state of the tree nodes:"/>
+
+    <tc:button label="Reset" action="#{tree.openAll}" id="reset" immediate="true"/>
+
+    <tc:tree id="tree" value="#{tree.tree}" state="#{tree.state}" var="node" showRoot="true" showRootJunction="true">
+      <tc:treeNode id="node">
+        <tc:treeIndent id="indent"/>
+        <tc:treeCommand id="command" label="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:tree>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-infinite.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-infinite.xhtml
new file mode 100644
index 0000000..63cfc12
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-infinite.xhtml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="20px;*"/>
+    </f:facet>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:flowLayout/>
+      </f:facet>
+      <tc:out value="Infinite tree, showing the "/>
+      <tc:link label="Cantor set" link="http://en.wikipedia.org/wiki/Cantor_set"/>
+    </tc:panel>
+
+    <tc:tree id="tree" value="#{tree.infinite}" var="interval" showRoot="true" showRootJunction="true">
+      <tc:treeNode id="node">
+        <tc:treeIndent/>
+        <tc:treeLabel value="#{interval.label}"/>
+      </tc:treeNode>
+    </tc:tree>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-with-model.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-with-model.selenium.html
new file mode 100644
index 0000000..1c0b0b1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-with-model.selenium.html
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/tree/tree-marked-with-model.xhtml</td>
+	<td></td>
+</tr>
+<!--nothing marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:tree:1:command</td>
+	<td></td>
+</tr>
+<!--sports marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+	<td>tobago-treeNode tobago-treeNode-markup-marked</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:reload</td>
+	<td></td>
+</tr>
+<!--nothing marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+    <td>tobago-treeNode tobago-treeNode-markup-marked</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:tree:1:command</td>
+	<td></td>
+</tr>
+<!--sports marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+	<td>tobago-treeNode tobago-treeNode-markup-marked</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-with-model.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-with-model.xhtml
new file mode 100644
index 0000000..1253626
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-with-model.xhtml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;2*;auto"/>
+    </f:facet>
+
+    <tc:out escape="false" value="Tree with a marked node which should be stored tempotarily in the view.
+    &lt;br/>Checklist:
+    &lt;ol>
+    &lt;li>Check: No node should be marked&lt;/li>
+    &lt;li>Click on the Sports node&lt;/li>
+    &lt;li>Check: Only the Sports node should be marked&lt;/li>
+    &lt;li>Click on the reload button (you will get a new view)&lt;/li>
+    &lt;li>Check: &lt;b>Only the Sports node should be marked&lt;/b>&lt;/li>
+    &lt;li>Click on the Sports node&lt;/li>
+    &lt;li>Check: Only the Sports node should be marked&lt;/li>
+    &lt;/ol>"/>
+
+    <tc:tree id="tree" value="#{tree.tree}" var="node" showRoot="true" showRootJunction="true"
+        state="#{tree.state}">
+      <tc:treeNode id="node">
+        <tc:treeIndent id="indent"/>
+        <tc:treeCommand label="#{node.userObject.name}" id="command"/>
+      </tc:treeNode>
+    </tc:tree>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto;auto"/>
+      </f:facet>
+
+      <tc:panel/>
+      <tc:button id="reload" link="#{request.pathInfo}" label="Reload with fresh view"/>
+      <tc:button id="clear" action="#{tree.clearSelected}" label="Reload with fresh view"/>
+
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-without-model.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-without-model.selenium.html
new file mode 100644
index 0000000..8cbb5bc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-without-model.selenium.html
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/faces/test/button/link-attribute.xhtml" />
+<title>New Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr>
+	<td>open</td>
+	<td>/faces/test/tree/tree-marked-without-model.xhtml</td>
+	<td></td>
+</tr>
+<!--nothing marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:tree:1:command</td>
+	<td></td>
+</tr>
+<!--sports marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+	<td>tobago-treeNode tobago-treeNode-markup-marked</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:reload</td>
+	<td></td>
+</tr>
+<!--nothing marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:tree:1:command</td>
+	<td></td>
+</tr>
+<!--sports marked-->
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:1:node']@class</td>
+	<td>tobago-treeNode tobago-treeNode-markup-marked</td>
+</tr>
+<tr>
+	<td>assertAttribute</td>
+	<td>//div[@id='page:tree:2:node']@class</td>
+	<td>tobago-treeNode</td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-without-model.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-without-model.xhtml
new file mode 100644
index 0000000..8e9aed4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-marked-without-model.xhtml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="600px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="*;2*;auto"/>
+    </f:facet>
+
+    <tc:out escape="false" value="Tree with a marked node which should be stored tempotarily in the view.
+    &lt;br/>Checklist:
+    &lt;ol>
+    &lt;li>Check: No node should be marked&lt;/li>
+    &lt;li>Click on the Sports node&lt;/li>
+    &lt;li>Check: Only the Sports node should be marked&lt;/li>
+    &lt;li>Click on the reload button (you will get a new view)&lt;/li>
+    &lt;li>Check: &lt;b>No node should be marked&lt;/b>&lt;/li>
+    &lt;li>Click on the Sports node&lt;/li>
+    &lt;li>Check: Only the Sports node should be marked&lt;/li>
+    &lt;/ol>"/>
+
+    <tc:tree id="tree" value="#{tree.tree}" var="node" showRoot="true" showRootJunction="true">
+      <tc:treeNode id="node">
+        <tc:treeIndent id="indent"/>
+        <tc:treeCommand label="#{node.userObject.name}" id="command"/>
+      </tc:treeNode>
+    </tc:tree>
+
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto"/>
+      </f:facet>
+
+      <tc:panel/>
+      <tc:button id="reload" link="#{request.pathInfo}" label="Reload with fresh view"/>
+
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select-via-state.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select-via-state.xhtml
new file mode 100644
index 0000000..04fa9fa
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select-via-state.xhtml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="20px;*;auto;auto"/>
+    </f:facet>
+
+    <tc:out value="Stores the selection value in the state object of the tree."/>
+
+    <tc:tree id="tree" selectable="single" showRoot="true" showRootJunction="true" value="#{tree.tree}" var="node">
+      <tc:treeNode id="template">
+        <tc:treeIndent/>
+        <tc:treeSelect id="select" label="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:tree>
+
+    <tc:in fieldId="in" label="Required" required="true"/>
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto;auto"/>
+      </f:facet>
+      <tc:panel/>
+      <tc:button id="cancel" label="Cancel" immediate="true"/>
+      <tc:button id="submit" label="Submit"/>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select-via-value.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select-via-value.xhtml
new file mode 100644
index 0000000..59efc8d
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select-via-value.xhtml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="20px;*;auto;auto"/>
+    </f:facet>
+
+    <tc:out value="Stores the selection value in the value attribute of the tc:treeSelect component."/>
+
+    <tc:tree id="tree" selectable="single" showRoot="true" showRootJunction="true"
+             value="#{tree.tree}" state="#{tree.state}" var="node">
+      <tc:treeNode id="template">
+        <tc:treeIndent/>
+        <tc:treeSelect id="select" label="#{node.userObject.name}" value="#{node.userObject.selected}"/>
+      </tc:treeNode>
+    </tc:tree>
+
+    <tc:in fieldId="in" label="Required" required="true"/>
+    <tc:panel>
+      <f:facet name="layout">
+        <tc:gridLayout columns="*;auto;auto"/>
+      </f:facet>
+      <tc:panel/>
+      <tc:button id="cancel" label="Cancel" immediate="true"/>
+      <tc:button id="submit" label="Submit"/>
+    </tc:panel>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select.selenium.html b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select.selenium.html
new file mode 100644
index 0000000..5276df2
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-select.selenium.html
@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head profile="http://selenium-ide.openqa.org/profiles/test-case">
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<link rel="selenium.base" href="http://localhost:8080/" />
+<title>Test</title>
+</head>
+<body>
+<table cellpadding="1" cellspacing="1" border="1">
+<thead>
+<tr><td rowspan="1" colspan="3">New Test</td></tr>
+</thead><tbody>
+<tr >
+	<td>open</td>
+	<td>/faces/test/tree/tree-select.xhtml</td>
+	<td></td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:tree:5:select</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:tree:5:select</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:cancel</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:tree:5:select</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:tree:5:select</td>
+	<td></td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:submit</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:tree:5:select</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:cancel</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:tree:5:select</td>
+	<td>off</td>
+</tr>
+<tr>
+	<td>click</td>
+	<td>id=page:tree:5:select</td>
+	<td></td>
+</tr>
+<tr>
+	<td>type</td>
+	<td>id=page:in</td>
+	<td>some text</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:submit</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:tree:5:select</td>
+	<td>on</td>
+</tr>
+<tr>
+	<td>clickAndWait</td>
+	<td>id=page:cancel</td>
+	<td></td>
+</tr>
+<tr>
+	<td>verifyValue</td>
+	<td>id=page:tree:5:select</td>
+	<td>on</td>
+</tr>
+
+</tbody></table>
+</body>
+</html>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-show-attributes.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-show-attributes.xhtml
new file mode 100644
index 0000000..8fed775
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-show-attributes.xhtml
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+
+<f:view xmlns:tc="http://myfaces.apache.org/tobago/component"
+            xmlns:ui="http://java.sun.com/jsf/facelets"
+        xmlns:h="http://java.sun.com/jsf/html"
+        xmlns:f="http://java.sun.com/jsf/core"
+        xmlns:c="http://java.sun.com/jsp/jstl/core">
+
+  <tc:page label="Different show attributes" id="page">
+    <f:facet name="layout">
+      <tc:gridLayout columns="300px;200px;200px;200px;200px" rows="20px;20px;100px;100px;100px;100px;*"/>
+    </f:facet>
+
+    <tc:panel/>
+    <tc:label value="show junctions = true">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:label>
+    <tc:label value="show junctions = false">
+      <tc:gridLayoutConstraint columnSpan="2"/>
+    </tc:label>
+
+    <tc:panel/>
+    <tc:label value="show icons = true"/>
+    <tc:label value="show icons = false"/>
+    <tc:label value="show icons = true"/>
+    <tc:label value="show icons = false"/>
+
+    <tc:panel>
+      <tc:gridLayoutConstraint rowSpan="4"/>
+      <f:facet name="layout">
+        <tc:gridLayout columns="100px;195px" rows="100px;100px;100px;100px"/>
+      </f:facet>
+
+      <tc:label value="show root = true">
+        <tc:gridLayoutConstraint rowSpan="2"/>
+      </tc:label>
+      <tc:label value="show root junctions = true"/>
+      <tc:label value="show root junctions = false"/>
+
+      <tc:label value="show root = false">
+        <tc:gridLayoutConstraint rowSpan="2"/>
+      </tc:label>
+      <tc:label value="show root junctions = true"/>
+      <tc:label value="show root junctions = false"/>
+
+    </tc:panel>
+
+    <c:forEach items="#{trueAndFalseList}" var="showRoot">
+      <c:forEach items="#{trueAndFalseList}" var="showRootJunction">
+        <c:forEach items="#{trueAndFalseList}" var="showJunctions">
+          <c:forEach items="#{trueAndFalseList}" var="showIcons">
+
+            <tc:box
+                label="#{showRoot}, #{showRootJunction}, #{showJunctions}, #{showIcons}"
+                tip="show root = #{showRoot}, show root junctions = #{showRootJunction}, show junctions = #{showJunctions}, show icons = #{showIcons}">
+              <tc:tree showRoot="#{showRoot}" showRootJunction="#{showRootJunction}"
+                       value="#{tree.small}" var="node">
+                  <tc:treeNode id="template">
+                    <tc:treeIndent showJunctions="#{showJunctions}"/>
+                    <tc:treeIcon rendered="#{showIcons}"/>
+                    <tc:treeCommand label="#{node.userObject.name}" action="#{node.userObject.action}"/>
+                  </tc:treeNode>
+              </tc:tree>
+            </tc:box>
+
+          </c:forEach>
+        </c:forEach>
+      </c:forEach>
+    </c:forEach>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-simple-with-data.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-simple-with-data.xhtml
new file mode 100644
index 0000000..586d7b0
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-simple-with-data.xhtml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="300px" />
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:out value="Simple tree with deprecated &lt;tc:treeData> tag:"/>
+
+    <tc:tree id="tree" selectable="single" showRoot="true" showRootJunction="true">
+      <tc:treeData value="#{tree.tree}" var="node" id="data">
+        <tc:treeNode id="template">
+          <tc:treeIndent/>
+          <tc:treeLabel value="#{node.userObject.name}"/>
+        </tc:treeNode>
+      </tc:treeData>
+    </tc:tree>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-simple.xhtml
new file mode 100644
index 0000000..5ef9bc1
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/tree/tree-simple.xhtml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:out value="Simple tree:"/>
+
+    <tc:tree id="tree" value="#{tree.tree}" var="node" showRoot="true" showRootJunction="true"
+             state="#{tree.state}">
+      <tc:treeNode id="node">
+        <tc:treeIndent/>
+        <tc:treeIcon/>
+        <tc:treeLabel value="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:tree>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeListbox/treeListbox.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeListbox/treeListbox.xhtml
new file mode 100644
index 0000000..c396fb7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeListbox/treeListbox.xhtml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page>
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+
+    <tc:treeListbox id="tree" value="#{tree.tree}" var="node">
+      <tc:treeNode id="template">
+        <tc:treeLabel value="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:treeListbox>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeMenu/treeMenu-command.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeMenu/treeMenu-command.xhtml
new file mode 100644
index 0000000..f2bd18f
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeMenu/treeMenu-command.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:out value="Tree Menu with commands as nodes:"/>
+
+    <tc:treeMenu id="tree" value="#{tree.tree}" var="node" showRoot="true">
+      <tc:treeNode id="node">
+        <tc:treeCommand label="#{node.userObject.name}" action="#{node.userObject.action}"/>
+      </tc:treeNode>
+    </tc:treeMenu>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeMenu/treeMenu-simple.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeMenu/treeMenu-simple.xhtml
new file mode 100644
index 0000000..72d5d96
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/treeMenu/treeMenu-simple.xhtml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="300px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;*"/>
+    </f:facet>
+
+    <tc:out value="Simple Tree Menu:"/>
+
+    <tc:treeMenu id="tree" showRoot="true" value="#{tree.tree}" var="node">
+      <tc:treeNode id="template">
+        <tc:treeLabel value="#{node.userObject.name}"/>
+      </tc:treeNode>
+    </tc:treeMenu>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/type/measure-image-with-constraints.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/type/measure-image-with-constraints.xhtml
new file mode 100644
index 0000000..b1de2f7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/type/measure-image-with-constraints.xhtml
@@ -0,0 +1,142 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="2000px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+    </f:facet>
+    <!--
+    Test of different ways to set the size of tc:gridLayoutConstraint and tc:image.
+    There are literals like "100" or "100px" and 
+    different types like: Measure, Integer, int, String (?)
+    -->
+
+    <tc:image id="i-0" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="0"/>
+      <tc:dataAttribute name="assert-width" value="100"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="100px" height="95px"
+          minimumWidth="100px" minimumHeight="95px"
+          preferredWidth="100px" preferredHeight="95px"
+          maximumWidth="100px" maximumHeight="95px"/>
+    </tc:image>
+    <tc:image id="i-1" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="100"/>
+      <tc:dataAttribute name="assert-width" value="150"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="150" height="95"
+          minimumWidth="150" minimumHeight="95"
+          preferredWidth="150" preferredHeight="95"
+          maximumWidth="150" maximumHeight="95"/>
+    </tc:image>
+    <tc:image id="i-2" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="200"/>
+      <tc:dataAttribute name="assert-width" value="200"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="#{measureBean.intWidth}" height="#{measureBean.intHeight}"
+          minimumWidth="#{measureBean.intWidth}" minimumHeight="#{measureBean.intHeight}"
+          preferredWidth="#{measureBean.intWidth}" preferredHeight="#{measureBean.intHeight}"
+          maximumWidth="#{measureBean.intWidth}" maximumHeight="#{measureBean.intHeight}"/>
+    </tc:image>
+    <tc:image id="i-3" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="300"/>
+      <tc:dataAttribute name="assert-width" value="250"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="#{measureBean.integerWidth}" height="#{measureBean.integerHeight}"
+          minimumWidth="#{measureBean.integerWidth}" minimumHeight="#{measureBean.integerHeight}"
+          preferredWidth="#{measureBean.integerWidth}" preferredHeight="#{measureBean.integerHeight}"
+          maximumWidth="#{measureBean.integerWidth}" maximumHeight="#{measureBean.integerHeight}"/>
+    </tc:image>
+    <tc:image id="i-4" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="400"/>
+      <tc:dataAttribute name="assert-width" value="300"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="#{measureBean.measureWidth}" height="#{measureBean.measureHeight}"
+          minimumWidth="#{measureBean.measureWidth}" minimumHeight="#{measureBean.measureHeight}"
+          preferredWidth="#{measureBean.measureWidth}" preferredHeight="#{measureBean.measureHeight}"
+          maximumWidth="#{measureBean.measureWidth}" maximumHeight="#{measureBean.measureHeight}"/>
+    </tc:image>
+    <tc:image id="i-5" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="500"/>
+      <tc:dataAttribute name="assert-width" value="350"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="#{measureBean.stringWidth}" height="#{measureBean.stringHeight}"
+          minimumWidth="#{measureBean.stringWidth}" minimumHeight="#{measureBean.stringHeight}"
+          preferredWidth="#{measureBean.stringWidth}" preferredHeight="#{measureBean.stringHeight}"
+          maximumWidth="#{measureBean.stringWidth}" maximumHeight="#{measureBean.stringHeight}"/>
+    </tc:image>
+    <tc:image id="i-6" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="600"/>
+      <tc:dataAttribute name="assert-width" value="400"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="#{measureBean.stringPxWidth}" height="#{measureBean.stringPxHeight}"
+          minimumWidth="#{measureBean.stringPxWidth}" minimumHeight="#{measureBean.stringPxHeight}"
+          preferredWidth="#{measureBean.stringPxWidth}" preferredHeight="#{measureBean.stringPxHeight}"
+          maximumWidth="#{measureBean.stringPxWidth}" maximumHeight="#{measureBean.stringPxHeight}"/>
+    </tc:image>
+    <tc:image id="i-7" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="700"/>
+      <tc:dataAttribute name="assert-width" value="450"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="#{measureBean.longWidth}" height="#{measureBean.longHeight}"
+          minimumWidth="#{measureBean.longWidth}" minimumHeight="#{measureBean.longHeight}"
+          preferredWidth="#{measureBean.longWidth}" preferredHeight="#{measureBean.longHeight}"
+          maximumWidth="#{measureBean.longWidth}" maximumHeight="#{measureBean.longHeight}"/>
+    </tc:image>
+    <tc:image id="i-8" value="pidgeon-point.jpg">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="800"/>
+      <tc:dataAttribute name="assert-width" value="500"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+      <tc:gridLayoutConstraint
+          width="#{measureBean.anyWidth}" height="#{measureBean.anyHeight}"
+          minimumWidth="#{measureBean.anyWidth}" minimumHeight="#{measureBean.anyHeight}"
+          preferredWidth="#{measureBean.anyWidth}" preferredHeight="#{measureBean.anyHeight}"
+          maximumWidth="#{measureBean.anyWidth}" maximumHeight="#{measureBean.anyHeight}"/>
+    </tc:image>
+
+    <!-- fixme: this filler is not nice, should work automatically -->
+    <tc:panel>
+      <tc:gridLayoutConstraint width="100px" height="200px"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/type/measure-image-without-constraints.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/type/measure-image-without-constraints.xhtml
new file mode 100644
index 0000000..1f4ba23
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/type/measure-image-without-constraints.xhtml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:ui="http://java.sun.com/jsf/facelets"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="600px" height="2000px"/>
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto;auto"/>
+    </f:facet>
+    <!--
+    Test of different ways to set the size of tc:gridLayoutConstraint and tc:image.
+    There are literals like "100" or "100px" and 
+    different types like: Measure, Integer, int, String (?)
+    -->
+
+    <tc:image id="j-0" value="pidgeon-point.jpg" width="100px" height="95px">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="0"/>
+      <tc:dataAttribute name="assert-width" value="100"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-1" value="pidgeon-point.jpg" width="150" height="95">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="100"/>
+      <tc:dataAttribute name="assert-width" value="150"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-2" value="pidgeon-point.jpg"
+              width="#{measureBean.intWidth}" height="#{measureBean.intHeight}">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="200"/>
+      <tc:dataAttribute name="assert-width" value="200"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-3" value="pidgeon-point.jpg"
+              width="#{measureBean.integerWidth}" height="#{measureBean.integerHeight}">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="300"/>
+      <tc:dataAttribute name="assert-width" value="250"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-4" value="pidgeon-point.jpg"
+              width="#{measureBean.measureWidth}" height="#{measureBean.measureHeight}">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="400"/>
+      <tc:dataAttribute name="assert-width" value="300"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-5" value="pidgeon-point.jpg"
+              width="#{measureBean.stringWidth}" height="#{measureBean.stringHeight}">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="500"/>
+      <tc:dataAttribute name="assert-width" value="350"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-6" value="pidgeon-point.jpg"
+              width="#{measureBean.stringPxWidth}" height="#{measureBean.stringPxHeight}">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="600"/>
+      <tc:dataAttribute name="assert-width" value="400"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-7" value="pidgeon-point.jpg"
+              width="#{measureBean.longWidth}" height="#{measureBean.longHeight}">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="700"/>
+      <tc:dataAttribute name="assert-width" value="450"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <tc:image id="j-8" value="pidgeon-point.jpg"
+              width="#{measureBean.anyWidth}" height="#{measureBean.anyHeight}">
+      <tc:dataAttribute name="assert-left" value="0"/>
+      <tc:dataAttribute name="assert-top" value="800"/>
+      <tc:dataAttribute name="assert-width" value="500"/>
+      <tc:dataAttribute name="assert-height" value="95"/>
+    </tc:image>
+
+    <!-- fixme: this filler is not nice, should work automatically -->
+    <tc:panel>
+      <tc:gridLayoutConstraint width="100px" height="200px"/>
+    </tc:panel>
+
+    <tc:script file="script/tobago-assert.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/version/version.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/version/version.js
new file mode 100644
index 0000000..ca2afbc
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/version/version.js
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+TestVersion = {};
+
+TestVersion.init = function () {
+
+  var checked = jQuery("input[checked]");
+  if (checked.size() != 2) {
+    TobagoAssert.fail("2 field must be checked", null, 2, checked);
+  }
+
+  var textList = jQuery("input[type=text]");
+
+  var version = checked.eq(0).next().html().toLowerCase();
+  var packageVersion = "version " + textList.eq(0).val().toLowerCase();
+
+  if (packageVersion.indexOf(version) == -1) {
+    TobagoAssert.fail("Version number", null, version, packageVersion);
+  }
+
+  var impl = checked.eq(1).next().html().toLowerCase();
+  var packageImpl = textList.eq(1).val().toLowerCase();
+
+  if (packageImpl.indexOf(impl) == -1) {
+    TobagoAssert.fail("Implementation", null, impl, packageImpl);
+  }
+};
+
+Tobago.registerListener(TestVersion.init, Tobago.Phase.DOCUMENT_READY);
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/version/version.xhtml b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/version/version.xhtml
new file mode 100644
index 0000000..feefd2b
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/test/version/version.xhtml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<f:view
+    xmlns:tc="http://myfaces.apache.org/tobago/component"
+    xmlns:f="http://java.sun.com/jsf/core">
+
+  <tc:page id="page">
+    <tc:gridLayoutConstraint width="700px" height="600px"/>
+
+    <f:facet name="layout">
+      <tc:gridLayout rows="auto;auto"/>
+    </f:facet>
+
+    <tc:box label="From class FacesVersion">
+      <tc:selectBooleanCheckbox value="#{version.version11}" label="Version 1.1 (not supported)"/>
+      <tc:selectBooleanCheckbox value="#{version.version12}" label="Version 1.2 (not supported)"/>
+      <tc:selectBooleanCheckbox value="#{version.version20}" label="Version 2.0"/>
+      <tc:selectBooleanCheckbox value="#{version.version21}" label="Version 2.1"/>
+      <tc:selectBooleanCheckbox value="#{version.version22}" label="Version 2.2"/>
+
+      <tc:selectBooleanCheckbox value="#{version.mojarra}" label="Mojarra"/>
+      <tc:selectBooleanCheckbox value="#{version.myfaces}" label="MyFaces"/>
+    </tc:box>
+
+    <tc:box label="From package">
+      <tc:in value="#{version.jsfVersion}" label="JSF Version"/>
+      <tc:in value="#{version.jsfTitle}" label="JSF Title"/>
+    </tc:box>
+
+    <tc:script file="script/tobago-assert.js"/>
+    <tc:script file="test/version/version.js"/>
+
+  </tc:page>
+</f:view>
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/tobago-resource/html/standard/standard/script/tobago.js b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/tobago-resource/html/standard/standard/script/tobago.js
new file mode 100644
index 0000000..734f9b9
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/main/webapp/tobago-resource/html/standard/standard/script/tobago.js
@@ -0,0 +1,22 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * This entry is to test order of included JS Files.
+ * Used in resource-manager/script.xhtml
+ */
+
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/AutomaticSeleniumTest.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/AutomaticSeleniumTest.java
new file mode 100644
index 0000000..c81297a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/AutomaticSeleniumTest.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathExpressionException;
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+@RunWith(Parameterized.class)
+public class AutomaticSeleniumTest extends SeleniumTest {
+
+  private static final Logger LOG = LoggerFactory.getLogger(AutomaticSeleniumTest.class);
+
+  private static final String MAVEN_TARGET = "target/tobago-example-test";
+
+  private String url;
+
+  public AutomaticSeleniumTest(final String title, final String url) {
+    this.url = url;
+  }
+
+  @Test
+  public void testPageConsistency() throws Exception {
+    final SeleniumScript script = getSeleniumScript(url);
+
+    getSelenium().killSession();
+
+    for (final SeleniumScriptItem item : script.getItems()) {
+      LOG.info("Calling: " + item);
+      getSelenium().command(item.getCommand(), item.getParameters()[0], item.getParameters()[1]);
+      getSelenium().checkPage();
+    }
+  }
+
+  private SeleniumScript getSeleniumScript(final String url)
+      throws XPathExpressionException, SAXException, IOException, ParserConfigurationException {
+    String seleniumUrl = url.substring("/faces/".length());
+    seleniumUrl = seleniumUrl.substring(0, seleniumUrl.lastIndexOf("."));
+    seleniumUrl = "http://localhost:8080/" + seleniumUrl + ".selenium.html";
+    return new SeleniumScript(new URL(seleniumUrl), url);
+  }
+
+  @Parameterized.Parameters
+  public static Collection<Object[]> findPages() {
+    final List<String> paths = new ArrayList<String>();
+
+    String base = MAVEN_TARGET + '/';
+
+    // e.g. in the IDE normally the base dir is the tobago project root
+    if (!new File(base).exists()) {
+      base = "tobago-example/tobago-example-test/" + base;
+    }
+
+    collect(paths, base, "");
+
+    Collections.sort(paths);
+
+    final List<Object[]> result = new ArrayList<Object[]>();
+
+    for (final String path : paths) {
+      final Object[] objects = {
+          path.replace('.', '_'), // because dots will be displayed strange in the IDE
+          createUrl(path)
+      };
+      result.add(objects);
+    }
+
+    return result;
+  }
+
+  private static void collect(final List<String> result, final String base, final String directory) {
+
+    final File file = new File(base + directory);
+
+    if (!file.exists()) {
+      throw new RuntimeException("Input directory doesn't exists: '" + file.getAbsolutePath() + "'");
+    }
+
+    if (!file.isDirectory()) {
+      throw new RuntimeException("Input is not a directory: '" + file.getAbsolutePath() + "'");
+    }
+
+    final String[] filenames = file.list();
+
+    for (final String filename : filenames) {
+
+      final String path = directory + '/' + filename;
+
+      if (new File(base + path).isDirectory()) {
+        collect(result, base, path);
+        continue;
+      }
+
+      if (TestPageFilter.isValid(path) && !TestPageFilter.isDisabled(path) && !TestPageFilter.isTodo(path)) {
+        result.add(path);
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumScript.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumScript.java
new file mode 100644
index 0000000..8449ad4
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumScript.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.junit.Assert;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathExpressionException;
+import javax.xml.xpath.XPathFactory;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.StringReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SeleniumScript {
+
+  private static final XPathFactory XPATH_FACTORY;
+  private static final XPathExpression XPATH_EXPRESSION;
+  private static final XPathExpression TR_XPATH;
+  private static final XPathExpression TD_XPATH;
+
+  private List<SeleniumScriptItem> items = new ArrayList<SeleniumScriptItem>();
+
+  static {
+    try {
+      XPATH_FACTORY = XPathFactory.newInstance();
+      XPATH_EXPRESSION = XPATH_FACTORY.newXPath().compile("//table/tbody");
+      TR_XPATH = XPATH_FACTORY.newXPath().compile("tr");
+      TD_XPATH = XPATH_FACTORY.newXPath().compile("td");
+    } catch (final XPathExpressionException e) {
+      throw new RuntimeException(e);
+    }
+  }
+
+  public SeleniumScript(final URL scriptUrl, final String url)
+      throws IOException, XPathExpressionException, SAXException, ParserConfigurationException {
+    try {
+      final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+      final DocumentBuilder parser = factory.newDocumentBuilder();
+      parser.setEntityResolver(new EntityResolver() {
+        @Override
+        public InputSource resolveEntity(final String publicId, final String systemId)
+            throws SAXException, IOException {
+          // do not any resource resolving
+          return new InputSource(new StringReader(""));
+        }
+      });
+
+      final Document document = parser.parse(scriptUrl.openStream());
+      addSeleniumItems(document, url);
+    } catch (final FileNotFoundException e) {
+      // using default
+      items.add(new SeleniumScriptItem("open", url, ""));
+    }
+  }
+
+  private void addSeleniumItems(final Document document, final String url) throws XPathExpressionException {
+
+    final Object table = XPATH_EXPRESSION.evaluate(document, XPathConstants.NODE);
+    final NodeList trList = (NodeList) TR_XPATH.evaluate(table, XPathConstants.NODESET);
+
+    for (int i = 0; i < trList.getLength(); i++) {
+      final Node tr = trList.item(i);
+      final NodeList tdList = (NodeList) TD_XPATH.evaluate(tr, XPathConstants.NODESET);
+
+      Assert.assertEquals(3, tdList.getLength());
+
+      final String command = tdList.item(0).getTextContent();
+      String parameter1 = tdList.item(1).getTextContent();
+      final String parameter2 = tdList.item(2).getTextContent();
+      if (command.equals("open")) {
+        // for open commands, use the filename, not the name in the script,
+        // because we need the script for *.jspx and *.xhtml
+        final String realPrefix = url.substring(0, url.lastIndexOf("."));
+        final String scriptPrefix = parameter1.substring(0, parameter1.lastIndexOf("."));
+        Assert.assertEquals("Is the url in the script correct?", scriptPrefix, realPrefix);
+        parameter1 = url;
+      }
+
+      items.add(new SeleniumScriptItem(command, parameter1, parameter2));
+    }
+  }
+
+  public List<SeleniumScriptItem> getItems() {
+    return items;
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumScriptItem.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumScriptItem.java
new file mode 100644
index 0000000..07f328a
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumScriptItem.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+public class SeleniumScriptItem {
+
+  private String command;
+  private String[] parameters;
+
+  public SeleniumScriptItem(final String command, final String parameter1, final String parameter2) {
+    this.command = command;
+    this.parameters = new String[]{parameter1, parameter2};
+  }
+
+  public String getCommand() {
+    return command;
+  }
+
+  public String[] getParameters() {
+    return parameters;
+  }
+
+  @Override
+  public String toString() {
+    return command + "('" + parameters[0] + "', '" + parameters[1] + "')";
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumTest.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumTest.java
new file mode 100644
index 0000000..d87dc1c
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SeleniumTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+
+public abstract class SeleniumTest {
+
+  private static final String CONTEXT_PATH = "";
+  //  private static final String CONTEXT_PATH = "tobago-example-test";
+  private static final String SERVLET_MAPPING = "faces";
+
+  private static TobagoSelenium selenium;
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    selenium = new TobagoSelenium("http://localhost:8080/");
+    selenium.start();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    selenium.stop();
+  }
+
+  protected TobagoSelenium getSelenium() {
+    return selenium;
+  }
+
+  protected static String createUrl(final String page) {
+    Assert.assertTrue("Page name must start with a slash.", page.startsWith("/"));
+    if (CONTEXT_PATH.length() == 0) {
+      return '/' + SERVLET_MAPPING + page;
+    } else {
+      return '/' + CONTEXT_PATH + '/' + SERVLET_MAPPING + page;
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SimpleSeleniumTest.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SimpleSeleniumTest.java
new file mode 100644
index 0000000..1b5f9d7
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/SimpleSeleniumTest.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class SimpleSeleniumTest extends SeleniumTest {
+
+  @Test
+  public void testHelloWorld() {
+    getSelenium().open("/faces/simple.xhtml");
+    getSelenium().checkPage();
+    Assert.assertEquals("Simple Test", getSelenium().getValue("page:in"));
+    getSelenium().captureScreenshot(SimpleSeleniumTest.class.getName() + ".testHelloWorld.png");
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TestPageFilterUnitTest.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TestPageFilterUnitTest.java
new file mode 100644
index 0000000..c52db03
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TestPageFilterUnitTest.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestPageFilterUnitTest {
+
+  @Test
+  public void testIsValid() {
+    Assert.assertFalse(TestPageFilter.isValid("test.html"));
+    Assert.assertTrue(TestPageFilter.isValid("/test.html"));
+
+    Assert.assertFalse(TestPageFilter.isValid("/WEB-INF"));
+    Assert.assertFalse(TestPageFilter.isValid("/WEB-INF/"));
+    Assert.assertFalse(TestPageFilter.isValid("/WEB-INF/web.xml"));
+    Assert.assertFalse(TestPageFilter.isValid("/WEB-INF/test.xhtml"));
+
+    Assert.assertFalse(TestPageFilter.isValid("/NETA-INF"));
+    Assert.assertFalse(TestPageFilter.isValid("/META-INF/"));
+
+    Assert.assertTrue(TestPageFilter.isValid("/navigation.xhtml"));
+    Assert.assertTrue(TestPageFilter.isValid("/nav.xhtml"));
+
+    Assert.assertTrue(TestPageFilter.isDisabled("/navigation.xhtml"));
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TestTheAutomaticSeleniumTest.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TestTheAutomaticSeleniumTest.java
new file mode 100644
index 0000000..87dc046
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TestTheAutomaticSeleniumTest.java
@@ -0,0 +1,130 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import com.thoughtworks.selenium.SeleniumException;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+public class TestTheAutomaticSeleniumTest {
+
+  private static final Logger LOG = LoggerFactory.getLogger(TestTheAutomaticSeleniumTest.class);
+
+  @BeforeClass
+  public static void setUp() throws Exception {
+    AutomaticSeleniumTest.setUp();
+  }
+
+  @AfterClass
+  public static void tearDown() throws Exception {
+    AutomaticSeleniumTest.tearDown();
+  }
+
+  @Test
+  public void areTheCorrectFilesTested() {
+
+    final List<String> metaTestList = new ArrayList<String>();
+
+    final Collection<Object[]> pages = AutomaticSeleniumTest.findPages();
+    for (final Object[] page : pages) {
+      final String url = (String) page[1];
+      final String prefix = "/faces/meta-test/";
+      if (url.startsWith(prefix)) {
+        metaTestList.add(url.substring(prefix.length()));
+      }
+    }
+
+    Collections.sort(metaTestList);
+
+    final String[] expected = new String[]{
+        "meta-0-ok.jspx",
+        "meta-0-ok.xhtml",
+        "meta-2-ok.xhtml",
+        "meta-3-ok.jspx"
+    };
+
+    Assert.assertArrayEquals(expected, metaTestList.toArray());
+  }
+
+  @Test
+  public void test404() throws Exception {
+    try {
+      final String url = AutomaticSeleniumTest.createUrl("/meta-test/meta-404-not-existing.xhtml");
+      LOG.info("Testing page: '" + url + "'");
+      final AutomaticSeleniumTest test = new AutomaticSeleniumTest(url, url);
+
+      test.testPageConsistency();
+
+      Assert.fail("The test should fail, but wasn't.");
+    } catch (final AssertionError e) { // from IDE
+      Assert.assertTrue(e.getMessage().contains("404 - page not found"));
+    } catch (final SeleniumException e) { // from mvn -Pintegration-test
+      LOG.info("Exception: '" + e.getMessage() + "'");
+      Assert.assertTrue(e.getMessage().contains("Response_Code = 404"));
+    }
+  }
+
+  @Test
+  public void testErrorSeverity() throws Exception {
+    try {
+      final String url = AutomaticSeleniumTest.createUrl("/meta-test/meta-1-fail.xhtml");
+      LOG.info("Testing page: '" + url + "'");
+      final AutomaticSeleniumTest test = new AutomaticSeleniumTest(url, url);
+
+      test.testPageConsistency();
+
+      Assert.fail("The test should fail, but wasn't.");
+    } catch (final AssertionError e) {
+      if (e.getMessage().contains(TobagoSelenium.HAS_ERROR_SEVERITY)) {
+        // okay, the error was detected.
+      } else {
+        throw e;
+      }
+    }
+  }
+
+  @Test
+  public void testNotTobago() throws Exception {
+    try {
+      final String url = AutomaticSeleniumTest.createUrl("/meta-test/meta-4-not-tobago.xhtml");
+      LOG.info("Testing page: '" + url + "'");
+      final AutomaticSeleniumTest test = new AutomaticSeleniumTest(url, url);
+
+      test.testPageConsistency();
+
+      Assert.fail("The test should fail, but wasn't.");
+    } catch (final AssertionError e) {
+      if (e.getMessage().contains(TobagoSelenium.IS_BROKEN)) {
+        // okay, the error was detected.
+      } else {
+        throw e;
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TobagoSelenium.java b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TobagoSelenium.java
new file mode 100644
index 0000000..7a18d56
--- /dev/null
+++ b/tobago-3.0.x/tobago-example/tobago-example-test/src/test/java/org/apache/myfaces/tobago/example/test/TobagoSelenium.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.example.test;
+
+import com.thoughtworks.selenium.DefaultSelenium;
+import com.thoughtworks.selenium.HttpCommandProcessor;
+import com.thoughtworks.selenium.SeleniumException;
+import org.junit.Assert;
+
+public class TobagoSelenium extends DefaultSelenium {
+
+  public static final String ERROR_ON_SERVER = "error on server";
+  public static final String HAS_ERROR_SEVERITY = "has error severity";
+  public static final String IS_BROKEN = "is broken";
+
+  private String browserUrl;
+
+  public TobagoSelenium(final String browserUrl) {
+    //XXX should be replaced
+    //XXX http://www.seleniumhq.org/docs/appendix_migrating_from_rc_to_webdriver.jsp#migrating-to-webdriver-reference
+    super(new HttpCommandProcessor("localhost", 4444, "*firefox", browserUrl));
+    this.browserUrl = browserUrl;
+  }
+
+  public String command(final String command, final String parameter1, final String parameter2) {
+    return commandProcessor.doCommand(command, new String[]{parameter1, parameter2});
+  }
+
+  public void killSession() {
+    open(browserUrl + "KillSession");
+  }
+
+  public void checkPage() {
+    final String location = getLocation();
+    final String html = getHtmlSource();
+    if (errorOnServer()) {
+      Assert.fail(format(ERROR_ON_SERVER, location, html, ""));
+    }
+    if (location.endsWith(".xhtml") || location.endsWith(".jspx")) {
+      try {
+        if (isErrorOnPage()) {
+          Assert.fail(format(HAS_ERROR_SEVERITY, location, html, "TobagoAssert.failed"));
+        }
+      } catch (final SeleniumException e) {
+        Assert.fail(format(IS_BROKEN, location, html, "Not a Tobago page? Exception=" + e));
+      }
+    }
+  }
+
+  public String format(final String error, final String location, final String html, final String options) {
+    final StringBuilder b = new StringBuilder();
+    b.append(error);
+    b.append("\nPage URL: ");
+    b.append(location);
+    b.append("\n");
+    b.append(options);
+    b.append("\n---------------------------------------------------------------------------------------------------\n");
+    b.append(html);
+    b.append("\n---------------------------------------------------------------------------------------------------\n");
+    return b.toString();
+  }
+
+  /**
+   * Happen an exception from MyFaces on the page?
+   */
+  protected boolean errorOnServer() {
+    return getHtmlSource().contains("An Error Occurred");
+  }
+
+  /**
+   * Checks the page for the Tobago JavaScript Logging Framework and tests its severity.
+   *
+   * @return True if the severity level of the page is error
+   * @throws com.thoughtworks.selenium.SeleniumException
+   *          If the page is not a Tobago page, or any other problem with JavaScript or the page.
+   */
+  protected boolean isErrorOnPage() throws SeleniumException {
+    final String errorSeverity = getEval("window.TobagoAssert && window.TobagoAssert.failed");
+    return Boolean.parseBoolean(errorSeverity);
+  }
+}
diff --git a/tobago-3.0.x/tobago-extension/pom.xml b/tobago-3.0.x/tobago-extension/pom.xml
new file mode 100644
index 0000000..195ccec
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance withA
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <packaging>pom</packaging>
+  <name>Tobago Extensions</name>
+  <artifactId>tobago-extension</artifactId>
+
+  <modules>
+    <module>tobago-sandbox</module>
+  </modules>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.core</groupId>
+      <artifactId>myfaces-api</artifactId>
+      <optional>true</optional>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/pom.xml b/tobago-3.0.x/tobago-extension/tobago-sandbox/pom.xml
new file mode 100644
index 0000000..c17cea5
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/pom.xml
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-extension</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-sandbox</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Sandbox</name>
+
+  <build>
+
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>build-helper-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>add-source</id>
+            <phase>generate-sources</phase>
+            <goals>
+              <goal>add-source</goal>
+            </goals>
+            <configuration>
+              <sources>
+                <source>${project.build.directory}/generated</source>
+              </sources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-dependency-plugin</artifactId>
+        <executions>
+          <execution>
+          <id>unpack-sources</id>
+          <phase>generate-sources</phase>
+          <goals><goal>unpack</goal></goals>
+          <configuration>
+            <artifactItems>
+              <artifactItem>
+                <groupId>org.apache.myfaces.tobago</groupId>
+                <artifactId>tobago-core</artifactId>
+                <version>${project.version}</version>
+                <type>jar</type>
+                <classifier>sources</classifier>
+                <includes>org/apache/myfaces/tobago/internal/taglib/declaration/**/*</includes>                  
+              </artifactItem>
+            </artifactItems>
+            <outputDirectory>${project.build.directory}/tobago-core-sources</outputDirectory>
+          </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>org.bsc.maven</groupId>
+        <artifactId>maven-processor-plugin</artifactId>
+        <version>2.2.4</version>
+        <executions>
+          <execution>
+            <id>process</id>
+            <goals>
+              <goal>process</goal>
+            </goals>
+            <phase>generate-sources</phase>
+            <configuration>
+              <!-- source output directory -->
+              <additionalSourceDirectories>
+                <additionalSourceDirectory>${project.build.directory}/tobago-core-sources</additionalSourceDirectory>
+              </additionalSourceDirectories>
+              <outputDirectory>${project.build.directory}/generated</outputDirectory>
+              <processors>
+                <processor>org.apache.myfaces.tobago.apt.processor.ClassesGenerator</processor>
+                <processor>org.apache.myfaces.tobago.apt.processor.TaglibGenerator</processor>
+                <processor>org.apache.myfaces.tobago.apt.processor.FacesConfigGenerator</processor>
+              </processors>
+              <optionMap>
+                <sourceFacesConfig>${basedir}/src/main/faces-config/faces-config.xml</sourceFacesConfig>
+                <targetFacesConfig>META-INF/faces-config.xml</targetFacesConfig>
+                <targetTaglib>META-INF</targetTaglib>
+              </optionMap>
+            </configuration>
+          </execution>
+        </executions>
+        <dependencies>
+          <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <version>${slf4j.version}</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <configuration>
+          <source>${maven.compile.source}</source>
+          <target>${maven.compile.target}</target>
+          <encoding>${maven.compile.encoding}</encoding>
+          <showWarnings>true</showWarnings>
+          <excludes>
+            <exclude>workaround-because-otherwise-this-will-be-excluded-in-the-next-step</exclude>
+            <exclude>org/apache/myfaces/tobago/renderkit/html/sandbox/standard/tag/SelectManyShuttleRenderer.java</exclude>
+          </excludes>
+        </configuration>
+        <executions>
+          <execution>
+            <id>compile</id>
+            <goals><goal>compile</goal></goals>
+            <configuration>
+              <source>${maven.compile.source}</source>
+              <target>${maven.compile.target}</target>
+              <encoding>${maven.compile.encoding}</encoding>
+              <showWarnings>true</showWarnings>
+              <includes>
+                <include>org/apache/myfaces/tobago/internal/taglib/*</include>
+                <include>org/apache/myfaces/tobago/component/*</include>
+                <include>org/apache/myfaces/tobago/renderkit/*</include>
+                <include>org/apache/myfaces/tobago/renderkit/html/sandbox/standard/tag/SelectManyShuttleRenderer.java</include>
+              </includes>
+              <excludes>
+                <exclude>test</exclude>
+              </excludes>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <artifactId>maven-resources-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>copy-resources</id>
+            <goals><goal>copy-resources</goal></goals>
+            <phase>process-classes</phase>
+            <configuration>
+              <outputDirectory>${project.build.outputDirectory}</outputDirectory>
+              <resources>
+                <resource>
+                  <directory>${project.build.directory}/generated</directory>
+                  <includes>
+                    <include>META-INF/**/*</include>
+                  </includes>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+          <execution>
+            <id>copy-tld</id>
+            <goals><goal>copy-resources</goal></goals>
+            <phase>process-classes</phase>
+            <configuration>
+              <outputDirectory>${project.build.outputDirectory}</outputDirectory>
+              <resources>
+                <resource>
+                  <targetPath>META-INF</targetPath>
+                  <directory>${project.build.directory}/generated</directory>
+                </resource>
+              </resources>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+
+  <reporting>
+    <plugins>
+
+      <plugin>
+        <groupId>com.github.matinh.vdldoc</groupId>
+        <artifactId>vdldoc-maven-plugin</artifactId>
+        <configuration>
+          <destDir>tlddoc</destDir>
+          <documentTitle>Tag Library Documentation</documentTitle>
+          <excludes>
+            <exclude>target/classes/**</exclude>
+          </excludes>
+          <includes>
+            <include>target/generated/META-INF/tobago-sandbox.taglib.xml</include>
+          </includes>
+          <reportOutputDirectory>target</reportOutputDirectory>
+        </configuration>
+      </plugin>
+
+    </plugins>
+  </reporting>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-tool-apt</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-tool-annotation</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.test</groupId>
+      <artifactId>myfaces-test20</artifactId>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+    <profile>
+      <id>generate-assembly</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>com.github.matinh.vdldoc</groupId>
+            <artifactId>vdldoc-maven-plugin</artifactId>
+            <configuration>
+              <destDir>tlddoc</destDir>
+              <documentTitle>Tag Library Documentation</documentTitle>
+              <excludes>
+                <exclude>target/classes/**</exclude>
+              </excludes>
+              <includes>
+                <include>target/generated/META-INF/tobago-sandbox.taglib.xml</include>
+              </includes>
+              <reportOutputDirectory>target</reportOutputDirectory>
+            </configuration>
+            <executions>
+              <execution>
+                <id>attach-tlddoc</id>
+                <phase>generate-sources</phase>
+                <goals>
+                  <goal>vdldoc</goal>
+                </goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+    <profile>
+      <id>attach-source</id>
+      <build>
+        <plugins>
+          <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-source-plugin</artifactId>
+            <executions>
+              <execution>
+                <id>attach-source</id>
+                <goals><goal>jar</goal></goals>
+              </execution>
+            </executions>
+          </plugin>
+        </plugins>
+      </build>
+    </profile>
+
+  </profiles>
+</project>
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/readme.txt b/tobago-3.0.x/tobago-extension/tobago-sandbox/readme.txt
new file mode 100644
index 0000000..1ee8535
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/readme.txt
@@ -0,0 +1,6 @@
+Building
+--------
+
+This arifact requires the tobago-core-sources.jar artifact.
+The tobago-core-sources.jar is generated with the profile
+attach-source in core (mvn -P attach-source).
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..31df991
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,3 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH,
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/faces-config/faces-config.xml b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/faces-config/faces-config.xml
new file mode 100644
index 0000000..8cd7a9a
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/faces-config/faces-config.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<faces-config
+    xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
+    version="2.0">
+
+  <name>tobago_sandbox</name>
+
+</faces-config>
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUINumberSlider.java b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUINumberSlider.java
new file mode 100644
index 0000000..ba3b7d7
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUINumberSlider.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+
+import javax.faces.context.FacesContext;
+import javax.faces.validator.LongRangeValidator;
+import javax.faces.validator.ValidatorException;
+
+public abstract class AbstractUINumberSlider extends javax.faces.component.UIInput implements Visual {
+
+  public abstract Integer getMin();
+
+  public abstract Integer getMax();
+
+  public abstract boolean isReadonly();
+  
+  public abstract boolean isDisabled();
+
+  @Override
+  public void validate(final FacesContext context) {
+    super.validate(context);
+    try {
+      new LongRangeValidator(getMax(), getMin()).validate(context, this, getValue());
+    } catch (final ValidatorException e) {
+      context.addMessage(getClientId(context), e.getFacesMessage());
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISplitLayout.java b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISplitLayout.java
new file mode 100644
index 0000000..6594ed1
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/component/AbstractUISplitLayout.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.component;
+
+import org.apache.myfaces.tobago.component.Visual;
+import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.Orientation;
+
+import javax.el.ELContext;
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.util.List;
+
+public abstract class AbstractUISplitLayout extends AbstractUIGridLayout {
+
+  private String submittedLayout;
+
+  public void updateLayout(final int position) {
+    final List<UIComponent> components = LayoutUtils.findLayoutChildren(getParent());
+    final Visual firstComponent = (Visual) components.get(0);
+    final Visual secondComponent = (Visual) components.get(1);
+    final int oldPosition;
+
+    final int currentSize1;
+    final int currentSize2;
+/* XXX to be reimplemented: not using GridLayout, it might be better using flex?!
+    if (getOrientation() == Orientation.horizontal) {
+      oldPosition = secondComponent.getLeft().getPixel() - 5;
+      currentSize1 = firstComponent.getCurrentWidth().getPixel();
+      currentSize2 = secondComponent.getCurrentWidth().getPixel();
+    } else {
+      oldPosition = secondComponent.getTop().getPixel() - 5;
+      currentSize1 = firstComponent.getCurrentHeight().getPixel();
+      currentSize2 = secondComponent.getCurrentHeight().getPixel();
+    }
+
+    final int offset = position - oldPosition;
+    final int newSize1 = currentSize1 + offset;
+    final int newSize2 = currentSize2 - offset;
+
+    final int ggt = gcd(newSize1, newSize2);
+    submittedLayout = Integer.toString(newSize1 / ggt) + "*;" + Integer.toString(newSize2 / ggt) + "*";
+*/
+  }
+
+  // TODO: MathUtils
+  public static int gcd(int a, int b) {
+    if (a < 0) {
+      a = -a;
+    }
+    if (b < 0) {
+      b = -b;
+    }
+    int t;
+    while (b != 0) {
+      t = a % b;
+      a = b;
+      b = t;
+    }
+    return a;
+  }
+
+  @Override
+  public void processUpdates(final FacesContext facesContext) {
+    updateModel(facesContext);
+    super.processUpdates(facesContext);
+  }
+
+  private void updateModel(final FacesContext facesContext) {
+    if (submittedLayout != null) {
+      final ValueExpression expression = getValueExpression("layout");
+      if (expression != null) {
+        final ELContext elContext = facesContext.getELContext();
+        expression.setValue(elContext, submittedLayout);
+        submittedLayout = null;
+      }
+    }
+  }
+
+@Override
+  public void setColumns(final String columns) {
+  }
+
+  @Override
+  public String getColumns() {
+    return getOrientation() == Orientation.vertical ? "1*" : getLayout2();
+  }
+
+//  private String getLayout2() {
+//    return getLayout().replace(";", ";5px;");
+//  }
+
+  @Override
+  public void setRows(final String rows) {
+  }
+
+  @Override
+  public String getRows() {
+    return getOrientation() == Orientation.horizontal ? "1*" : getLayout2();
+  }
+
+  private String getLayout2() {
+    return submittedLayout != null ? submittedLayout : getLayout();
+  }
+
+  public abstract String getLayout();
+
+  public abstract Orientation getOrientation();
+
+  public abstract Measure getRowSpacing();
+
+  public abstract Measure getColumnSpacing();
+
+  @Override
+  public abstract boolean isRigid();
+}
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/NumberSliderTagDeclaration.java b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/NumberSliderTagDeclaration.java
new file mode 100644
index 0000000..6e61116
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/NumberSliderTagDeclaration.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.sandbox;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasIdBindingAndRendered;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValue;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasValueChangeListener;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsDisabled;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsReadonly;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+
+import javax.faces.component.UIInput;
+
+/**
+ * Renders a slider to select a number in a range.
+ */
+@Tag(name = "numberSlider")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UINumberSlider",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUINumberSlider",
+    uiComponentFacesClass = "javax.faces.component.UIInput",
+    componentFamily = UIInput.COMPONENT_FAMILY,
+    rendererType = "NumberSlider")
+public interface NumberSliderTagDeclaration
+    extends HasIdBindingAndRendered, IsReadonly, IsDisabled,
+    HasValue, HasValueChangeListener, IsVisual {
+
+  /**
+   * The minimum integer that can be entered and which represents the left
+   * border of the slider.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "0")
+  void setMin(String min);
+
+  /**
+   * The maximum integer that can be entered and which represents the right
+   * border of the slider.
+   */
+  @TagAttribute()
+  @UIComponentTagAttribute(type = "java.lang.Integer", defaultValue = "100")
+  void setMax(String max);
+}
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/SplitLayoutTagDeclaration.java b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/SplitLayoutTagDeclaration.java
new file mode 100644
index 0000000..a9966b7
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/SplitLayoutTagDeclaration.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.internal.taglib.sandbox;
+
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.internal.component.AbstractUIGridLayout;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasBinding;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasId;
+import org.apache.myfaces.tobago.internal.taglib.declaration.HasSpacing;
+import org.apache.myfaces.tobago.internal.taglib.declaration.IsVisual;
+import org.apache.myfaces.tobago.layout.Orientation;
+
+/**
+   * Renders a SplitLayout.
+   * A area with two child components rendered horizontally or vertically and allows to change the
+   * layout relation of this two components on the client.
+   */
+@Tag(name = "splitLayout")
+@UIComponentTag(
+    uiComponent = "org.apache.myfaces.tobago.component.UISplitLayout",
+    uiComponentBaseClass = "org.apache.myfaces.tobago.internal.component.AbstractUISplitLayout",
+    componentFamily = AbstractUIGridLayout.COMPONENT_FAMILY,
+    rendererType = "SplitLayout",
+    allowedChildComponenents = "NONE")
+public interface SplitLayoutTagDeclaration
+      extends HasId, HasSpacing, HasBinding, IsVisual {
+
+  /**
+   * This value defines the layout constraints for the layout.
+   * It is two layout tokens separated by a semicolon. See GridLayout.
+   * Example: '2*;*'.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(defaultValue = "1*;1*")
+  void setLayout(String rows);
+
+  /**
+   * This value defines the orientation of the split layout.
+   * Possible values are {@link Orientation#horizontal} and {@link Orientation#vertical}.
+   */
+  @TagAttribute(required = true)
+  @UIComponentTagAttribute(
+      type = "org.apache.myfaces.tobago.layout.Orientation",
+      allowedValues = {Orientation.HORIZONTAL, Orientation.VERTICAL})
+  void setOrientation(String orientation);
+
+  /**
+   * This attribute advises the layout manager, to not use space that comes from non rendered components.
+   */
+  @TagAttribute
+  @UIComponentTagAttribute(type = "boolean")
+  void setRigid(String rigid);
+}
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/package-info.java b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/package-info.java
new file mode 100644
index 0000000..8b62b42
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/internal/taglib/sandbox/package-info.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * <b>Tobago Framework Sandbox Tag Library 3.0.x -
+ * (C) Copyright 2002-2017 The Apache Software Foundation</b>
+ *
+ * <b>Warning: The sandbox tag library contains unstable components.
+ * Everything is subject to change without prior notice.</b>
+ */
+@org.apache.myfaces.tobago.apt.annotation.Taglib(
+    shortName = "tcs",
+    uri = "http://myfaces.apache.org/tobago/sandbox",
+    name = "tobago-sandbox",
+    displayName = "Tobago Sandbox 3.0.x")
+
+package org.apache.myfaces.tobago.internal.taglib.sandbox;
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/renderkit/html/sandbox/standard/tag/NumberSliderRenderer.java b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/renderkit/html/sandbox/standard/tag/NumberSliderRenderer.java
new file mode 100644
index 0000000..bb8b630
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/renderkit/html/sandbox/standard/tag/NumberSliderRenderer.java
@@ -0,0 +1,185 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html.sandbox.standard.tag;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUINumberSlider;
+import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
+import org.apache.myfaces.tobago.layout.Measure;
+import org.apache.myfaces.tobago.layout.Position;
+import org.apache.myfaces.tobago.renderkit.RendererBase;
+import org.apache.myfaces.tobago.renderkit.css.Classes;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
+import org.apache.myfaces.tobago.util.ComponentUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIInput;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.Map;
+
+public class NumberSliderRenderer extends RendererBase {
+
+  @Override
+  public void encodeEnd(final FacesContext facesContext, final UIComponent component) throws IOException {
+
+    final AbstractUINumberSlider slider = (AbstractUINumberSlider) component;
+    
+    final String id = slider.getClientId(facesContext);
+    final String currentValue = getCurrentValue(facesContext, slider);
+    final boolean readonly = slider.isReadonly();
+    final boolean disabled = slider.isDisabled();
+    final Integer min = slider.getMin();
+    final Integer max = slider.getMax();
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+
+//    final Style style = slider.getStyle();
+//    final int width = -1;
+//    int sliderWidthPerc
+//        = getResourceManager().getThemeMeasure(facesContext, slider, SLIDER_WIDTH_PERCENT).getPixel();
+//      if (sliderWidthPerc <= 25) {
+//        sliderWidthPerc = 25;
+//      }
+//      if (sliderWidthPerc >= 75) {
+//        sliderWidthPerc = 75;
+//      }
+//    int sliderWidth = 100; // fixme
+//    int inputWidth = 50; // fixme;
+//    if (style.getWidth() != null && style.getWidth().getPixel() >= 0) {
+//      sliderWidth = (width * sliderWidthPerc) / 100;
+//      inputWidth = (width * (100 - sliderWidthPerc)) / 100;
+//    }
+
+    writer.startElement(HtmlElements.TABLE);
+    writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.PRESENTATION.toString(), false);
+    writer.writeIdAttribute(id);
+    writer.writeClassAttribute(Classes.create(slider), slider.getCustomClass());
+    HtmlRendererUtils.writeDataAttributes(facesContext, writer, slider);
+    writer.writeStyleAttribute(slider.getStyle());
+    //writer.writeAttribute(HtmlAttributes.border,"1",false);
+
+    writer.startElement(HtmlElements.TR);
+    writer.startElement(HtmlElements.TD);
+    writer.writeClassAttribute(Classes.create(slider, "min"));
+
+    final Style widthStyle = new Style();
+//    widthStyle.setWidth(Measure.valueOf(sliderWidth / 2));
+    writer.writeStyleAttribute(widthStyle);
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(Classes.create(slider, "min"));
+    writer.write(Integer.toString(min));
+    writer.endElement(HtmlElements.SPAN);
+
+    writer.endElement(HtmlElements.TD);
+    writer.startElement(HtmlElements.TD);
+    writer.writeClassAttribute(Classes.create(slider, "max"));
+    writer.writeStyleAttribute(widthStyle);
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeClassAttribute(Classes.create(slider, "max"));
+    writer.write(Integer.toString(max));
+    writer.endElement(HtmlElements.SPAN);
+    writer.endElement(HtmlElements.TD);
+
+    // the input field starts here
+    writer.startElement(HtmlElements.TD);
+    writer.writeAttribute(HtmlAttributes.ROWSPAN, "2", false);
+    writer.writeClassAttribute(Classes.create(slider, "td"));
+
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeClassAttribute(Classes.create(slider, "input"));
+//    widthStyle.setWidth(Measure.valueOf(inputWidth));
+    writer.writeStyleAttribute(widthStyle);
+    final String inputIdAndName = getIdForInputField(facesContext, slider);
+    writer.writeNameAttribute(inputIdAndName);
+    writer.writeIdAttribute(inputIdAndName);
+    if (currentValue != null) {
+      writer.writeAttribute(HtmlAttributes.VALUE, currentValue, false);
+    }
+    writer.writeAttribute(HtmlAttributes.READONLY, readonly);
+    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
+    writer.endElement(HtmlElements.INPUT);
+    writer.endElement(HtmlElements.TD);
+
+    writer.endElement(HtmlElements.TR);
+    writer.startElement(HtmlElements.TR);
+    writer.startElement(HtmlElements.TD);
+    writer.writeAttribute(HtmlAttributes.COLSPAN, 2);
+
+    //track
+    writer.startElement(HtmlElements.DIV);
+    writer.writeClassAttribute(Classes.create(slider, "slider"));
+    writer.writeIdAttribute(getIdForSliderTrack(facesContext, slider));
+
+    // handle
+    writer.startElement(HtmlElements.DIV);
+    writer.writeIdAttribute(getIdForSliderHandle(facesContext, slider));
+    final Style handleStyle = new Style();
+    handleStyle.setPosition(Position.relative);
+    handleStyle.setTop(Measure.valueOf(-6));
+    handleStyle.setWidth(Measure.valueOf(12));
+    handleStyle.setHeight(Measure.valueOf(6));
+    writer.writeStyleAttribute(handleStyle); // todo: why not do that via the class?
+    writer.startElement(HtmlElements.IMG);
+    writer.writeAttribute(HtmlAttributes.SRC, facesContext.getExternalContext().getRequestContextPath(), true);
+    writer.endElement(HtmlElements.IMG);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.DIV);
+    writer.endElement(HtmlElements.TD);
+    writer.endElement(HtmlElements.TR);
+    writer.endElement(HtmlElements.TABLE);
+
+//    writeSliderJavaScript(facesContext, slider, writer);
+    //HtmlRendererUtils.renderFocusId(facesContext, slider);
+  }
+
+  @Override
+  public void decode(final FacesContext context, final UIComponent component) {
+    final UIInput uiInput;
+    if (component instanceof UIInput && !ComponentUtils.isOutputOnly(component)) {
+      uiInput = (UIInput) component;
+    } else {
+      return;
+    }
+    final String inputId = getIdForInputField(context, component);
+    final Map requestParameterMap = context.getExternalContext().getRequestParameterMap();
+    if (requestParameterMap.containsKey(inputId)) {
+      final String newValue = (String) requestParameterMap.get(inputId);
+      uiInput.setSubmittedValue(newValue);
+    }
+  }
+
+  private String getIdForInputField(final FacesContext context, final UIComponent component) {
+    final String id = component.getClientId(context);
+    return id + ComponentUtils.SUB_SEPARATOR + "input";
+  }
+
+  private String getIdForSliderTrack(final FacesContext context, final UIComponent component) {
+    final String id = component.getClientId(context);
+    return id + ComponentUtils.SUB_SEPARATOR + "track";
+  }
+
+  private String getIdForSliderHandle(final FacesContext context, final UIComponent component) {
+    final String id = component.getClientId(context);
+    return id + ComponentUtils.SUB_SEPARATOR + "handle";
+  }
+}
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SplitLayoutRenderer.java b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SplitLayoutRenderer.java
new file mode 100644
index 0000000..a222183
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/java/org/apache/myfaces/tobago/renderkit/html/scarborough/standard/tag/SplitLayoutRenderer.java
@@ -0,0 +1,166 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html.scarborough.standard.tag;
+
+import org.apache.myfaces.tobago.internal.component.AbstractUISplitLayout;
+import org.apache.myfaces.tobago.internal.layout.LayoutUtils;
+import org.apache.myfaces.tobago.renderkit.css.Style;
+import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
+import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
+import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
+import org.apache.myfaces.tobago.renderkit.html.MarkupLanguageAttributes;
+import org.apache.myfaces.tobago.internal.renderkit.renderer.GridLayoutRenderer;
+import org.apache.myfaces.tobago.internal.util.RenderUtils;
+import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class SplitLayoutRenderer extends GridLayoutRenderer {
+
+  private static final Logger LOG = LoggerFactory.getLogger(SplitLayoutRenderer.class);
+  private static final String POSITION_ID_POSTFIX = "_spLP";
+
+  // todo: put as enum to DataAttributes, when moved from sandbox to core
+  private static final MarkupLanguageAttributes SPLIT_LAYOUT = DataAttributes.dynamic("tobago-split-layout");
+
+  // todo: put as enum to DataAttributes, when moved from sandbox to core
+  private static final MarkupLanguageAttributes SPLIT_LAYOUT_CONTAINMENT
+      = DataAttributes.dynamic("data-tobago-split-layout-containment");
+
+  @Override
+  public void decode(final FacesContext facesContext, final UIComponent component) {
+    final String sourceId = facesContext.getExternalContext().getRequestParameterMap().get("javax.faces.source");
+    final String clientId = component.getClientId();
+    if (clientId.equals(sourceId)) {
+      // only decode and update layout at resize request
+      final Map<String, String> parameterMap = facesContext.getExternalContext().getRequestParameterMap();
+      final String position = parameterMap.get(clientId + POSITION_ID_POSTFIX);
+      ((AbstractUISplitLayout) component).updateLayout(Integer.parseInt(position));
+    }
+  }
+
+  @Override
+  public void encodeChildren(final FacesContext facesContext, final UIComponent component) throws IOException {
+    final UIComponent parent = component.getParent();
+    if (parent.isRendered()) {
+      final List<UIComponent> components = LayoutUtils.findLayoutChildren(parent);
+      if (components.size() != 2) {
+        LOG.warn("Illegal component count in splitLayout: {}", components.size());
+      }
+      RenderUtils.encode(facesContext, components.get(0));
+      RenderUtils.encode(facesContext, components.get(1));
+      if (components.get(0).isRendered() && components.get(1).isRendered()) {
+        // only when both components are rendered
+        encodeHandle(facesContext, (AbstractUISplitLayout) component);
+      }
+    }
+  }
+
+  protected void encodeHandle(final FacesContext facesContext, final AbstractUISplitLayout layout) throws IOException {
+    final String id = layout.getClientId(facesContext);
+
+    final TobagoResponseWriter writer = getResponseWriter(facesContext);
+    writer.startElement(HtmlElements.SPAN);
+    writer.writeIdAttribute(id);
+    writer.writeAttribute(SPLIT_LAYOUT, layout.getOrientation().name(), false);
+    writer.writeAttribute(SPLIT_LAYOUT_CONTAINMENT, createDraggableContainment(layout), true);
+/* XXX todo not implemented currently
+    final Style style = calculateHandleStyle(layout);
+    writer.writeStyleAttribute(style);
+    writer.writeClassAttribute(Classes.create(layout, layout.getOrientation().name()));
+
+    final int position;
+    if (layout.getOrientation() == Orientation.horizontal) {
+      position = style.getLeft().getPixel();
+    } else {
+      position = style.getTop().getPixel();
+    }
+*/
+    writer.startElement(HtmlElements.INPUT);
+    writer.writeIdAttribute(id + POSITION_ID_POSTFIX);
+    writer.writeNameAttribute(id + POSITION_ID_POSTFIX);
+    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
+//    writer.writeAttribute(HtmlAttributes.value, Integer.toString(position), false);
+    writer.endElement(HtmlElements.INPUT);
+    writer.endElement(HtmlElements.SPAN);
+  }
+
+  private String createDraggableContainment(final AbstractUISplitLayout layout) {
+/* XXX todo not implemented currently
+    final UIComponent parent = layout.getParent();
+    final LayoutContainer container = (LayoutContainer) parent;
+    final List<UIComponent> components = LayoutUtils.findLayoutChildren(parent);
+    final Style firstComponent = ((Visual) components.get(0)).getStyle();
+    final Style secondComponent = ((Visual) components.get(1)).getStyle();
+
+    Measure minimum;
+
+    if (layout.getOrientation() == Orientation.horizontal) {
+      minimum = firstComponent.getMinWidth();
+      final int minimumSize1 = minimum != null ? minimum.getPixel() : 0;
+      minimum = secondComponent.getMinWidth();
+      final int minimumSize2 = minimum != null ? minimum.getPixel() : 0;
+      final int totalSize = container.getWidth().getPixel();
+      return "[" + minimumSize1 + ", 0, " + (totalSize - minimumSize2) + ", 0]";
+    } else {
+      minimum = firstComponent.getMinHeight();
+      final int minimumSize1 = minimum != null ? minimum.getPixel() : 0;
+      minimum = secondComponent.getMinHeight();
+      final int minimumSize2 = minimum != null ? minimum.getPixel() : 0;
+      final int totalSize = container.getHeight().getPixel();
+      return "[0, " + minimumSize1 + ", 0, " + (totalSize - minimumSize2) + "]";
+    }
+*/
+    return "";
+  }
+
+  private Style calculateHandleStyle(final AbstractUISplitLayout layout) {
+/* XXX todo not implemented currently
+    final UIComponent parent = layout.getParent();
+    final LayoutContainer container = (LayoutContainer) parent;
+    final LayoutComponent secondComponent = (LayoutComponent) LayoutUtils.findLayoutChildren(parent).get(1);
+    final Style style = new Style();
+
+    if (layout.getOrientation() == Orientation.horizontal) {
+      style.setWidth(Measure.valueOf(5));
+      style.setHeight(container.getCurrentHeight());
+      style.setLeft(Measure.valueOf(secondComponent.getLeft().subtract(5)));
+      style.setTop(Measure.valueOf(0));
+    } else {
+      style.setWidth(container.getCurrentWidth());
+      style.setHeight(Measure.valueOf(5));
+      style.setLeft(Measure.valueOf(0));
+      style.setTop(Measure.valueOf(Measure.valueOf(secondComponent.getTop().subtract(5))));
+    }
+    // todo: use CSS class
+    style.setDisplay(Display.block);
+    style.setPosition(Position.absolute);
+    return style;
+*/
+    return null;
+  }
+}
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/META-INF/tobago-config.xml b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/META-INF/tobago-config.xml
new file mode 100644
index 0000000..9c47f78
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/META-INF/tobago-config.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+    version="3.0">
+  <name>tobago-sandbox</name>
+  <ordering>
+    <after>
+      <name>tobago-theme-speyside</name>
+    </after>
+  </ordering>
+  <theme-definitions>
+    <theme-definition>
+      <name>sandbox</name>
+      <display-name>Sandbox Theme</display-name>
+      <fallback>speyside</fallback>
+      <versioned>false</versioned>
+      <resources production="true">
+        <script name="script/tobago.js"/>
+        <style name="style/tobago.css"/>
+      </resources>
+      <resources production="false">
+        <script name="script/tobago.js"/>
+        <style name="style/tobago.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/image/sliderEnd.png b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/image/sliderEnd.png
new file mode 100644
index 0000000..af303c9
Binary files /dev/null and b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/image/sliderEnd.png differ
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/image/sliderTriangle.png b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/image/sliderTriangle.png
new file mode 100644
index 0000000..ba56214
Binary files /dev/null and b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/image/sliderTriangle.png differ
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/script/tobago.js b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/script/tobago.js
new file mode 100644
index 0000000..cfccbf7
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/script/tobago.js
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.SplitLayout = {
+  init: function(elements) {
+    Tobago.Utils.selectWithJQuery(elements, "[data-tobago-split-layout]").each(Tobago.SplitLayout.initLayout);
+  },
+
+  initLayout: function() {
+    var handle = jQuery(this);
+    var offset = handle.parent().offset();
+    var containment = handle.data("tobago-split-layout-containment");
+    var options = {
+      distance: 10,
+      containment: [offset.left + containment[0], offset.top + containment[1],
+          offset.left + containment[2], offset.top + containment[3]],
+      axis: handle.data("tobago-split-layout") == "horizontal" ? "x" : "y",
+      start: Tobago.SplitLayout.startDragging,
+      stop: Tobago.SplitLayout.stopDragging
+    };
+    handle.draggable(options)
+  },
+
+  startDragging: function(event, ui) {
+    ui.helper.parent().find("iframe").each(function() {
+      var iframe = jQuery(this);
+      iframe.data("tobago-split-layout-iframe-zindex", iframe.css("z-index"));
+      iframe.css("z-index", "-1");
+    });
+  },
+
+
+  stopDragging: function(event, ui) {
+    ui.helper.parent().find("iframe").each(function() {
+      var iframe = jQuery(this);
+      iframe.css("z-index", iframe.data("tobago-split-layout-iframe-zindex"));
+    });
+    var hidden = ui.helper.children("input");
+    if (ui.helper.data("tobago-split-layout") == "horizontal") {
+      hidden.val(ui.position.left)
+    } else {
+      hidden.val(ui.position.top)
+    }
+    var panel = Tobago.SplitLayout.findParentElementWithId(ui.helper);
+    var clientId = panel.id;
+    //Tobago.reloadComponent(panel, clientId, ui.helper.get(0).id);
+    jsf.ajax.request(
+        ui.helper.get(0).id,
+        event,
+        {
+          //"javax.faces.behavior.event": "click",
+          execute: clientId,
+          render: clientId
+        });
+  },
+
+  findParentElementWithId: function(element) {
+    var parent = element.parent();
+    while (parent.get(0).id === undefined || parent.get(0).id.length == 0) {
+      parent = parent.parent();
+    }
+    return parent.get(0);
+  }
+};
+
+Tobago.registerListener(Tobago.SplitLayout.init, Tobago.Phase.AFTER_UPDATE);
+Tobago.registerListener(Tobago.SplitLayout.init, Tobago.Phase.DOCUMENT_READY);
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/style/tobago.css b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/style/tobago.css
new file mode 100644
index 0000000..763b2c7
--- /dev/null
+++ b/tobago-3.0.x/tobago-extension/tobago-sandbox/src/main/resources/org/apache/myfaces/tobago/sandbox/html/scarborough/standard/style/tobago.css
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* number Slider --------------------------------------------------------------- */
+
+.tobago-numberSlider {
+}
+
+.tobago-numberSlider-min {
+  text-align: left;
+}
+
+.tobago-numberSlider-min {
+  font: bold 11px arial, helvetica, sans-serif;
+}
+
+.tobago-numberSlider-max {
+  text-align: right;
+}
+
+.tobago-numberSlider-max {
+  font: bold 11px arial, helvetica, sans-serif;
+}
+
+.tobago-numberSlider-td {
+}
+
+.tobago-numberSlider-input {
+}
+
+.tobago-numberSlider-slider {
+  width: 100%;
+  height: 3px;
+  background-color: #660000;
+}
+
+.tobago-splitLayout-vertical:hover {
+  cursor: n-resize;
+  border: dotted #000000 thin;
+  /*background-color: blue;*/
+  z-index: 10000;
+}
+
+.tobago-splitLayout-horizontal:hover {
+  cursor: e-resize;
+  border: dotted #000000 thin;
+  /*background-color: blue;*/
+  z-index: 10000;
+}
diff --git a/tobago-3.0.x/tobago-pmd-config.xml b/tobago-3.0.x/tobago-pmd-config.xml
new file mode 100644
index 0000000..0b110cf
--- /dev/null
+++ b/tobago-3.0.x/tobago-pmd-config.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<ruleset name="Custom ruleset"
+    xmlns="http://pmd.sourceforge.net/ruleset/2.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://pmd.sourceforge.net/ruleset/2.0.0 http://pmd.sourceforge.net/ruleset_2_0_0.xsd">
+
+  <!-- TODO: Should this be moved to org.apache.myfaces.buildtools:checkstyle-rules ? -->
+
+  <description>Tobago Code Rules</description>
+
+  <rule ref="rulesets/java/basic.xml"/>
+  <rule ref="rulesets/java/unusedcode.xml"/>
+  <rule ref="rulesets/java/imports.xml"/>
+  <rule ref="rulesets/java/design.xml"/>
+  <rule ref="rulesets/java/optimizations.xml"/>
+  <rule ref="rulesets/java/coupling.xml">
+    <exclude name="LawOfDemeter"/>
+  </rule>
+  <rule ref="rulesets/java/braces.xml"/>
+  <rule ref="rulesets/java/clone.xml"/>
+  <rule ref="rulesets/java/codesize.xml"/>
+  <rule ref="rulesets/java/finalizers.xml"/>
+  <rule ref="rulesets/java/junit.xml"/>
+  <rule ref="rulesets/java/migrating_to_15.xml"/>
+  <rule ref="rulesets/java/typeresolution.xml"/>
+  <rule ref="rulesets/java/strings.xml"/>
+
+<!-- tbd
+  <rule ref="rulesets/java/controversial.xml"/>
+  <rule ref="rulesets/java/logging-java.xml"/>
+  <rule ref="rulesets/java/strictexception.xml"/>
+  <rule ref="rulesets/java/naming.xml"/>
+-->
+
+</ruleset>
diff --git a/tobago-3.0.x/tobago-theme/pom.xml b/tobago-3.0.x/tobago-theme/pom.xml
new file mode 100644
index 0000000..bc5bc07
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/pom.xml
@@ -0,0 +1,236 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <packaging>pom</packaging>
+  <name>Tobago Themes</name>
+  <artifactId>tobago-theme</artifactId>
+
+  <properties>
+    <bootstrap.version>4.0.0-alpha.5</bootstrap.version>
+  </properties>
+
+  <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.codehaus.mojo</groupId>
+          <artifactId>exec-maven-plugin</artifactId>
+          <version>1.4.0</version>
+        </plugin>
+        <plugin>
+          <groupId>net.alchim31.maven</groupId>
+          <artifactId>yuicompressor-maven-plugin</artifactId>
+          <version>1.5.1</version>
+        </plugin>
+      </plugins>
+    </pluginManagement>
+  </build>
+
+  <modules>
+    <module>tobago-theme-standard</module>
+    <!--<module>tobago-theme-scarborough</module>-->
+    <module>tobago-theme-speyside</module>
+    <!--<module>tobago-theme-richmond</module>-->
+    <!--<module>tobago-theme-charlotteville</module>-->
+  </modules>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.core</groupId>
+      <artifactId>myfaces-api</artifactId>
+      <optional>true</optional>
+    </dependency>
+  </dependencies>
+
+  <profiles>
+
+    <profile>
+      <id>all-modules</id>
+      <modules>
+        <module>tobago-theme-scarborough</module>
+        <module>tobago-theme-richmond</module>
+        <module>tobago-theme-charlotteville</module>
+      </modules>
+    </profile>
+
+    <profile>
+      <id>rebuild-theme</id>
+      <build>
+        <plugins>
+
+          <plugin>
+            <artifactId>maven-scm-plugin</artifactId>
+            <version>1.9.5</version>
+            <executions>
+              <execution>
+                <!--load Bootstrap sources via git to target/checkout -->
+                <id>step #1: copy-bootstrap</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>checkout</goal>
+                </goals>
+                <configuration>
+                  <connectionUrl>scm:git:https://github.com/twbs/bootstrap</connectionUrl>
+                  <skipCheckoutIfExists>true</skipCheckoutIfExists>
+                  <scmVersion>v${bootstrap.version}</scmVersion>
+                  <scmVersionType>branch</scmVersionType>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+
+          <plugin>
+            <artifactId>maven-resources-plugin</artifactId>
+            <version>2.7</version>
+            <executions>
+              <execution>
+                <!-- copy Bootstrap to target/bootstrap -->
+                <id>step #2: copy-bootstrap</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy-resources</goal>
+                </goals>
+                <configuration>
+                  <outputDirectory>${project.build.directory}/bootstrap</outputDirectory>
+                  <resources>
+                    <resource>
+                      <directory>${project.build.directory}/checkout</directory>
+                      <exclude>scss/_custom.scss</exclude>
+                    </resource>
+                  </resources>
+                </configuration>
+              </execution>
+              <execution>
+                <!-- copy customization to target/bootstrap -->
+                <id>step #3: copy-custom</id>
+                <phase>generate-resources</phase>
+                <goals>
+                  <goal>copy-resources</goal>
+                </goals>
+                <configuration>
+                  <outputDirectory>${project.build.directory}/bootstrap</outputDirectory>
+                  <resources>
+                    <resource>
+                      <directory>src/main
+                      </directory>
+                      <includes>
+                        <include>scss/*</include>
+                      </includes>
+                    </resource>
+                  </resources>
+                </configuration>
+              </execution>
+              <execution>
+                <!-- copy the result to target/classes -->
+                <id>step #8: copy-bootstrap-dist</id>
+                <phase>process-resources</phase>
+                <goals>
+                  <goal>copy-resources</goal>
+                </goals>
+                <configuration>
+                  <outputDirectory>
+                    ${basedir}/src/main/resources/META-INF/resources/tobago/${theme.name}/bootstrap/${bootstrap.version}
+                  </outputDirectory>
+                  <resources>
+                    <resource>
+                      <directory>${project.build.directory}/bootstrap/dist</directory>
+                    </resource>
+                  </resources>
+                </configuration>
+              </execution>
+            </executions>
+          </plugin>
+
+          <plugin>
+            <groupId>com.github.eirslett</groupId>
+            <artifactId>frontend-maven-plugin</artifactId>
+            <version>1.0</version>
+
+            <!-- optional -->
+            <configuration>
+              <nodeVersion>v6.5.0</nodeVersion>
+              <npmVersion>3.10.8</npmVersion>
+              <!-- optional: where to download node and npm from. Defaults to https://nodejs.org/dist/ -->
+              <!--<downloadRoot>http://myproxy.example.org/nodejs/dist/</downloadRoot>-->
+              <!-- optional: where to install node and npm. Defaults to the working directory -->
+              <installDirectory>${project.build.directory}/frontend</installDirectory>
+              <workingDirectory>${project.build.directory}/bootstrap</workingDirectory>
+            </configuration>
+
+            <executions>
+
+              <execution>
+                <!-- install "node" and "npm" -->
+                <id>step #4: install node and npm</id>
+                <goals>
+                  <goal>install-node-and-npm</goal>
+                </goals>
+                <phase>generate-resources</phase>
+              </execution>
+
+              <execution>
+                <!-- install "grunt-cli" -->
+                <id>step #5: npm install grunt-cli</id>
+                <goals>
+                  <goal>npm</goal>
+                </goals>
+                <phase>generate-resources</phase>
+                <configuration>
+                  <arguments>install grunt-cli</arguments>
+                </configuration>
+              </execution>
+
+              <execution>
+                <!-- install all other required stuff for "bootstrap" -->
+                <id>step #6: npm install</id>
+                <goals>
+                  <goal>npm</goal>
+                </goals>
+                <phase>generate-resources</phase>
+                <configuration>
+                  <arguments>install</arguments>
+                </configuration>
+              </execution>
+
+              <execution>
+                <!-- build "bootstrap" with "grunt" -->
+                <id>step #7: grunt build</id>
+                <goals>
+                  <goal>grunt</goal>
+                </goals>
+                <phase>generate-resources</phase>
+                <configuration>
+                  <arguments>dist</arguments>
+                </configuration>
+              </execution>
+
+            </executions>
+          </plugin>
+
+        </plugins>
+      </build>
+    </profile>
+  </profiles>
+
+</project>
diff --git a/tobago-3.0.x/tobago-theme/rebuild-theme.sh b/tobago-3.0.x/tobago-theme/rebuild-theme.sh
new file mode 100755
index 0000000..6eed660
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/rebuild-theme.sh
@@ -0,0 +1,50 @@
+#!/usr/bin/env bash
+
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# XXX temporary help script. How to call this like:  mvn -P rebuild-theme without the parent?
+
+set -e
+
+# all _tobago.css must be the same. TODO: Later we delete the duplicates...
+
+cp tobago-theme-standard/src/main/scss/_tobago.scss tobago-theme-charlotteville/src/main/scss/_tobago.scss
+cp tobago-theme-standard/src/main/scss/_tobago.scss tobago-theme-richmond/src/main/scss/_tobago.scss
+cp tobago-theme-standard/src/main/scss/_tobago.scss tobago-theme-scarborough/src/main/scss/_tobago.scss
+cp tobago-theme-standard/src/main/scss/_tobago.scss tobago-theme-speyside/src/main/scss/_tobago.scss
+
+mvn -P all-modules clean
+
+mvn -P rebuild-theme -f tobago-theme-charlotteville/pom.xml
+rm tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap-*
+
+mvn -P rebuild-theme -f tobago-theme-richmond/pom.xml
+rm tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap-*
+
+mvn -P rebuild-theme -f tobago-theme-scarborough/pom.xml
+rm tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap-*
+
+mvn -P rebuild-theme -f tobago-theme-speyside/pom.xml
+rm tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap-*
+
+mvn -P rebuild-theme -f tobago-theme-standard/pom.xml
+rm tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap-*
+
+mvn -P all-modules install
+
+echo DONE
+echo Now you will find the bootstrap stuff inside the src trees
+echo use: svn status
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/pom.xml b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/pom.xml
new file mode 100644
index 0000000..706bd7b
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-theme</artifactId>
+    <version>3.0.3-SNAPSHOT</version>
+  </parent>
+  <artifactId>tobago-theme-charlotteville</artifactId>
+  <name>Tobago Theme Charlotteville</name>
+
+  <properties>
+    <theme.name>charlotteville</theme.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-standard</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..b1db76e
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,3 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.css b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.css
new file mode 100644
index 0000000..df273cd
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.css
@@ -0,0 +1,7681 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+/*
+ * theme: standard
+ * agent: standard
+ */
+/* box -------------------------------------------------------------- */
+.tobago-box-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+.tobago-flexLayout {
+  display: -webkit-flex;
+  /* needed e.g. for Safari 8.0.2 */
+  display: -ms-flexbox;
+  /* needed for IE 10 */
+  display: -webkit-box;
+  display: flex;
+  min-width: 0;
+  /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+          flex-direction: column;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  -webkit-box-align: baseline;
+  -webkit-align-items: baseline;
+      -ms-flex-align: baseline;
+          align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  -webkit-box-align: end;
+  -webkit-align-items: flex-end;
+      -ms-flex-align: end;
+          align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  -webkit-box-align: start;
+  -webkit-align-items: flex-start;
+      -ms-flex-align: start;
+          align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  -webkit-box-align: stretch;
+  -webkit-align-items: stretch;
+      -ms-flex-align: stretch;
+          align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  -webkit-box-pack: start;
+  -webkit-justify-content: flex-start;
+      -ms-flex-pack: start;
+          justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd {
+  -webkit-box-pack: end;
+  -webkit-justify-content: flex-end;
+      -ms-flex-pack: end;
+          justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween {
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround {
+  -webkit-justify-content: space-around;
+      -ms-flex-pack: distribute;
+          justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+  box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+.tobago-gridLayout {
+  width: 100%;
+  height: 100%;
+  /*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+  vertical-align: top;
+  padding: 0;
+  border-left: 5px solid transparent;
+  border-top: 5px solid transparent;
+  height: 100%;
+  /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+  border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+  border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+.tobago-header {
+  margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+  margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+.tobago-image-markup-disabled {
+  -webkit-filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+          filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal;
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+.tobago-selectManyShuttle {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  -webkit-flex-shrink: 0;
+      -ms-flex-negative: 0;
+          flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important;
+  /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+
+.tobago-sheet-paging-markup-right {
+  float: right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 1 auto;
+      -ms-flex: 1 1 auto;
+          flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important;
+  /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+  padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+  background-color: #0097CF;
+  color: #FFFFFF;
+  cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+.tobago-tab {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}
+
+.form-horizontal .control-label {
+  margin-top: 10px;
+  margin-bottom: 5px;
+}
+
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content: "*";
+  color: red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
+
+/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */
+html {
+  font-family: sans-serif;
+  line-height: 1.15;
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+}
+
+body {
+  margin: 0;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+  display: block;
+}
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+}
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+progress {
+  vertical-align: baseline;
+}
+
+template,
+[hidden] {
+  display: none;
+}
+
+a {
+  background-color: transparent;
+  -webkit-text-decoration-skip: objects;
+}
+
+a:active,
+a:hover {
+  outline-width: 0;
+}
+
+abbr[title] {
+  border-bottom: none;
+  text-decoration: underline;
+  text-decoration: underline dotted;
+}
+
+b,
+strong {
+  font-weight: inherit;
+}
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+dfn {
+  font-style: italic;
+}
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+
+small {
+  font-size: 80%;
+}
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+img {
+  border-style: none;
+}
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+figure {
+  margin: 1em 40px;
+}
+
+hr {
+  -webkit-box-sizing: content-box;
+          box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font: inherit;
+  margin: 0;
+}
+
+optgroup {
+  font-weight: bold;
+}
+
+button,
+input {
+  overflow: visible;
+}
+
+button,
+select {
+  text-transform: none;
+}
+
+button,
+html [type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+legend {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  color: inherit;
+  display: table;
+  max-width: 100%;
+  padding: 0;
+  white-space: normal;
+}
+
+textarea {
+  overflow: auto;
+}
+
+[type="checkbox"],
+[type="radio"] {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+[type="search"] {
+  -webkit-appearance: textfield;
+  outline-offset: -2px;
+}
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54;
+}
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  font: inherit;
+}
+
+@media print {
+  *,
+  *::before,
+  *::after,
+  *::first-letter,
+  p::first-line,
+  div::first-line,
+  blockquote::first-line,
+  li::first-line {
+    text-shadow: none !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  abbr[title]::after {
+    content: " (" attr(title) ")";
+  }
+  pre {
+    white-space: pre-wrap !important;
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  .navbar {
+    display: none;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .tag {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+
+html {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+  -webkit-box-sizing: inherit;
+          box-sizing: inherit;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+html {
+  font-size: 16px;
+  -ms-overflow-style: scrollbar;
+  -webkit-tap-highlight-color: transparent;
+}
+
+body {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-size: 1rem;
+  line-height: 1.5;
+  color: #373a3c;
+  background-color: #ffeecf;
+}
+
+[tabindex="-1"]:focus {
+  outline: none !important;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 0;
+  margin-bottom: .5rem;
+}
+
+p {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #818a91;
+}
+
+address {
+  margin-bottom: 1rem;
+  font-style: normal;
+  line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+  margin-bottom: 0;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-bottom: .5rem;
+  margin-left: 0;
+}
+
+blockquote {
+  margin: 0 0 1rem;
+}
+
+a {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+a:focus, a:hover {
+  color: #014c8c;
+  text-decoration: underline;
+}
+
+a:focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+a:not([href]):not([tabindex]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus {
+  outline: none;
+}
+
+pre {
+  margin-top: 0;
+  margin-bottom: 1rem;
+  overflow: auto;
+}
+
+figure {
+  margin: 0 0 1rem;
+}
+
+img {
+  vertical-align: middle;
+}
+
+[role="button"] {
+  cursor: pointer;
+}
+
+a,
+area,
+button,
+[role="button"],
+input,
+label,
+select,
+summary,
+textarea {
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+}
+
+table {
+  border-collapse: collapse;
+  background-color: transparent;
+}
+
+caption {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  color: #818a91;
+  text-align: left;
+  caption-side: bottom;
+}
+
+th {
+  text-align: left;
+}
+
+label {
+  display: inline-block;
+  margin-bottom: .5rem;
+}
+
+button:focus {
+  outline: 1px dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+textarea {
+  line-height: inherit;
+}
+
+input[type="radio"]:disabled,
+input[type="checkbox"]:disabled {
+  cursor: not-allowed;
+}
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  -webkit-appearance: listbox;
+}
+
+textarea {
+  resize: vertical;
+}
+
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: .5rem;
+  font-size: 1.5rem;
+  line-height: inherit;
+}
+
+input[type="search"] {
+  -webkit-appearance: none;
+}
+
+output {
+  display: inline-block;
+}
+
+[hidden] {
+  display: none !important;
+}
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  margin-bottom: 0.5rem;
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+
+h1, .h1 {
+  font-size: 2.5rem;
+}
+
+h2, .h2 {
+  font-size: 2rem;
+}
+
+h3, .h3 {
+  font-size: 1.75rem;
+}
+
+h4, .h4 {
+  font-size: 1.5rem;
+}
+
+h5, .h5 {
+  font-size: 1.25rem;
+}
+
+h6, .h6 {
+  font-size: 1rem;
+}
+
+.lead {
+  font-size: 1.25rem;
+  font-weight: 300;
+}
+
+.display-1 {
+  font-size: 6rem;
+  font-weight: 300;
+}
+
+.display-2 {
+  font-size: 5.5rem;
+  font-weight: 300;
+}
+
+.display-3 {
+  font-size: 4.5rem;
+  font-weight: 300;
+}
+
+.display-4 {
+  font-size: 3.5rem;
+  font-weight: 300;
+}
+
+hr {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+small,
+.small {
+  font-size: 80%;
+  font-weight: normal;
+}
+
+mark,
+.mark {
+  padding: 0.2em;
+  background-color: #fcf8e3;
+}
+
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline-item {
+  display: inline-block;
+}
+
+.list-inline-item:not(:last-child) {
+  margin-right: 5px;
+}
+
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+.blockquote {
+  padding: 0.5rem 1rem;
+  margin-bottom: 1rem;
+  font-size: 1.25rem;
+  border-left: 0.25rem solid #eceeef;
+}
+
+.blockquote-footer {
+  display: block;
+  font-size: 80%;
+  color: #818a91;
+}
+
+.blockquote-footer::before {
+  content: "\2014 \00A0";
+}
+
+.blockquote-reverse {
+  padding-right: 1rem;
+  padding-left: 0;
+  text-align: right;
+  border-right: 0.25rem solid #eceeef;
+  border-left: 0;
+}
+
+.blockquote-reverse .blockquote-footer::before {
+  content: "";
+}
+
+.blockquote-reverse .blockquote-footer::after {
+  content: "\00A0 \2014";
+}
+
+dl.row > dd + dt {
+  clear: left;
+}
+
+.img-fluid, .carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  max-width: 100%;
+  height: auto;
+}
+
+.img-thumbnail {
+  padding: 0.25rem;
+  background-color: #ffeecf;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  -webkit-transition: all .2s ease-in-out;
+  -o-transition: all .2s ease-in-out;
+  transition: all .2s ease-in-out;
+  max-width: 100%;
+  height: auto;
+}
+
+.figure {
+  display: inline-block;
+}
+
+.figure-img {
+  margin-bottom: 0.5rem;
+  line-height: 1;
+}
+
+.figure-caption {
+  font-size: 90%;
+  color: #818a91;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+code {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #bd4147;
+  background-color: #f7f7f9;
+  border-radius: 0.25rem;
+}
+
+kbd {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 0.2rem;
+}
+
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: bold;
+}
+
+pre {
+  display: block;
+  margin-top: 0;
+  margin-bottom: 1rem;
+  font-size: 90%;
+  color: #373a3c;
+}
+
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  background-color: transparent;
+  border-radius: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+.container {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .container {
+    width: 540px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 768px) {
+  .container {
+    width: 720px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 992px) {
+  .container {
+    width: 960px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container {
+    width: 1140px;
+    max-width: 100%;
+  }
+}
+
+.container-fluid {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container-fluid::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.row::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+.col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg [...]
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+@media (min-width: 576px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+.col-xs-1 {
+  float: left;
+  width: 8.333333%;
+}
+
+.col-xs-2 {
+  float: left;
+  width: 16.666667%;
+}
+
+.col-xs-3 {
+  float: left;
+  width: 25%;
+}
+
+.col-xs-4 {
+  float: left;
+  width: 33.333333%;
+}
+
+.col-xs-5 {
+  float: left;
+  width: 41.666667%;
+}
+
+.col-xs-6 {
+  float: left;
+  width: 50%;
+}
+
+.col-xs-7 {
+  float: left;
+  width: 58.333333%;
+}
+
+.col-xs-8 {
+  float: left;
+  width: 66.666667%;
+}
+
+.col-xs-9 {
+  float: left;
+  width: 75%;
+}
+
+.col-xs-10 {
+  float: left;
+  width: 83.333333%;
+}
+
+.col-xs-11 {
+  float: left;
+  width: 91.666667%;
+}
+
+.col-xs-12 {
+  float: left;
+  width: 100%;
+}
+
+.pull-xs-0 {
+  right: auto;
+}
+
+.pull-xs-1 {
+  right: 8.333333%;
+}
+
+.pull-xs-2 {
+  right: 16.666667%;
+}
+
+.pull-xs-3 {
+  right: 25%;
+}
+
+.pull-xs-4 {
+  right: 33.333333%;
+}
+
+.pull-xs-5 {
+  right: 41.666667%;
+}
+
+.pull-xs-6 {
+  right: 50%;
+}
+
+.pull-xs-7 {
+  right: 58.333333%;
+}
+
+.pull-xs-8 {
+  right: 66.666667%;
+}
+
+.pull-xs-9 {
+  right: 75%;
+}
+
+.pull-xs-10 {
+  right: 83.333333%;
+}
+
+.pull-xs-11 {
+  right: 91.666667%;
+}
+
+.pull-xs-12 {
+  right: 100%;
+}
+
+.push-xs-0 {
+  left: auto;
+}
+
+.push-xs-1 {
+  left: 8.333333%;
+}
+
+.push-xs-2 {
+  left: 16.666667%;
+}
+
+.push-xs-3 {
+  left: 25%;
+}
+
+.push-xs-4 {
+  left: 33.333333%;
+}
+
+.push-xs-5 {
+  left: 41.666667%;
+}
+
+.push-xs-6 {
+  left: 50%;
+}
+
+.push-xs-7 {
+  left: 58.333333%;
+}
+
+.push-xs-8 {
+  left: 66.666667%;
+}
+
+.push-xs-9 {
+  left: 75%;
+}
+
+.push-xs-10 {
+  left: 83.333333%;
+}
+
+.push-xs-11 {
+  left: 91.666667%;
+}
+
+.push-xs-12 {
+  left: 100%;
+}
+
+.offset-xs-1 {
+  margin-left: 8.333333%;
+}
+
+.offset-xs-2 {
+  margin-left: 16.666667%;
+}
+
+.offset-xs-3 {
+  margin-left: 25%;
+}
+
+.offset-xs-4 {
+  margin-left: 33.333333%;
+}
+
+.offset-xs-5 {
+  margin-left: 41.666667%;
+}
+
+.offset-xs-6 {
+  margin-left: 50%;
+}
+
+.offset-xs-7 {
+  margin-left: 58.333333%;
+}
+
+.offset-xs-8 {
+  margin-left: 66.666667%;
+}
+
+.offset-xs-9 {
+  margin-left: 75%;
+}
+
+.offset-xs-10 {
+  margin-left: 83.333333%;
+}
+
+.offset-xs-11 {
+  margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+  .col-sm-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-sm-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-sm-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-sm-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-sm-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-sm-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-sm-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-sm-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-sm-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-sm-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-sm-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-sm-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-sm-0 {
+    right: auto;
+  }
+  .pull-sm-1 {
+    right: 8.333333%;
+  }
+  .pull-sm-2 {
+    right: 16.666667%;
+  }
+  .pull-sm-3 {
+    right: 25%;
+  }
+  .pull-sm-4 {
+    right: 33.333333%;
+  }
+  .pull-sm-5 {
+    right: 41.666667%;
+  }
+  .pull-sm-6 {
+    right: 50%;
+  }
+  .pull-sm-7 {
+    right: 58.333333%;
+  }
+  .pull-sm-8 {
+    right: 66.666667%;
+  }
+  .pull-sm-9 {
+    right: 75%;
+  }
+  .pull-sm-10 {
+    right: 83.333333%;
+  }
+  .pull-sm-11 {
+    right: 91.666667%;
+  }
+  .pull-sm-12 {
+    right: 100%;
+  }
+  .push-sm-0 {
+    left: auto;
+  }
+  .push-sm-1 {
+    left: 8.333333%;
+  }
+  .push-sm-2 {
+    left: 16.666667%;
+  }
+  .push-sm-3 {
+    left: 25%;
+  }
+  .push-sm-4 {
+    left: 33.333333%;
+  }
+  .push-sm-5 {
+    left: 41.666667%;
+  }
+  .push-sm-6 {
+    left: 50%;
+  }
+  .push-sm-7 {
+    left: 58.333333%;
+  }
+  .push-sm-8 {
+    left: 66.666667%;
+  }
+  .push-sm-9 {
+    left: 75%;
+  }
+  .push-sm-10 {
+    left: 83.333333%;
+  }
+  .push-sm-11 {
+    left: 91.666667%;
+  }
+  .push-sm-12 {
+    left: 100%;
+  }
+  .offset-sm-0 {
+    margin-left: 0%;
+  }
+  .offset-sm-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-sm-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-sm-3 {
+    margin-left: 25%;
+  }
+  .offset-sm-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-sm-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-sm-6 {
+    margin-left: 50%;
+  }
+  .offset-sm-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-sm-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-sm-9 {
+    margin-left: 75%;
+  }
+  .offset-sm-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-sm-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-md-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-md-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-md-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-md-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-md-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-md-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-md-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-md-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-md-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-md-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-md-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-md-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-md-0 {
+    right: auto;
+  }
+  .pull-md-1 {
+    right: 8.333333%;
+  }
+  .pull-md-2 {
+    right: 16.666667%;
+  }
+  .pull-md-3 {
+    right: 25%;
+  }
+  .pull-md-4 {
+    right: 33.333333%;
+  }
+  .pull-md-5 {
+    right: 41.666667%;
+  }
+  .pull-md-6 {
+    right: 50%;
+  }
+  .pull-md-7 {
+    right: 58.333333%;
+  }
+  .pull-md-8 {
+    right: 66.666667%;
+  }
+  .pull-md-9 {
+    right: 75%;
+  }
+  .pull-md-10 {
+    right: 83.333333%;
+  }
+  .pull-md-11 {
+    right: 91.666667%;
+  }
+  .pull-md-12 {
+    right: 100%;
+  }
+  .push-md-0 {
+    left: auto;
+  }
+  .push-md-1 {
+    left: 8.333333%;
+  }
+  .push-md-2 {
+    left: 16.666667%;
+  }
+  .push-md-3 {
+    left: 25%;
+  }
+  .push-md-4 {
+    left: 33.333333%;
+  }
+  .push-md-5 {
+    left: 41.666667%;
+  }
+  .push-md-6 {
+    left: 50%;
+  }
+  .push-md-7 {
+    left: 58.333333%;
+  }
+  .push-md-8 {
+    left: 66.666667%;
+  }
+  .push-md-9 {
+    left: 75%;
+  }
+  .push-md-10 {
+    left: 83.333333%;
+  }
+  .push-md-11 {
+    left: 91.666667%;
+  }
+  .push-md-12 {
+    left: 100%;
+  }
+  .offset-md-0 {
+    margin-left: 0%;
+  }
+  .offset-md-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-md-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-md-3 {
+    margin-left: 25%;
+  }
+  .offset-md-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-md-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-md-6 {
+    margin-left: 50%;
+  }
+  .offset-md-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-md-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-md-9 {
+    margin-left: 75%;
+  }
+  .offset-md-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-md-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-lg-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-lg-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-lg-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-lg-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-lg-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-lg-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-lg-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-lg-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-lg-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-lg-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-lg-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-lg-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-lg-0 {
+    right: auto;
+  }
+  .pull-lg-1 {
+    right: 8.333333%;
+  }
+  .pull-lg-2 {
+    right: 16.666667%;
+  }
+  .pull-lg-3 {
+    right: 25%;
+  }
+  .pull-lg-4 {
+    right: 33.333333%;
+  }
+  .pull-lg-5 {
+    right: 41.666667%;
+  }
+  .pull-lg-6 {
+    right: 50%;
+  }
+  .pull-lg-7 {
+    right: 58.333333%;
+  }
+  .pull-lg-8 {
+    right: 66.666667%;
+  }
+  .pull-lg-9 {
+    right: 75%;
+  }
+  .pull-lg-10 {
+    right: 83.333333%;
+  }
+  .pull-lg-11 {
+    right: 91.666667%;
+  }
+  .pull-lg-12 {
+    right: 100%;
+  }
+  .push-lg-0 {
+    left: auto;
+  }
+  .push-lg-1 {
+    left: 8.333333%;
+  }
+  .push-lg-2 {
+    left: 16.666667%;
+  }
+  .push-lg-3 {
+    left: 25%;
+  }
+  .push-lg-4 {
+    left: 33.333333%;
+  }
+  .push-lg-5 {
+    left: 41.666667%;
+  }
+  .push-lg-6 {
+    left: 50%;
+  }
+  .push-lg-7 {
+    left: 58.333333%;
+  }
+  .push-lg-8 {
+    left: 66.666667%;
+  }
+  .push-lg-9 {
+    left: 75%;
+  }
+  .push-lg-10 {
+    left: 83.333333%;
+  }
+  .push-lg-11 {
+    left: 91.666667%;
+  }
+  .push-lg-12 {
+    left: 100%;
+  }
+  .offset-lg-0 {
+    margin-left: 0%;
+  }
+  .offset-lg-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-lg-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-lg-3 {
+    margin-left: 25%;
+  }
+  .offset-lg-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-lg-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-lg-6 {
+    margin-left: 50%;
+  }
+  .offset-lg-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-lg-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-lg-9 {
+    margin-left: 75%;
+  }
+  .offset-lg-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-lg-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xl-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-xl-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-xl-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-xl-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-xl-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-xl-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-xl-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-xl-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-xl-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-xl-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-xl-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-xl-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-xl-0 {
+    right: auto;
+  }
+  .pull-xl-1 {
+    right: 8.333333%;
+  }
+  .pull-xl-2 {
+    right: 16.666667%;
+  }
+  .pull-xl-3 {
+    right: 25%;
+  }
+  .pull-xl-4 {
+    right: 33.333333%;
+  }
+  .pull-xl-5 {
+    right: 41.666667%;
+  }
+  .pull-xl-6 {
+    right: 50%;
+  }
+  .pull-xl-7 {
+    right: 58.333333%;
+  }
+  .pull-xl-8 {
+    right: 66.666667%;
+  }
+  .pull-xl-9 {
+    right: 75%;
+  }
+  .pull-xl-10 {
+    right: 83.333333%;
+  }
+  .pull-xl-11 {
+    right: 91.666667%;
+  }
+  .pull-xl-12 {
+    right: 100%;
+  }
+  .push-xl-0 {
+    left: auto;
+  }
+  .push-xl-1 {
+    left: 8.333333%;
+  }
+  .push-xl-2 {
+    left: 16.666667%;
+  }
+  .push-xl-3 {
+    left: 25%;
+  }
+  .push-xl-4 {
+    left: 33.333333%;
+  }
+  .push-xl-5 {
+    left: 41.666667%;
+  }
+  .push-xl-6 {
+    left: 50%;
+  }
+  .push-xl-7 {
+    left: 58.333333%;
+  }
+  .push-xl-8 {
+    left: 66.666667%;
+  }
+  .push-xl-9 {
+    left: 75%;
+  }
+  .push-xl-10 {
+    left: 83.333333%;
+  }
+  .push-xl-11 {
+    left: 91.666667%;
+  }
+  .push-xl-12 {
+    left: 100%;
+  }
+  .offset-xl-0 {
+    margin-left: 0%;
+  }
+  .offset-xl-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-xl-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-xl-3 {
+    margin-left: 25%;
+  }
+  .offset-xl-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-xl-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-xl-6 {
+    margin-left: 50%;
+  }
+  .offset-xl-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-xl-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-xl-9 {
+    margin-left: 75%;
+  }
+  .offset-xl-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-xl-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 1rem;
+}
+
+.table th,
+.table td {
+  padding: 0.75rem;
+  vertical-align: top;
+  border-top: 1px solid #eceeef;
+}
+
+.table thead th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #eceeef;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #eceeef;
+}
+
+.table .table {
+  background-color: #ffeecf;
+}
+
+.table-sm th,
+.table-sm td {
+  padding: 0.3rem;
+}
+
+.table-bordered {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered thead th,
+.table-bordered thead td {
+  border-bottom-width: 2px;
+}
+
+.table-striped tbody tr:nth-of-type(odd) {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+
+.table-hover tbody tr:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-active,
+.table-active > th,
+.table-active > td {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover > td,
+.table-hover .table-active:hover > th {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-success,
+.table-success > th,
+.table-success > td {
+  background-color: #dff0d8;
+}
+
+.table-hover .table-success:hover {
+  background-color: #d0e9c6;
+}
+
+.table-hover .table-success:hover > td,
+.table-hover .table-success:hover > th {
+  background-color: #d0e9c6;
+}
+
+.table-info,
+.table-info > th,
+.table-info > td {
+  background-color: #d9edf7;
+}
+
+.table-hover .table-info:hover {
+  background-color: #c4e3f3;
+}
+
+.table-hover .table-info:hover > td,
+.table-hover .table-info:hover > th {
+  background-color: #c4e3f3;
+}
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+  background-color: #fcf8e3;
+}
+
+.table-hover .table-warning:hover {
+  background-color: #faf2cc;
+}
+
+.table-hover .table-warning:hover > td,
+.table-hover .table-warning:hover > th {
+  background-color: #faf2cc;
+}
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+  background-color: #f2dede;
+}
+
+.table-hover .table-danger:hover {
+  background-color: #ebcccc;
+}
+
+.table-hover .table-danger:hover > td,
+.table-hover .table-danger:hover > th {
+  background-color: #ebcccc;
+}
+
+.thead-inverse th {
+  color: #fff;
+  background-color: #373a3c;
+}
+
+.thead-default th {
+  color: #55595c;
+  background-color: #eceeef;
+}
+
+.table-inverse {
+  color: #eceeef;
+  background-color: #373a3c;
+}
+
+.table-inverse th,
+.table-inverse td,
+.table-inverse thead th {
+  border-color: #55595c;
+}
+
+.table-inverse.table-bordered {
+  border: 0;
+}
+
+.table-responsive {
+  display: block;
+  width: 100%;
+  min-height: 0%;
+  overflow-x: auto;
+}
+
+.table-reflow thead {
+  float: left;
+}
+
+.table-reflow tbody {
+  display: block;
+  white-space: nowrap;
+}
+
+.table-reflow th,
+.table-reflow td {
+  border-top: 1px solid #eceeef;
+  border-left: 1px solid #eceeef;
+}
+
+.table-reflow th:last-child,
+.table-reflow td:last-child {
+  border-right: 1px solid #eceeef;
+}
+
+.table-reflow thead:last-child tr:last-child th,
+.table-reflow thead:last-child tr:last-child td,
+.table-reflow tbody:last-child tr:last-child th,
+.table-reflow tbody:last-child tr:last-child td,
+.table-reflow tfoot:last-child tr:last-child th,
+.table-reflow tfoot:last-child tr:last-child td {
+  border-bottom: 1px solid #eceeef;
+}
+
+.table-reflow tr {
+  float: left;
+}
+
+.table-reflow tr th,
+.table-reflow tr td {
+  display: block !important;
+  border: 1px solid #eceeef;
+}
+
+.form-control {
+  display: block;
+  width: 100%;
+  padding: 0.5rem 0.75rem;
+  font-size: 1rem;
+  line-height: 1.25;
+  color: #55595c;
+  background-color: #fff;
+  background-image: none;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.form-control::-ms-expand {
+  background-color: transparent;
+  border: 0;
+}
+
+.form-control:focus {
+  color: #55595c;
+  background-color: #fff;
+  border-color: #66afe9;
+  outline: none;
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::-moz-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:disabled, .form-control[readonly] {
+  background-color: #eceeef;
+  opacity: 1;
+}
+
+.form-control:disabled {
+  cursor: not-allowed;
+}
+
+select.form-control:not([size]):not([multiple]) {
+  height: calc(2.5rem - 2px);
+}
+
+select.form-control:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.form-control-file,
+.form-control-range {
+  display: block;
+}
+
+.col-form-label {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+}
+
+.col-form-label-lg {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  font-size: 1.25rem;
+}
+
+.col-form-label-sm {
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  font-size: 0.875rem;
+}
+
+.col-form-legend {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+}
+
+.form-control-static {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  line-height: 1.25;
+  border: solid transparent;
+  border-width: 1px 0;
+}
+
+.form-control-static.form-control-sm, .input-group-sm > .form-control-static.form-control,
+.input-group-sm > .form-control-static.input-group-addon,
+.input-group-sm > .input-group-btn > .form-control-static.btn, .form-control-static.form-control-lg, .input-group-lg > .form-control-static.form-control,
+.input-group-lg > .form-control-static.input-group-addon,
+.input-group-lg > .input-group-btn > .form-control-static.btn {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.form-control-sm, .input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),
+.input-group-sm > select.input-group-addon:not([size]):not([multiple]),
+.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 1.8125rem;
+}
+
+.form-control-lg, .input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),
+.input-group-lg > select.input-group-addon:not([size]):not([multiple]),
+.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 3.166667rem;
+}
+
+.form-group {
+  margin-bottom: 1rem;
+}
+
+.form-text {
+  display: block;
+  margin-top: 0.25rem;
+}
+
+.form-check {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+}
+
+.form-check + .form-check {
+  margin-top: -.25rem;
+}
+
+.form-check.disabled .form-check-label {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-check-label {
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  cursor: pointer;
+}
+
+.form-check-input {
+  position: absolute;
+  margin-top: .25rem;
+  margin-left: -1.25rem;
+}
+
+.form-check-input:only-child {
+  position: static;
+}
+
+.form-check-inline {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  vertical-align: middle;
+  cursor: pointer;
+}
+
+.form-check-inline + .form-check-inline {
+  margin-left: .75rem;
+}
+
+.form-check-inline.disabled {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-control-feedback {
+  margin-top: 0.25rem;
+}
+
+.form-control-success,
+.form-control-warning,
+.form-control-danger {
+  padding-right: 2.25rem;
+  background-repeat: no-repeat;
+  background-position: center right 0.625rem;
+  -webkit-background-size: 1.25rem 1.25rem;
+          background-size: 1.25rem 1.25rem;
+}
+
+.has-success .form-control-feedback,
+.has-success .form-control-label,
+.has-success .form-check-label,
+.has-success .form-check-inline,
+.has-success .custom-control {
+  color: #5cb85c;
+}
+
+.has-success .form-control {
+  border-color: #5cb85c;
+}
+
+.has-success .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+}
+
+.has-success .input-group-addon {
+  color: #5cb85c;
+  border-color: #5cb85c;
+  background-color: #eaf6ea;
+}
+
+.has-success .form-control-success {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#5cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");
+}
+
+.has-warning .form-control-feedback,
+.has-warning .form-control-label,
+.has-warning .form-check-label,
+.has-warning .form-check-inline,
+.has-warning .custom-control {
+  color: #f0ad4e;
+}
+
+.has-warning .form-control {
+  border-color: #f0ad4e;
+}
+
+.has-warning .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+}
+
+.has-warning .input-group-addon {
+  color: #f0ad4e;
+  border-color: #f0ad4e;
+  background-color: white;
+}
+
+.has-warning .form-control-warning {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E");
+}
+
+.has-danger .form-control-feedback,
+.has-danger .form-control-label,
+.has-danger .form-check-label,
+.has-danger .form-check-inline,
+.has-danger .custom-control {
+  color: #d9534f;
+}
+
+.has-danger .form-control {
+  border-color: #d9534f;
+}
+
+.has-danger .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+}
+
+.has-danger .input-group-addon {
+  color: #d9534f;
+  border-color: #d9534f;
+  background-color: #fdf7f7;
+}
+
+.has-danger .form-control-danger {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E");
+}
+
+@media (min-width: 576px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-static {
+    display: inline-block;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .form-control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check-label {
+    padding-left: 0;
+  }
+  .form-inline .form-check-input {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+
+.btn {
+  display: inline-block;
+  font-weight: normal;
+  line-height: 1.25;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  border: 1px solid transparent;
+  padding: 0.5rem 1rem;
+  font-size: 1rem;
+  border-radius: 0.25rem;
+}
+
+.btn:focus, .btn.focus, .btn:active:focus, .btn:active.focus, .btn.active:focus, .btn.active.focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn:focus, .btn:hover {
+  text-decoration: none;
+}
+
+.btn.focus {
+  text-decoration: none;
+}
+
+.btn:active, .btn.active {
+  background-image: none;
+  outline: 0;
+}
+
+.btn.disabled, .btn:disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+a.btn.disabled,
+fieldset[disabled] a.btn {
+  pointer-events: none;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary:hover {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:focus, .btn-primary.focus {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:active, .btn-primary.active,
+.open > .btn-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+  background-image: none;
+}
+
+.btn-primary:active:hover, .btn-primary:active:focus, .btn-primary:active.focus, .btn-primary.active:hover, .btn-primary.active:focus, .btn-primary.active.focus,
+.open > .btn-primary.dropdown-toggle:hover,
+.open > .btn-primary.dropdown-toggle:focus,
+.open > .btn-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary:disabled:focus, .btn-primary:disabled.focus {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary.disabled:hover, .btn-primary:disabled:hover {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-secondary {
+  color: #373a3c;
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary:hover {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:focus, .btn-secondary.focus {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:active, .btn-secondary.active,
+.open > .btn-secondary.dropdown-toggle {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+  background-image: none;
+}
+
+.btn-secondary:active:hover, .btn-secondary:active:focus, .btn-secondary:active.focus, .btn-secondary.active:hover, .btn-secondary.active:focus, .btn-secondary.active.focus,
+.open > .btn-secondary.dropdown-toggle:hover,
+.open > .btn-secondary.dropdown-toggle:focus,
+.open > .btn-secondary.dropdown-toggle.focus {
+  color: #373a3c;
+  background-color: #d4d4d4;
+  border-color: #8c8c8c;
+}
+
+.btn-secondary.disabled:focus, .btn-secondary.disabled.focus, .btn-secondary:disabled:focus, .btn-secondary:disabled.focus {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary.disabled:hover, .btn-secondary:disabled:hover {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-info {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info:hover {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:focus, .btn-info.focus {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:active, .btn-info.active,
+.open > .btn-info.dropdown-toggle {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+  background-image: none;
+}
+
+.btn-info:active:hover, .btn-info:active:focus, .btn-info:active.focus, .btn-info.active:hover, .btn-info.active:focus, .btn-info.active.focus,
+.open > .btn-info.dropdown-toggle:hover,
+.open > .btn-info.dropdown-toggle:focus,
+.open > .btn-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info:disabled:focus, .btn-info:disabled.focus {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info.disabled:hover, .btn-info:disabled:hover {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-success {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success:hover {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:focus, .btn-success.focus {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:active, .btn-success.active,
+.open > .btn-success.dropdown-toggle {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+  background-image: none;
+}
+
+.btn-success:active:hover, .btn-success:active:focus, .btn-success:active.focus, .btn-success.active:hover, .btn-success.active:focus, .btn-success.active.focus,
+.open > .btn-success.dropdown-toggle:hover,
+.open > .btn-success.dropdown-toggle:focus,
+.open > .btn-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success:disabled:focus, .btn-success:disabled.focus {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success.disabled:hover, .btn-success:disabled:hover {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-warning {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning:hover {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:focus, .btn-warning.focus {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:active, .btn-warning.active,
+.open > .btn-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+  background-image: none;
+}
+
+.btn-warning:active:hover, .btn-warning:active:focus, .btn-warning:active.focus, .btn-warning.active:hover, .btn-warning.active:focus, .btn-warning.active.focus,
+.open > .btn-warning.dropdown-toggle:hover,
+.open > .btn-warning.dropdown-toggle:focus,
+.open > .btn-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning:disabled:focus, .btn-warning:disabled.focus {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning.disabled:hover, .btn-warning:disabled:hover {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-danger {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger:hover {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:focus, .btn-danger.focus {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:active, .btn-danger.active,
+.open > .btn-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+  background-image: none;
+}
+
+.btn-danger:active:hover, .btn-danger:active:focus, .btn-danger:active.focus, .btn-danger.active:hover, .btn-danger.active:focus, .btn-danger.active.focus,
+.open > .btn-danger.dropdown-toggle:hover,
+.open > .btn-danger.dropdown-toggle:focus,
+.open > .btn-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger:disabled:focus, .btn-danger:disabled.focus {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger.disabled:hover, .btn-danger:disabled:hover {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-primary {
+  color: #0275d8;
+  background-image: none;
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:hover {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:focus, .btn-outline-primary.focus {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active, .btn-outline-primary.active,
+.open > .btn-outline-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active:hover, .btn-outline-primary:active:focus, .btn-outline-primary:active.focus, .btn-outline-primary.active:hover, .btn-outline-primary.active:focus, .btn-outline-primary.active.focus,
+.open > .btn-outline-primary.dropdown-toggle:hover,
+.open > .btn-outline-primary.dropdown-toggle:focus,
+.open > .btn-outline-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-outline-primary.disabled:focus, .btn-outline-primary.disabled.focus, .btn-outline-primary:disabled:focus, .btn-outline-primary:disabled.focus {
+  border-color: #43a7fd;
+}
+
+.btn-outline-primary.disabled:hover, .btn-outline-primary:disabled:hover {
+  border-color: #43a7fd;
+}
+
+.btn-outline-secondary {
+  color: #ccc;
+  background-image: none;
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:hover {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:focus, .btn-outline-secondary.focus {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active, .btn-outline-secondary.active,
+.open > .btn-outline-secondary.dropdown-toggle {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active:hover, .btn-outline-secondary:active:focus, .btn-outline-secondary:active.focus, .btn-outline-secondary.active:hover, .btn-outline-secondary.active:focus, .btn-outline-secondary.active.focus,
+.open > .btn-outline-secondary.dropdown-toggle:hover,
+.open > .btn-outline-secondary.dropdown-toggle:focus,
+.open > .btn-outline-secondary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #a1a1a1;
+  border-color: #8c8c8c;
+}
+
+.btn-outline-secondary.disabled:focus, .btn-outline-secondary.disabled.focus, .btn-outline-secondary:disabled:focus, .btn-outline-secondary:disabled.focus {
+  border-color: white;
+}
+
+.btn-outline-secondary.disabled:hover, .btn-outline-secondary:disabled:hover {
+  border-color: white;
+}
+
+.btn-outline-info {
+  color: #5bc0de;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:hover {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:focus, .btn-outline-info.focus {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active, .btn-outline-info.active,
+.open > .btn-outline-info.dropdown-toggle {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active:hover, .btn-outline-info:active:focus, .btn-outline-info:active.focus, .btn-outline-info.active:hover, .btn-outline-info.active:focus, .btn-outline-info.active.focus,
+.open > .btn-outline-info.dropdown-toggle:hover,
+.open > .btn-outline-info.dropdown-toggle:focus,
+.open > .btn-outline-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-outline-info.disabled:focus, .btn-outline-info.disabled.focus, .btn-outline-info:disabled:focus, .btn-outline-info:disabled.focus {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-info.disabled:hover, .btn-outline-info:disabled:hover {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-success {
+  color: #5cb85c;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:hover {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:focus, .btn-outline-success.focus {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active, .btn-outline-success.active,
+.open > .btn-outline-success.dropdown-toggle {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active:hover, .btn-outline-success:active:focus, .btn-outline-success:active.focus, .btn-outline-success.active:hover, .btn-outline-success.active:focus, .btn-outline-success.active.focus,
+.open > .btn-outline-success.dropdown-toggle:hover,
+.open > .btn-outline-success.dropdown-toggle:focus,
+.open > .btn-outline-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-outline-success.disabled:focus, .btn-outline-success.disabled.focus, .btn-outline-success:disabled:focus, .btn-outline-success:disabled.focus {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-success.disabled:hover, .btn-outline-success:disabled:hover {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-warning {
+  color: #f0ad4e;
+  background-image: none;
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:hover {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:focus, .btn-outline-warning.focus {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active, .btn-outline-warning.active,
+.open > .btn-outline-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active:hover, .btn-outline-warning:active:focus, .btn-outline-warning:active.focus, .btn-outline-warning.active:hover, .btn-outline-warning.active:focus, .btn-outline-warning.active.focus,
+.open > .btn-outline-warning.dropdown-toggle:hover,
+.open > .btn-outline-warning.dropdown-toggle:focus,
+.open > .btn-outline-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-outline-warning.disabled:focus, .btn-outline-warning.disabled.focus, .btn-outline-warning:disabled:focus, .btn-outline-warning:disabled.focus {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-warning.disabled:hover, .btn-outline-warning:disabled:hover {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-danger {
+  color: #d9534f;
+  background-image: none;
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:hover {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:focus, .btn-outline-danger.focus {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active, .btn-outline-danger.active,
+.open > .btn-outline-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active:hover, .btn-outline-danger:active:focus, .btn-outline-danger:active.focus, .btn-outline-danger.active:hover, .btn-outline-danger.active:focus, .btn-outline-danger.active.focus,
+.open > .btn-outline-danger.dropdown-toggle:hover,
+.open > .btn-outline-danger.dropdown-toggle:focus,
+.open > .btn-outline-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-outline-danger.disabled:focus, .btn-outline-danger.disabled.focus, .btn-outline-danger:disabled:focus, .btn-outline-danger:disabled.focus {
+  border-color: #eba5a3;
+}
+
+.btn-outline-danger.disabled:hover, .btn-outline-danger:disabled:hover {
+  border-color: #eba5a3;
+}
+
+.btn-link {
+  font-weight: normal;
+  color: #0275d8;
+  border-radius: 0;
+}
+
+.btn-link, .btn-link:active, .btn-link.active, .btn-link:disabled {
+  background-color: transparent;
+}
+
+.btn-link, .btn-link:focus, .btn-link:active {
+  border-color: transparent;
+}
+
+.btn-link:hover {
+  border-color: transparent;
+}
+
+.btn-link:focus, .btn-link:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link:disabled:focus, .btn-link:disabled:hover {
+  color: #818a91;
+  text-decoration: none;
+}
+
+.btn-lg, .btn-group-lg > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.btn-sm, .btn-group-sm > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+}
+
+.btn-block + .btn-block {
+  margin-top: 0.5rem;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+  -o-transition: opacity .15s linear;
+  transition: opacity .15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  display: none;
+}
+
+.collapse.in {
+  display: block;
+}
+
+tr.collapse.in {
+  display: table-row;
+}
+
+tbody.collapse.in {
+  display: table-row-group;
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition-timing-function: ease;
+       -o-transition-timing-function: ease;
+          transition-timing-function: ease;
+  -webkit-transition-duration: .35s;
+       -o-transition-duration: .35s;
+          transition-duration: .35s;
+  -webkit-transition-property: height;
+  -o-transition-property: height;
+  transition-property: height;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.3em;
+  vertical-align: middle;
+  content: "";
+  border-top: 0.3em solid;
+  border-right: 0.3em solid transparent;
+  border-left: 0.3em solid transparent;
+}
+
+.dropdown-toggle:focus {
+  outline: 0;
+}
+
+.dropup .dropdown-toggle::after {
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 10rem;
+  padding: 0.5rem 0;
+  margin: 0.125rem 0 0;
+  font-size: 1rem;
+  color: #373a3c;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.dropdown-divider {
+  height: 1px;
+  margin: 0.5rem 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+
+.dropdown-item {
+  display: block;
+  width: 100%;
+  padding: 3px 1.5rem;
+  clear: both;
+  font-weight: normal;
+  color: #373a3c;
+  text-align: inherit;
+  white-space: nowrap;
+  background: none;
+  border: 0;
+}
+
+.dropdown-item:focus, .dropdown-item:hover {
+  color: #2b2d2f;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.dropdown-item.active, .dropdown-item.active:focus, .dropdown-item.active:hover {
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  outline: 0;
+}
+
+.dropdown-item.disabled, .dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  color: #818a91;
+}
+
+.dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: "progid:DXImageTransform.Microsoft.gradient(enabled = false)";
+}
+
+.open > .dropdown-menu {
+  display: block;
+}
+
+.open > a {
+  outline: 0;
+}
+
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+
+.dropdown-header {
+  display: block;
+  padding: 0.5rem 1.5rem;
+  margin-bottom: 0;
+  font-size: 0.875rem;
+  color: #818a91;
+  white-space: nowrap;
+}
+
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 0.125rem;
+}
+
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+  margin-bottom: 0;
+}
+
+.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+.btn-group-vertical > .btn:focus,
+.btn-group-vertical > .btn:active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover {
+  z-index: 2;
+}
+
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+
+.btn-toolbar {
+  margin-left: -0.5rem;
+}
+
+.btn-toolbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 0.5rem;
+}
+
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group > .btn-group {
+  float: left;
+}
+
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+.btn + .dropdown-toggle-split {
+  padding-right: 0.75rem;
+  padding-left: 0.75rem;
+}
+
+.btn + .dropdown-toggle-split::after {
+  margin-left: 0;
+}
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+  padding-right: 0.375rem;
+  padding-left: 0.375rem;
+}
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+  padding-right: 1.125rem;
+  padding-left: 1.125rem;
+}
+
+.btn .caret {
+  margin-left: 0;
+}
+
+.btn-lg .caret, .btn-group-lg > .btn .caret {
+  border-width: 0.3em 0.3em 0;
+  border-bottom-width: 0;
+}
+
+.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret {
+  border-width: 0 0.3em 0.3em;
+}
+
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+
+.btn-group-vertical > .btn-group::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+  position: absolute;
+  clip: rect(0, 0, 0, 0);
+  pointer-events: none;
+}
+
+.input-group {
+  position: relative;
+  width: 100%;
+  display: table;
+  border-collapse: separate;
+}
+
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+
+.input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {
+  z-index: 3;
+}
+
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+
+.input-group-addon {
+  padding: 0.5rem 0.75rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+  font-weight: normal;
+  line-height: 1.25;
+  color: #55595c;
+  text-align: center;
+  background-color: #eceeef;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.input-group-addon.form-control-sm,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .input-group-addon.btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.input-group-addon.form-control-lg,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .input-group-addon.btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+
+.input-group .form-control:not(:last-child),
+.input-group-addon:not(:last-child),
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group > .btn,
+.input-group-btn:not(:last-child) > .dropdown-toggle,
+.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.input-group-addon:not(:last-child) {
+  border-right: 0;
+}
+
+.input-group .form-control:not(:first-child),
+.input-group-addon:not(:first-child),
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group > .btn,
+.input-group-btn:not(:first-child) > .dropdown-toggle,
+.input-group-btn:not(:last-child) > .btn:not(:first-child),
+.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.form-control + .input-group-addon:not(:first-child) {
+  border-left: 0;
+}
+
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+
+.input-group-btn > .btn {
+  position: relative;
+}
+
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+
+.input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {
+  z-index: 3;
+}
+
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group {
+  margin-right: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group {
+  z-index: 2;
+  margin-left: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,
+.input-group-btn:not(:first-child) > .btn-group:focus,
+.input-group-btn:not(:first-child) > .btn-group:active,
+.input-group-btn:not(:first-child) > .btn-group:hover {
+  z-index: 3;
+}
+
+.custom-control {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.5rem;
+  cursor: pointer;
+}
+
+.custom-control + .custom-control {
+  margin-left: 1rem;
+}
+
+.custom-control-input {
+  position: absolute;
+  z-index: -1;
+  opacity: 0;
+}
+
+.custom-control-input:checked ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #0074d9;
+}
+
+.custom-control-input:focus ~ .custom-control-indicator {
+  -webkit-box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+          box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+}
+
+.custom-control-input:active ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #84c6ff;
+}
+
+.custom-control-input:disabled ~ .custom-control-indicator {
+  cursor: not-allowed;
+  background-color: #eee;
+}
+
+.custom-control-input:disabled ~ .custom-control-description {
+  color: #767676;
+  cursor: not-allowed;
+}
+
+.custom-control-indicator {
+  position: absolute;
+  top: .25rem;
+  left: 0;
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  pointer-events: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #ddd;
+  background-repeat: no-repeat;
+  background-position: center center;
+  -webkit-background-size: 50% 50%;
+          background-size: 50% 50%;
+}
+
+.custom-checkbox .custom-control-indicator {
+  border-radius: 0.25rem;
+}
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
+}
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {
+  background-color: #0074d9;
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#fff' d='M0 2h4'/%3E%3C/svg%3E");
+}
+
+.custom-radio .custom-control-indicator {
+  border-radius: 50%;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#fff'/%3E%3C/svg%3E");
+}
+
+.custom-controls-stacked .custom-control {
+  float: left;
+  clear: left;
+}
+
+.custom-controls-stacked .custom-control + .custom-control {
+  margin-left: 0;
+}
+
+.custom-select {
+  display: inline-block;
+  max-width: 100%;
+  height: calc(2.5rem - 2px);
+  padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+  padding-right: 0.75rem \9;
+  color: #55595c;
+  vertical-align: middle;
+  background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;
+  background-image: none \9;
+  -webkit-background-size: 8px 10px;
+          background-size: 8px 10px;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+  -moz-appearance: none;
+  -webkit-appearance: none;
+}
+
+.custom-select:focus {
+  border-color: #51a7e8;
+  outline: none;
+}
+
+.custom-select:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.custom-select:disabled {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.custom-select::-ms-expand {
+  opacity: 0;
+}
+
+.custom-select-sm {
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  font-size: 75%;
+}
+
+.custom-file {
+  position: relative;
+  display: inline-block;
+  max-width: 100%;
+  height: 2.5rem;
+  cursor: pointer;
+}
+
+.custom-file-input {
+  min-width: 14rem;
+  max-width: 100%;
+  margin: 0;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+
+.custom-file-control {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 5;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+}
+
+.custom-file-control:lang(en)::after {
+  content: "Choose file...";
+}
+
+.custom-file-control::before {
+  position: absolute;
+  top: -1px;
+  right: -1px;
+  bottom: -1px;
+  z-index: 6;
+  display: block;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  background-color: #eee;
+  border: 1px solid #ddd;
+  border-radius: 0 0.25rem 0.25rem 0;
+}
+
+.custom-file-control:lang(en)::before {
+  content: "Browse";
+}
+
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.nav-link {
+  display: inline-block;
+}
+
+.nav-link:focus, .nav-link:hover {
+  text-decoration: none;
+}
+
+.nav-link.disabled {
+  color: #818a91;
+}
+
+.nav-link.disabled, .nav-link.disabled:focus, .nav-link.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+
+.nav-inline .nav-item {
+  display: inline-block;
+}
+
+.nav-inline .nav-item + .nav-item,
+.nav-inline .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-tabs .nav-item {
+  float: left;
+  margin-bottom: -1px;
+}
+
+.nav-tabs .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-tabs .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border: 1px solid transparent;
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover {
+  border-color: #eceeef #eceeef #ddd;
+}
+
+.nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:focus, .nav-tabs .nav-link.disabled:hover {
+  color: #818a91;
+  background-color: transparent;
+  border-color: transparent;
+}
+
+.nav-tabs .nav-link.active, .nav-tabs .nav-link.active:focus, .nav-tabs .nav-link.active:hover,
+.nav-tabs .nav-item.open .nav-link,
+.nav-tabs .nav-item.open .nav-link:focus,
+.nav-tabs .nav-item.open .nav-link:hover {
+  color: #55595c;
+  background-color: #ffeecf;
+  border-color: #ddd #ddd transparent;
+}
+
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.nav-pills::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-pills .nav-item {
+  float: left;
+}
+
+.nav-pills .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-pills .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border-radius: 0.25rem;
+}
+
+.nav-pills .nav-link.active, .nav-pills .nav-link.active:focus, .nav-pills .nav-link.active:hover,
+.nav-pills .nav-item.open .nav-link,
+.nav-pills .nav-item.open .nav-link:focus,
+.nav-pills .nav-item.open .nav-link:hover {
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+}
+
+.nav-stacked .nav-item {
+  display: block;
+  float: none;
+}
+
+.nav-stacked .nav-item + .nav-item {
+  margin-top: 0.2rem;
+  margin-left: 0;
+}
+
+.tab-content > .tab-pane {
+  display: none;
+}
+
+.tab-content > .active {
+  display: block;
+}
+
+.navbar {
+  position: relative;
+  padding: 0.5rem 1rem;
+}
+
+.navbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .navbar {
+    border-radius: 0.25rem;
+  }
+}
+
+.navbar-full {
+  z-index: 1000;
+}
+
+@media (min-width: 576px) {
+  .navbar-full {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+@media (min-width: 576px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top {
+  top: 0;
+}
+
+.navbar-fixed-bottom {
+  bottom: 0;
+}
+
+.navbar-sticky-top {
+  position: -webkit-sticky;
+  position: sticky;
+  top: 0;
+  z-index: 1030;
+  width: 100%;
+}
+
+@media (min-width: 576px) {
+  .navbar-sticky-top {
+    border-radius: 0;
+  }
+}
+
+.navbar-brand {
+  float: left;
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  margin-right: 1rem;
+  font-size: 1.25rem;
+  line-height: inherit;
+}
+
+.navbar-brand:focus, .navbar-brand:hover {
+  text-decoration: none;
+}
+
+.navbar-divider {
+  float: left;
+  width: 1px;
+  padding-top: 0.425rem;
+  padding-bottom: 0.425rem;
+  margin-right: 1rem;
+  margin-left: 1rem;
+  overflow: hidden;
+}
+
+.navbar-divider::before {
+  content: "\00a0";
+}
+
+.navbar-text {
+  display: inline-block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-toggler {
+  width: 2.5em;
+  height: 2em;
+  padding: 0.5rem 0.75rem;
+  font-size: 1.25rem;
+  line-height: 1;
+  background: transparent no-repeat center center;
+  -webkit-background-size: 24px 24px;
+          background-size: 24px 24px;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.navbar-toggler:focus, .navbar-toggler:hover {
+  text-decoration: none;
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-xs .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-xs .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-sm .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-sm .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-md .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-md .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block;
+  }
+}
+
+.navbar-toggleable-lg::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 1199px) {
+  .navbar-toggleable-lg .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-lg .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-lg .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 1200px) {
+  .navbar-toggleable-lg {
+    display: block;
+  }
+}
+
+.navbar-toggleable-xl {
+  display: block;
+}
+
+.navbar-toggleable-xl::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.navbar-toggleable-xl .navbar-brand {
+  display: block;
+  float: none;
+  margin-top: .5rem;
+  margin-right: 0;
+}
+
+.navbar-toggleable-xl .navbar-nav {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+
+.navbar-toggleable-xl .navbar-nav .dropdown-menu {
+  position: static;
+  float: none;
+}
+
+.navbar-nav .nav-item {
+  float: left;
+}
+
+.navbar-nav .nav-link {
+  display: block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-nav .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.navbar-nav .nav-item + .nav-item {
+  margin-left: 1rem;
+}
+
+.navbar-light .navbar-brand,
+.navbar-light .navbar-toggler {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover,
+.navbar-light .navbar-toggler:focus,
+.navbar-light .navbar-toggler:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-nav .nav-link {
+  color: rgba(0, 0, 0, 0.5);
+}
+
+.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover {
+  color: rgba(0, 0, 0, 0.7);
+}
+
+.navbar-light .navbar-nav .open > .nav-link, .navbar-light .navbar-nav .open > .nav-link:focus, .navbar-light .navbar-nav .open > .nav-link:hover,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link:focus,
+.navbar-light .navbar-nav .active > .nav-link:hover,
+.navbar-light .navbar-nav .nav-link.open,
+.navbar-light .navbar-nav .nav-link.open:focus,
+.navbar-light .navbar-nav .nav-link.open:hover,
+.navbar-light .navbar-nav .nav-link.active,
+.navbar-light .navbar-nav .nav-link.active:focus,
+.navbar-light .navbar-nav .nav-link.active:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.navbar-light .navbar-divider {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.navbar-dark .navbar-brand,
+.navbar-dark .navbar-toggler {
+  color: white;
+}
+
+.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover,
+.navbar-dark .navbar-toggler:focus,
+.navbar-dark .navbar-toggler:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-nav .nav-link {
+  color: rgba(255, 255, 255, 0.5);
+}
+
+.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.navbar-dark .navbar-nav .open > .nav-link, .navbar-dark .navbar-nav .open > .nav-link:focus, .navbar-dark .navbar-nav .open > .nav-link:hover,
+.navbar-dark .navbar-nav .active > .nav-link,
+.navbar-dark .navbar-nav .active > .nav-link:focus,
+.navbar-dark .navbar-nav .active > .nav-link:hover,
+.navbar-dark .navbar-nav .nav-link.open,
+.navbar-dark .navbar-nav .nav-link.open:focus,
+.navbar-dark .navbar-nav .nav-link.open:hover,
+.navbar-dark .navbar-nav .nav-link.active,
+.navbar-dark .navbar-nav .nav-link.active:focus,
+.navbar-dark .navbar-nav .nav-link.active:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(255, 255, 255, 0.1);
+}
+
+.navbar-dark .navbar-divider {
+  background-color: rgba(255, 255, 255, 0.075);
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block !important;
+  }
+}
+
+.card {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+  background-color: #fff;
+  border-radius: 0.25rem;
+  border: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-block {
+  padding: 1.25rem;
+}
+
+.card-block::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-title {
+  margin-bottom: 0.75rem;
+}
+
+.card-subtitle {
+  margin-top: -0.375rem;
+  margin-bottom: 0;
+}
+
+.card-text:last-child {
+  margin-bottom: 0;
+}
+
+.card-link:hover {
+  text-decoration: none;
+}
+
+.card-link + .card-link {
+  margin-left: 1.25rem;
+}
+
+.card > .list-group:first-child .list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.card > .list-group:last-child .list-group-item:last-child {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.card-header {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 0;
+  background-color: #f5f5f5;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-header:first-child {
+  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
+}
+
+.card-footer {
+  padding: 0.75rem 1.25rem;
+  background-color: #f5f5f5;
+  border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-footer:last-child {
+  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);
+}
+
+.card-header-tabs {
+  margin-right: -0.625rem;
+  margin-bottom: -0.75rem;
+  margin-left: -0.625rem;
+  border-bottom: 0;
+}
+
+.card-header-pills {
+  margin-right: -0.625rem;
+  margin-left: -0.625rem;
+}
+
+.card-primary {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.card-primary .card-header,
+.card-primary .card-footer {
+  background-color: transparent;
+}
+
+.card-success {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.card-success .card-header,
+.card-success .card-footer {
+  background-color: transparent;
+}
+
+.card-info {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.card-info .card-header,
+.card-info .card-footer {
+  background-color: transparent;
+}
+
+.card-warning {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.card-warning .card-header,
+.card-warning .card-footer {
+  background-color: transparent;
+}
+
+.card-danger {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.card-danger .card-header,
+.card-danger .card-footer {
+  background-color: transparent;
+}
+
+.card-outline-primary {
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.card-outline-secondary {
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.card-outline-info {
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.card-outline-success {
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.card-outline-warning {
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.card-outline-danger {
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer {
+  border-color: rgba(255, 255, 255, 0.2);
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer,
+.card-inverse .card-title,
+.card-inverse .card-blockquote {
+  color: #fff;
+}
+
+.card-inverse .card-link,
+.card-inverse .card-text,
+.card-inverse .card-subtitle,
+.card-inverse .card-blockquote .blockquote-footer {
+  color: rgba(255, 255, 255, 0.65);
+}
+
+.card-inverse .card-link:focus, .card-inverse .card-link:hover {
+  color: #fff;
+}
+
+.card-blockquote {
+  padding: 0;
+  margin-bottom: 0;
+  border-left: 0;
+}
+
+.card-img {
+  border-radius: calc(0.25rem - 1px);
+}
+
+.card-img-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1.25rem;
+}
+
+.card-img-top {
+  border-top-right-radius: calc(0.25rem - 1px);
+  border-top-left-radius: calc(0.25rem - 1px);
+}
+
+.card-img-bottom {
+  border-bottom-right-radius: calc(0.25rem - 1px);
+  border-bottom-left-radius: calc(0.25rem - 1px);
+}
+
+@media (min-width: 576px) {
+  .card-deck {
+    display: table;
+    width: 100%;
+    margin-bottom: 0.75rem;
+    table-layout: fixed;
+    border-spacing: 1.25rem 0;
+  }
+  .card-deck .card {
+    display: table-cell;
+    margin-bottom: 0;
+    vertical-align: top;
+  }
+  .card-deck-wrapper {
+    margin-right: -1.25rem;
+    margin-left: -1.25rem;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-group {
+    display: table;
+    width: 100%;
+    table-layout: fixed;
+  }
+  .card-group .card {
+    display: table-cell;
+    vertical-align: top;
+  }
+  .card-group .card + .card {
+    margin-left: 0;
+    border-left: 0;
+  }
+  .card-group .card:first-child {
+    border-bottom-right-radius: 0;
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-top {
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-bottom {
+    border-bottom-right-radius: 0;
+  }
+  .card-group .card:last-child {
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-top {
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-bottom {
+    border-bottom-left-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) {
+    border-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) .card-img-top,
+  .card-group .card:not(:first-child):not(:last-child) .card-img-bottom {
+    border-radius: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-columns {
+    -webkit-column-count: 3;
+       -moz-column-count: 3;
+            column-count: 3;
+    -webkit-column-gap: 1.25rem;
+       -moz-column-gap: 1.25rem;
+            column-gap: 1.25rem;
+  }
+  .card-columns .card {
+    display: inline-block;
+    width: 100%;
+  }
+}
+
+.breadcrumb {
+  padding: 0.75rem 1rem;
+  margin-bottom: 1rem;
+  list-style: none;
+  background-color: #eceeef;
+  border-radius: 0.25rem;
+}
+
+.breadcrumb::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.breadcrumb-item {
+  float: left;
+}
+
+.breadcrumb-item + .breadcrumb-item::before {
+  display: inline-block;
+  padding-right: 0.5rem;
+  padding-left: 0.5rem;
+  color: #818a91;
+  content: "/";
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: underline;
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: none;
+}
+
+.breadcrumb-item.active {
+  color: #818a91;
+}
+
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border-radius: 0.25rem;
+}
+
+.page-item {
+  display: inline;
+}
+
+.page-item:first-child .page-link {
+  margin-left: 0;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.page-item:last-child .page-link {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.page-item.active .page-link, .page-item.active .page-link:focus, .page-item.active .page-link:hover {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.page-item.disabled .page-link, .page-item.disabled .page-link:focus, .page-item.disabled .page-link:hover {
+  color: #818a91;
+  pointer-events: none;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+
+.page-link {
+  position: relative;
+  float: left;
+  padding: 0.5rem 0.75rem;
+  margin-left: -1px;
+  color: #0275d8;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.page-link:focus, .page-link:hover {
+  color: #014c8c;
+  background-color: #eceeef;
+  border-color: #ddd;
+}
+
+.pagination-lg .page-link {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+}
+
+.pagination-lg .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.3rem;
+  border-top-left-radius: 0.3rem;
+}
+
+.pagination-lg .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.3rem;
+  border-top-right-radius: 0.3rem;
+}
+
+.pagination-sm .page-link {
+  padding: 0.275rem 0.75rem;
+  font-size: 0.875rem;
+}
+
+.pagination-sm .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.2rem;
+  border-top-left-radius: 0.2rem;
+}
+
+.pagination-sm .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.2rem;
+  border-top-right-radius: 0.2rem;
+}
+
+.tag {
+  display: inline-block;
+  padding: 0.25em 0.4em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: 0.25rem;
+}
+
+.tag:empty {
+  display: none;
+}
+
+.btn .tag {
+  position: relative;
+  top: -1px;
+}
+
+a.tag:focus, a.tag:hover {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.tag-pill {
+  padding-right: 0.6em;
+  padding-left: 0.6em;
+  border-radius: 10rem;
+}
+
+.tag-default {
+  background-color: #818a91;
+}
+
+.tag-default[href]:focus, .tag-default[href]:hover {
+  background-color: #687077;
+}
+
+.tag-primary {
+  background-color: #0275d8;
+}
+
+.tag-primary[href]:focus, .tag-primary[href]:hover {
+  background-color: #025aa5;
+}
+
+.tag-success {
+  background-color: #5cb85c;
+}
+
+.tag-success[href]:focus, .tag-success[href]:hover {
+  background-color: #449d44;
+}
+
+.tag-info {
+  background-color: #5bc0de;
+}
+
+.tag-info[href]:focus, .tag-info[href]:hover {
+  background-color: #31b0d5;
+}
+
+.tag-warning {
+  background-color: #f0ad4e;
+}
+
+.tag-warning[href]:focus, .tag-warning[href]:hover {
+  background-color: #ec971f;
+}
+
+.tag-danger {
+  background-color: #d9534f;
+}
+
+.tag-danger[href]:focus, .tag-danger[href]:hover {
+  background-color: #c9302c;
+}
+
+.jumbotron {
+  padding: 2rem 1rem;
+  margin-bottom: 2rem;
+  background-color: #eceeef;
+  border-radius: 0.3rem;
+}
+
+@media (min-width: 576px) {
+  .jumbotron {
+    padding: 4rem 2rem;
+  }
+}
+
+.jumbotron-hr {
+  border-top-color: #d0d5d8;
+}
+
+.jumbotron-fluid {
+  padding-right: 0;
+  padding-left: 0;
+  border-radius: 0;
+}
+
+.alert {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 1rem;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.alert-heading {
+  color: inherit;
+}
+
+.alert-link {
+  font-weight: bold;
+}
+
+.alert-dismissible {
+  padding-right: 2.5rem;
+}
+
+.alert-dismissible .close {
+  position: relative;
+  top: -.125rem;
+  right: -1.25rem;
+  color: inherit;
+}
+
+.alert-success {
+  background-color: #dff0d8;
+  border-color: #d0e9c6;
+  color: #3c763d;
+}
+
+.alert-success hr {
+  border-top-color: #c1e2b3;
+}
+
+.alert-success .alert-link {
+  color: #2b542c;
+}
+
+.alert-info {
+  background-color: #d9edf7;
+  border-color: #bcdff1;
+  color: #31708f;
+}
+
+.alert-info hr {
+  border-top-color: #a6d5ec;
+}
+
+.alert-info .alert-link {
+  color: #245269;
+}
+
+.alert-warning {
+  background-color: #fcf8e3;
+  border-color: #faf2cc;
+  color: #8a6d3b;
+}
+
+.alert-warning hr {
+  border-top-color: #f7ecb5;
+}
+
+.alert-warning .alert-link {
+  color: #66512c;
+}
+
+.alert-danger {
+  background-color: #f2dede;
+  border-color: #ebcccc;
+  color: #a94442;
+}
+
+.alert-danger hr {
+  border-top-color: #e4b9b9;
+}
+
+.alert-danger .alert-link {
+  color: #843534;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  display: block;
+  width: 100%;
+  height: 1rem;
+  margin-bottom: 1rem;
+}
+
+.progress[value] {
+  background-color: #eee;
+  border: 0;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  border-radius: 0.25rem;
+}
+
+.progress[value]::-ms-fill {
+  background-color: #0074d9;
+  border: 0;
+}
+
+.progress[value]::-moz-progress-bar {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-value {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value="100"]::-moz-progress-bar {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value="100"]::-webkit-progress-value {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-bar {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+base::-moz-progress-bar,
+.progress[value] {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress {
+    background-color: #eee;
+    border-radius: 0.25rem;
+  }
+  .progress-bar {
+    display: inline-block;
+    height: 1rem;
+    text-indent: -999rem;
+    background-color: #0074d9;
+    border-bottom-left-radius: 0.25rem;
+    border-top-left-radius: 0.25rem;
+  }
+  .progress[width="100%"] {
+    border-bottom-right-radius: 0.25rem;
+    border-top-right-radius: 0.25rem;
+  }
+}
+
+.progress-striped[value]::-webkit-progress-value {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 1rem 1rem;
+          background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-moz-progress-bar {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-ms-fill {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-bar-striped {
+    background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    -webkit-background-size: 1rem 1rem;
+            background-size: 1rem 1rem;
+  }
+}
+
+.progress-animated[value]::-webkit-progress-value {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-animated[value]::-moz-progress-bar {
+  animation: progress-bar-stripes 2s linear infinite;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-animated .progress-bar-striped {
+    -webkit-animation: progress-bar-stripes 2s linear infinite;
+         -o-animation: progress-bar-stripes 2s linear infinite;
+            animation: progress-bar-stripes 2s linear infinite;
+  }
+}
+
+.progress-success[value]::-webkit-progress-value {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-moz-progress-bar {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-ms-fill {
+  background-color: #5cb85c;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-success .progress-bar {
+    background-color: #5cb85c;
+  }
+}
+
+.progress-info[value]::-webkit-progress-value {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-moz-progress-bar {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-ms-fill {
+  background-color: #5bc0de;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-info .progress-bar {
+    background-color: #5bc0de;
+  }
+}
+
+.progress-warning[value]::-webkit-progress-value {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-moz-progress-bar {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-ms-fill {
+  background-color: #f0ad4e;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-warning .progress-bar {
+    background-color: #f0ad4e;
+  }
+}
+
+.progress-danger[value]::-webkit-progress-value {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-moz-progress-bar {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-ms-fill {
+  background-color: #d9534f;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-danger .progress-bar {
+    background-color: #d9534f;
+  }
+}
+
+.media,
+.media-body {
+  overflow: hidden;
+}
+
+.media-body {
+  width: 10000px;
+}
+
+.media-left,
+.media-right,
+.media-body {
+  display: table-cell;
+  vertical-align: top;
+}
+
+.media-middle {
+  vertical-align: middle;
+}
+
+.media-bottom {
+  vertical-align: bottom;
+}
+
+.media-object {
+  display: block;
+}
+
+.media-object.img-thumbnail {
+  max-width: none;
+}
+
+.media-right {
+  padding-left: 10px;
+}
+
+.media-left {
+  padding-right: 10px;
+}
+
+.media-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-group {
+  padding-left: 0;
+  margin-bottom: 0;
+}
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 0.75rem 1.25rem;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.list-group-item.disabled, .list-group-item.disabled:focus, .list-group-item.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading {
+  color: inherit;
+}
+
+.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text {
+  color: #818a91;
+}
+
+.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover {
+  z-index: 2;
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > .small {
+  color: inherit;
+}
+
+.list-group-item.active .list-group-item-text, .list-group-item.active:focus .list-group-item-text, .list-group-item.active:hover .list-group-item-text {
+  color: #a8d6fe;
+}
+
+.list-group-flush .list-group-item {
+  border-right: 0;
+  border-left: 0;
+  border-radius: 0;
+}
+
+.list-group-item-action {
+  width: 100%;
+  color: #555;
+  text-align: inherit;
+}
+
+.list-group-item-action .list-group-item-heading {
+  color: #333;
+}
+
+.list-group-item-action:focus, .list-group-item-action:hover {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+
+a.list-group-item-success,
+button.list-group-item-success {
+  color: #3c763d;
+}
+
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-success:focus, a.list-group-item-success:hover,
+button.list-group-item-success:focus,
+button.list-group-item-success:hover {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+
+a.list-group-item-success.active, a.list-group-item-success.active:focus, a.list-group-item-success.active:hover,
+button.list-group-item-success.active,
+button.list-group-item-success.active:focus,
+button.list-group-item-success.active:hover {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+
+a.list-group-item-info,
+button.list-group-item-info {
+  color: #31708f;
+}
+
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-info:focus, a.list-group-item-info:hover,
+button.list-group-item-info:focus,
+button.list-group-item-info:hover {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+
+a.list-group-item-info.active, a.list-group-item-info.active:focus, a.list-group-item-info.active:hover,
+button.list-group-item-info.active,
+button.list-group-item-info.active:focus,
+button.list-group-item-info.active:hover {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+
+a.list-group-item-warning,
+button.list-group-item-warning {
+  color: #8a6d3b;
+}
+
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-warning:focus, a.list-group-item-warning:hover,
+button.list-group-item-warning:focus,
+button.list-group-item-warning:hover {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+
+a.list-group-item-warning.active, a.list-group-item-warning.active:focus, a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active,
+button.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:hover {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+
+a.list-group-item-danger,
+button.list-group-item-danger {
+  color: #a94442;
+}
+
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-danger:focus, a.list-group-item-danger:hover,
+button.list-group-item-danger:focus,
+button.list-group-item-danger:hover {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+
+a.list-group-item-danger.active, a.list-group-item-danger.active:focus, a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active,
+button.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:hover {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+.embed-responsive-21by9 {
+  padding-bottom: 42.857143%;
+}
+
+.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+
+.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+
+.embed-responsive-1by1 {
+  padding-bottom: 100%;
+}
+
+.close {
+  float: right;
+  font-size: 1.5rem;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  opacity: .2;
+}
+
+.close:focus, .close:hover {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  opacity: .5;
+}
+
+button.close {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.modal-open {
+  overflow: hidden;
+}
+
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  outline: 0;
+}
+
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+  transition: -webkit-transform .3s ease-out;
+  -o-transition: -o-transform .3s ease-out;
+  transition: transform .3s ease-out;
+  transition: transform .3s ease-out, -webkit-transform .3s ease-out, -o-transform .3s ease-out;
+  -webkit-transform: translate(0, -25%);
+      -ms-transform: translate(0, -25%);
+       -o-transform: translate(0, -25%);
+          transform: translate(0, -25%);
+}
+
+.modal.in .modal-dialog {
+  -webkit-transform: translate(0, 0);
+      -ms-transform: translate(0, 0);
+       -o-transform: translate(0, 0);
+          transform: translate(0, 0);
+}
+
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+  outline: 0;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop.in {
+  opacity: 0.5;
+}
+
+.modal-header {
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+.modal-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-header .close {
+  margin-top: -2px;
+}
+
+.modal-title {
+  margin: 0;
+  line-height: 1.5;
+}
+
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+
+.modal-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+
+@media (min-width: 576px) {
+  .modal-dialog {
+    max-width: 600px;
+    margin: 30px auto;
+  }
+  .modal-sm {
+    max-width: 300px;
+  }
+}
+
+@media (min-width: 992px) {
+  .modal-lg {
+    max-width: 900px;
+  }
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  opacity: 0;
+}
+
+.tooltip.in {
+  opacity: 0.9;
+}
+
+.tooltip.tooltip-top, .tooltip.bs-tether-element-attached-bottom {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+
+.tooltip.tooltip-top .tooltip-inner::before, .tooltip.bs-tether-element-attached-bottom .tooltip-inner::before {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+
+.tooltip.tooltip-right, .tooltip.bs-tether-element-attached-left {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+
+.tooltip.tooltip-right .tooltip-inner::before, .tooltip.bs-tether-element-attached-left .tooltip-inner::before {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+
+.tooltip.tooltip-bottom, .tooltip.bs-tether-element-attached-top {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+
+.tooltip.tooltip-bottom .tooltip-inner::before, .tooltip.bs-tether-element-attached-top .tooltip-inner::before {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+
+.tooltip.tooltip-left, .tooltip.bs-tether-element-attached-right {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+
+.tooltip.tooltip-left .tooltip-inner::before, .tooltip.bs-tether-element-attached-right .tooltip-inner::before {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  background-color: #000;
+  border-radius: 0.25rem;
+}
+
+.tooltip-inner::before {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: block;
+  max-width: 276px;
+  padding: 1px;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+}
+
+.popover.popover-top, .popover.bs-tether-element-attached-bottom {
+  margin-top: -10px;
+}
+
+.popover.popover-top::before, .popover.popover-top::after, .popover.bs-tether-element-attached-bottom::before, .popover.bs-tether-element-attached-bottom::after {
+  left: 50%;
+  border-bottom-width: 0;
+}
+
+.popover.popover-top::before, .popover.bs-tether-element-attached-bottom::before {
+  bottom: -11px;
+  margin-left: -11px;
+  border-top-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-top::after, .popover.bs-tether-element-attached-bottom::after {
+  bottom: -10px;
+  margin-left: -10px;
+  border-top-color: #fff;
+}
+
+.popover.popover-right, .popover.bs-tether-element-attached-left {
+  margin-left: 10px;
+}
+
+.popover.popover-right::before, .popover.popover-right::after, .popover.bs-tether-element-attached-left::before, .popover.bs-tether-element-attached-left::after {
+  top: 50%;
+  border-left-width: 0;
+}
+
+.popover.popover-right::before, .popover.bs-tether-element-attached-left::before {
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-right::after, .popover.bs-tether-element-attached-left::after {
+  left: -10px;
+  margin-top: -10px;
+  border-right-color: #fff;
+}
+
+.popover.popover-bottom, .popover.bs-tether-element-attached-top {
+  margin-top: 10px;
+}
+
+.popover.popover-bottom::before, .popover.popover-bottom::after, .popover.bs-tether-element-attached-top::before, .popover.bs-tether-element-attached-top::after {
+  left: 50%;
+  border-top-width: 0;
+}
+
+.popover.popover-bottom::before, .popover.bs-tether-element-attached-top::before {
+  top: -11px;
+  margin-left: -11px;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-bottom::after, .popover.bs-tether-element-attached-top::after {
+  top: -10px;
+  margin-left: -10px;
+  border-bottom-color: #f7f7f7;
+}
+
+.popover.popover-bottom .popover-title::before, .popover.bs-tether-element-attached-top .popover-title::before {
+  position: absolute;
+  top: 0;
+  left: 50%;
+  display: block;
+  width: 20px;
+  margin-left: -10px;
+  content: "";
+  border-bottom: 1px solid #f7f7f7;
+}
+
+.popover.popover-left, .popover.bs-tether-element-attached-right {
+  margin-left: -10px;
+}
+
+.popover.popover-left::before, .popover.popover-left::after, .popover.bs-tether-element-attached-right::before, .popover.bs-tether-element-attached-right::after {
+  top: 50%;
+  border-right-width: 0;
+}
+
+.popover.popover-left::before, .popover.bs-tether-element-attached-right::before {
+  right: -11px;
+  margin-top: -11px;
+  border-left-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-left::after, .popover.bs-tether-element-attached-right::after {
+  right: -10px;
+  margin-top: -10px;
+  border-left-color: #fff;
+}
+
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 1rem;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 0.2375rem 0.2375rem 0 0;
+}
+
+.popover-title:empty {
+  display: none;
+}
+
+.popover-content {
+  padding: 9px 14px;
+}
+
+.popover::before,
+.popover::after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover::before {
+  content: "";
+  border-width: 11px;
+}
+
+.popover::after {
+  content: "";
+  border-width: 10px;
+}
+
+.carousel {
+  position: relative;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-inner > .carousel-item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+  -o-transition: .6s ease-in-out left;
+  transition: .6s ease-in-out left;
+}
+
+.carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  line-height: 1;
+}
+
+@media all and (transform-3d), (-webkit-transform-3d) {
+  .carousel-inner > .carousel-item {
+    -webkit-transition: -webkit-transform .6s ease-in-out;
+    transition: -webkit-transform .6s ease-in-out;
+    -o-transition: -o-transform .6s ease-in-out;
+    transition: transform .6s ease-in-out;
+    transition: transform .6s ease-in-out, -webkit-transform .6s ease-in-out, -o-transform .6s ease-in-out;
+    -webkit-backface-visibility: hidden;
+            backface-visibility: hidden;
+    -webkit-perspective: 1000px;
+            perspective: 1000px;
+  }
+  .carousel-inner > .carousel-item.next, .carousel-inner > .carousel-item.active.right {
+    left: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+            transform: translate3d(100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.prev, .carousel-inner > .carousel-item.active.left {
+    left: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+            transform: translate3d(-100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.next.left, .carousel-inner > .carousel-item.prev.right, .carousel-inner > .carousel-item.active {
+    left: 0;
+    -webkit-transform: translate3d(0, 0, 0);
+            transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+
+.carousel-inner > .active {
+  left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.carousel-inner > .next {
+  left: 100%;
+}
+
+.carousel-inner > .prev {
+  left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+
+.carousel-inner > .active.left {
+  left: -100%;
+}
+
+.carousel-inner > .active.right {
+  left: 100%;
+}
+
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+  opacity: 0.5;
+}
+
+.carousel-control.left {
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+
+.carousel-control:focus, .carousel-control:hover {
+  color: #fff;
+  text-decoration: none;
+  outline: 0;
+  opacity: .9;
+}
+
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+  line-height: 1;
+}
+
+.carousel-control .icon-prev {
+  left: 50%;
+  margin-left: -10px;
+}
+
+.carousel-control .icon-next {
+  right: 50%;
+  margin-right: -10px;
+}
+
+.carousel-control .icon-prev::before {
+  content: "\2039";
+}
+
+.carousel-control .icon-next::before {
+  content: "\203a";
+}
+
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: transparent;
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+
+.carousel-caption .btn {
+  text-shadow: none;
+}
+
+@media (min-width: 576px) {
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+
+.align-baseline {
+  vertical-align: baseline !important;
+}
+
+.align-top {
+  vertical-align: top !important;
+}
+
+.align-middle {
+  vertical-align: middle !important;
+}
+
+.align-bottom {
+  vertical-align: bottom !important;
+}
+
+.align-text-bottom {
+  vertical-align: text-bottom !important;
+}
+
+.align-text-top {
+  vertical-align: text-top !important;
+}
+
+.bg-faded {
+  background-color: #f7f7f9;
+}
+
+.bg-primary {
+  background-color: #0275d8 !important;
+}
+
+a.bg-primary:focus, a.bg-primary:hover {
+  background-color: #025aa5 !important;
+}
+
+.bg-success {
+  background-color: #5cb85c !important;
+}
+
+a.bg-success:focus, a.bg-success:hover {
+  background-color: #449d44 !important;
+}
+
+.bg-info {
+  background-color: #5bc0de !important;
+}
+
+a.bg-info:focus, a.bg-info:hover {
+  background-color: #31b0d5 !important;
+}
+
+.bg-warning {
+  background-color: #f0ad4e !important;
+}
+
+a.bg-warning:focus, a.bg-warning:hover {
+  background-color: #ec971f !important;
+}
+
+.bg-danger {
+  background-color: #d9534f !important;
+}
+
+a.bg-danger:focus, a.bg-danger:hover {
+  background-color: #c9302c !important;
+}
+
+.bg-inverse {
+  background-color: #373a3c !important;
+}
+
+a.bg-inverse:focus, a.bg-inverse:hover {
+  background-color: #1f2021 !important;
+}
+
+.rounded {
+  border-radius: 0.25rem;
+}
+
+.rounded-top {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-right {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.rounded-bottom {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.rounded-left {
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-circle {
+  border-radius: 50%;
+}
+
+.clearfix::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.d-block {
+  display: block !important;
+}
+
+.d-inline-block {
+  display: inline-block !important;
+}
+
+.d-inline {
+  display: inline !important;
+}
+
+.float-xs-left {
+  float: left !important;
+}
+
+.float-xs-right {
+  float: right !important;
+}
+
+.float-xs-none {
+  float: none !important;
+}
+
+@media (min-width: 576px) {
+  .float-sm-left {
+    float: left !important;
+  }
+  .float-sm-right {
+    float: right !important;
+  }
+  .float-sm-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .float-md-left {
+    float: left !important;
+  }
+  .float-md-right {
+    float: right !important;
+  }
+  .float-md-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .float-lg-left {
+    float: left !important;
+  }
+  .float-lg-right {
+    float: right !important;
+  }
+  .float-lg-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .float-xl-left {
+    float: left !important;
+  }
+  .float-xl-right {
+    float: right !important;
+  }
+  .float-xl-none {
+    float: none !important;
+  }
+}
+
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+
+.w-100 {
+  width: 100% !important;
+}
+
+.h-100 {
+  height: 100% !important;
+}
+
+.mx-auto {
+  margin-right: auto !important;
+  margin-left: auto !important;
+}
+
+.m-0 {
+  margin: 0 0 !important;
+}
+
+.mt-0 {
+  margin-top: 0 !important;
+}
+
+.mr-0 {
+  margin-right: 0 !important;
+}
+
+.mb-0 {
+  margin-bottom: 0 !important;
+}
+
+.ml-0 {
+  margin-left: 0 !important;
+}
+
+.mx-0 {
+  margin-right: 0 !important;
+  margin-left: 0 !important;
+}
+
+.my-0 {
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+
+.m-1 {
+  margin: 1rem 1rem !important;
+}
+
+.mt-1 {
+  margin-top: 1rem !important;
+}
+
+.mr-1 {
+  margin-right: 1rem !important;
+}
+
+.mb-1 {
+  margin-bottom: 1rem !important;
+}
+
+.ml-1 {
+  margin-left: 1rem !important;
+}
+
+.mx-1 {
+  margin-right: 1rem !important;
+  margin-left: 1rem !important;
+}
+
+.my-1 {
+  margin-top: 1rem !important;
+  margin-bottom: 1rem !important;
+}
+
+.m-2 {
+  margin: 1.5rem 1.5rem !important;
+}
+
+.mt-2 {
+  margin-top: 1.5rem !important;
+}
+
+.mr-2 {
+  margin-right: 1.5rem !important;
+}
+
+.mb-2 {
+  margin-bottom: 1.5rem !important;
+}
+
+.ml-2 {
+  margin-left: 1.5rem !important;
+}
+
+.mx-2 {
+  margin-right: 1.5rem !important;
+  margin-left: 1.5rem !important;
+}
+
+.my-2 {
+  margin-top: 1.5rem !important;
+  margin-bottom: 1.5rem !important;
+}
+
+.m-3 {
+  margin: 3rem 3rem !important;
+}
+
+.mt-3 {
+  margin-top: 3rem !important;
+}
+
+.mr-3 {
+  margin-right: 3rem !important;
+}
+
+.mb-3 {
+  margin-bottom: 3rem !important;
+}
+
+.ml-3 {
+  margin-left: 3rem !important;
+}
+
+.mx-3 {
+  margin-right: 3rem !important;
+  margin-left: 3rem !important;
+}
+
+.my-3 {
+  margin-top: 3rem !important;
+  margin-bottom: 3rem !important;
+}
+
+.p-0 {
+  padding: 0 0 !important;
+}
+
+.pt-0 {
+  padding-top: 0 !important;
+}
+
+.pr-0 {
+  padding-right: 0 !important;
+}
+
+.pb-0 {
+  padding-bottom: 0 !important;
+}
+
+.pl-0 {
+  padding-left: 0 !important;
+}
+
+.px-0 {
+  padding-right: 0 !important;
+  padding-left: 0 !important;
+}
+
+.py-0 {
+  padding-top: 0 !important;
+  padding-bottom: 0 !important;
+}
+
+.p-1 {
+  padding: 1rem 1rem !important;
+}
+
+.pt-1 {
+  padding-top: 1rem !important;
+}
+
+.pr-1 {
+  padding-right: 1rem !important;
+}
+
+.pb-1 {
+  padding-bottom: 1rem !important;
+}
+
+.pl-1 {
+  padding-left: 1rem !important;
+}
+
+.px-1 {
+  padding-right: 1rem !important;
+  padding-left: 1rem !important;
+}
+
+.py-1 {
+  padding-top: 1rem !important;
+  padding-bottom: 1rem !important;
+}
+
+.p-2 {
+  padding: 1.5rem 1.5rem !important;
+}
+
+.pt-2 {
+  padding-top: 1.5rem !important;
+}
+
+.pr-2 {
+  padding-right: 1.5rem !important;
+}
+
+.pb-2 {
+  padding-bottom: 1.5rem !important;
+}
+
+.pl-2 {
+  padding-left: 1.5rem !important;
+}
+
+.px-2 {
+  padding-right: 1.5rem !important;
+  padding-left: 1.5rem !important;
+}
+
+.py-2 {
+  padding-top: 1.5rem !important;
+  padding-bottom: 1.5rem !important;
+}
+
+.p-3 {
+  padding: 3rem 3rem !important;
+}
+
+.pt-3 {
+  padding-top: 3rem !important;
+}
+
+.pr-3 {
+  padding-right: 3rem !important;
+}
+
+.pb-3 {
+  padding-bottom: 3rem !important;
+}
+
+.pl-3 {
+  padding-left: 3rem !important;
+}
+
+.px-3 {
+  padding-right: 3rem !important;
+  padding-left: 3rem !important;
+}
+
+.py-3 {
+  padding-top: 3rem !important;
+  padding-bottom: 3rem !important;
+}
+
+.pos-f-t {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+.text-justify {
+  text-align: justify !important;
+}
+
+.text-nowrap {
+  white-space: nowrap !important;
+}
+
+.text-truncate {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.text-xs-left {
+  text-align: left !important;
+}
+
+.text-xs-right {
+  text-align: right !important;
+}
+
+.text-xs-center {
+  text-align: center !important;
+}
+
+@media (min-width: 576px) {
+  .text-sm-left {
+    text-align: left !important;
+  }
+  .text-sm-right {
+    text-align: right !important;
+  }
+  .text-sm-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .text-md-left {
+    text-align: left !important;
+  }
+  .text-md-right {
+    text-align: right !important;
+  }
+  .text-md-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .text-lg-left {
+    text-align: left !important;
+  }
+  .text-lg-right {
+    text-align: right !important;
+  }
+  .text-lg-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .text-xl-left {
+    text-align: left !important;
+  }
+  .text-xl-right {
+    text-align: right !important;
+  }
+  .text-xl-center {
+    text-align: center !important;
+  }
+}
+
+.text-lowercase {
+  text-transform: lowercase !important;
+}
+
+.text-uppercase {
+  text-transform: uppercase !important;
+}
+
+.text-capitalize {
+  text-transform: capitalize !important;
+}
+
+.font-weight-normal {
+  font-weight: normal;
+}
+
+.font-weight-bold {
+  font-weight: bold;
+}
+
+.font-italic {
+  font-style: italic;
+}
+
+.text-white {
+  color: #fff !important;
+}
+
+.text-muted {
+  color: #818a91 !important;
+}
+
+a.text-muted:focus, a.text-muted:hover {
+  color: #687077 !important;
+}
+
+.text-primary {
+  color: #0275d8 !important;
+}
+
+a.text-primary:focus, a.text-primary:hover {
+  color: #025aa5 !important;
+}
+
+.text-success {
+  color: #5cb85c !important;
+}
+
+a.text-success:focus, a.text-success:hover {
+  color: #449d44 !important;
+}
+
+.text-info {
+  color: #5bc0de !important;
+}
+
+a.text-info:focus, a.text-info:hover {
+  color: #31b0d5 !important;
+}
+
+.text-warning {
+  color: #f0ad4e !important;
+}
+
+a.text-warning:focus, a.text-warning:hover {
+  color: #ec971f !important;
+}
+
+.text-danger {
+  color: #d9534f !important;
+}
+
+a.text-danger:focus, a.text-danger:hover {
+  color: #c9302c !important;
+}
+
+.text-gray-dark {
+  color: #373a3c !important;
+}
+
+a.text-gray-dark:focus, a.text-gray-dark:hover {
+  color: #1f2021 !important;
+}
+
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.invisible {
+  visibility: hidden !important;
+}
+
+.hidden-xs-up {
+  display: none !important;
+}
+
+@media (max-width: 575px) {
+  .hidden-xs-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 576px) {
+  .hidden-sm-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-sm-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .hidden-md-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 991px) {
+  .hidden-md-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .hidden-lg-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 1199px) {
+  .hidden-lg-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .hidden-xl-up {
+    display: none !important;
+  }
+}
+
+.hidden-xl-down {
+  display: none !important;
+}
+
+.visible-print-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+
+.visible-print-inline {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+
+.visible-print-inline-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
new file mode 100644
index 0000000..5eecafb
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_custom.scss","../../scss/_tobago.scss","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_hover.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
new file mode 100644
index 0000000..669aeab
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.tobago-box-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center}.tobago-button>img{margin-top:-1px;margin-bottom:-1px}.tobago-collapsed.tobago-box .card-block,.tobago-collapsed.tobago-panel,.tobago-collapsed.tobago-section .tobago-section-content{display:none}.tobago-d [...]
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
new file mode 100644
index 0000000..fcaf1a0
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/_tobago.scss","dist/css/bootstrap.css","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_cle [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.js b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.js
new file mode 100644
index 0000000..0a37e60
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.js
@@ -0,0 +1,3430 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+if (typeof jQuery === 'undefined') {
+  throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+  var version = $.fn.jquery.split(' ')[0].split('.')
+  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {
+    throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
+  }
+}(jQuery);
+
+
++function () {
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) [...]
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): util.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Util = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Private TransitionEnd Helpers
+   * ------------------------------------------------------------------------
+   */
+
+  var transition = false;
+
+  var MAX_UID = 1000000;
+
+  var TransitionEndEvent = {
+    WebkitTransition: 'webkitTransitionEnd',
+    MozTransition: 'transitionend',
+    OTransition: 'oTransitionEnd otransitionend',
+    transition: 'transitionend'
+  };
+
+  // shoutout AngusCroll (https://goo.gl/pxwQGp)
+  function toType(obj) {
+    return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
+  }
+
+  function isElement(obj) {
+    return (obj[0] || obj).nodeType;
+  }
+
+  function getSpecialTransitionEndEvent() {
+    return {
+      bindType: transition.end,
+      delegateType: transition.end,
+      handle: function handle(event) {
+        if ($(event.target).is(this)) {
+          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
+        }
+        return undefined;
+      }
+    };
+  }
+
+  function transitionEndTest() {
+    if (window.QUnit) {
+      return false;
+    }
+
+    var el = document.createElement('bootstrap');
+
+    for (var name in TransitionEndEvent) {
+      if (el.style[name] !== undefined) {
+        return { end: TransitionEndEvent[name] };
+      }
+    }
+
+    return false;
+  }
+
+  function transitionEndEmulator(duration) {
+    var _this = this;
+
+    var called = false;
+
+    $(this).one(Util.TRANSITION_END, function () {
+      called = true;
+    });
+
+    setTimeout(function () {
+      if (!called) {
+        Util.triggerTransitionEnd(_this);
+      }
+    }, duration);
+
+    return this;
+  }
+
+  function setTransitionEndSupport() {
+    transition = transitionEndTest();
+
+    $.fn.emulateTransitionEnd = transitionEndEmulator;
+
+    if (Util.supportsTransitionEnd()) {
+      $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
+    }
+  }
+
+  /**
+   * --------------------------------------------------------------------------
+   * Public Util Api
+   * --------------------------------------------------------------------------
+   */
+
+  var Util = {
+
+    TRANSITION_END: 'bsTransitionEnd',
+
+    getUID: function getUID(prefix) {
+      do {
+        /* eslint-disable no-bitwise */
+        prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
+        /* eslint-enable no-bitwise */
+      } while (document.getElementById(prefix));
+      return prefix;
+    },
+    getSelectorFromElement: function getSelectorFromElement(element) {
+      var selector = element.getAttribute('data-target');
+
+      if (!selector) {
+        selector = element.getAttribute('href') || '';
+        selector = /^#[a-z]/i.test(selector) ? selector : null;
+      }
+
+      return selector;
+    },
+    reflow: function reflow(element) {
+      new Function('bs', 'return bs')(element.offsetHeight);
+    },
+    triggerTransitionEnd: function triggerTransitionEnd(element) {
+      $(element).trigger(transition.end);
+    },
+    supportsTransitionEnd: function supportsTransitionEnd() {
+      return Boolean(transition);
+    },
+    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
+      for (var property in configTypes) {
+        if (configTypes.hasOwnProperty(property)) {
+          var expectedTypes = configTypes[property];
+          var value = config[property];
+          var valueType = void 0;
+
+          if (value && isElement(value)) {
+            valueType = 'element';
+          } else {
+            valueType = toType(value);
+          }
+
+          if (!new RegExp(expectedTypes).test(valueType)) {
+            throw new Error(componentName.toUpperCase() + ': ' + ('Option "' + property + '" provided type "' + valueType + '" ') + ('but expected type "' + expectedTypes + '".'));
+          }
+        }
+      }
+    }
+  };
+
+  setTransitionEndSupport();
+
+  return Util;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): alert.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Alert = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'alert';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.alert';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Selector = {
+    DISMISS: '[data-dismiss="alert"]'
+  };
+
+  var Event = {
+    CLOSE: 'close' + EVENT_KEY,
+    CLOSED: 'closed' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    ALERT: 'alert',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Alert = function () {
+    function Alert(element) {
+      _classCallCheck(this, Alert);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Alert.prototype.close = function close(element) {
+      element = element || this._element;
+
+      var rootElement = this._getRootElement(element);
+      var customEvent = this._triggerCloseEvent(rootElement);
+
+      if (customEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._removeElement(rootElement);
+    };
+
+    Alert.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Alert.prototype._getRootElement = function _getRootElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      var parent = false;
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      if (!parent) {
+        parent = $(element).closest('.' + ClassName.ALERT)[0];
+      }
+
+      return parent;
+    };
+
+    Alert.prototype._triggerCloseEvent = function _triggerCloseEvent(element) {
+      var closeEvent = $.Event(Event.CLOSE);
+
+      $(element).trigger(closeEvent);
+      return closeEvent;
+    };
+
+    Alert.prototype._removeElement = function _removeElement(element) {
+      $(element).removeClass(ClassName.IN);
+
+      if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {
+        this._destroyElement(element);
+        return;
+      }
+
+      $(element).one(Util.TRANSITION_END, $.proxy(this._destroyElement, this, element)).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Alert.prototype._destroyElement = function _destroyElement(element) {
+      $(element).detach().trigger(Event.CLOSED).remove();
+    };
+
+    // static
+
+    Alert._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $element = $(this);
+        var data = $element.data(DATA_KEY);
+
+        if (!data) {
+          data = new Alert(this);
+          $element.data(DATA_KEY, data);
+        }
+
+        if (config === 'close') {
+          data[config](this);
+        }
+      });
+    };
+
+    Alert._handleDismiss = function _handleDismiss(alertInstance) {
+      return function (event) {
+        if (event) {
+          event.preventDefault();
+        }
+
+        alertInstance.close(this);
+      };
+    };
+
+    _createClass(Alert, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Alert;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Alert._jQueryInterface;
+  $.fn[NAME].Constructor = Alert;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Alert._jQueryInterface;
+  };
+
+  return Alert;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): button.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Button = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'button';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.button';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var ClassName = {
+    ACTIVE: 'active',
+    BUTTON: 'btn',
+    FOCUS: 'focus'
+  };
+
+  var Selector = {
+    DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
+    DATA_TOGGLE: '[data-toggle="buttons"]',
+    INPUT: 'input',
+    ACTIVE: '.active',
+    BUTTON: '.btn'
+  };
+
+  var Event = {
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    FOCUS_BLUR_DATA_API: 'focus' + EVENT_KEY + DATA_API_KEY + ' ' + ('blur' + EVENT_KEY + DATA_API_KEY)
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Button = function () {
+    function Button(element) {
+      _classCallCheck(this, Button);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Button.prototype.toggle = function toggle() {
+      var triggerChangeEvent = true;
+      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];
+
+      if (rootElement) {
+        var input = $(this._element).find(Selector.INPUT)[0];
+
+        if (input) {
+          if (input.type === 'radio') {
+            if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) {
+              triggerChangeEvent = false;
+            } else {
+              var activeElement = $(rootElement).find(Selector.ACTIVE)[0];
+
+              if (activeElement) {
+                $(activeElement).removeClass(ClassName.ACTIVE);
+              }
+            }
+          }
+
+          if (triggerChangeEvent) {
+            input.checked = !$(this._element).hasClass(ClassName.ACTIVE);
+            $(this._element).trigger('change');
+          }
+
+          input.focus();
+        }
+      } else {
+        this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));
+      }
+
+      if (triggerChangeEvent) {
+        $(this._element).toggleClass(ClassName.ACTIVE);
+      }
+    };
+
+    Button.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // static
+
+    Button._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          data = new Button(this);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (config === 'toggle') {
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Button, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Button;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    event.preventDefault();
+
+    var button = event.target;
+
+    if (!$(button).hasClass(ClassName.BUTTON)) {
+      button = $(button).closest(Selector.BUTTON);
+    }
+
+    Button._jQueryInterface.call($(button), 'toggle');
+  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    var button = $(event.target).closest(Selector.BUTTON)[0];
+    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Button._jQueryInterface;
+  $.fn[NAME].Constructor = Button;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Button._jQueryInterface;
+  };
+
+  return Button;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): carousel.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Carousel = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'carousel';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.carousel';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
+  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
+
+  var Default = {
+    interval: 5000,
+    keyboard: true,
+    slide: false,
+    pause: 'hover',
+    wrap: true
+  };
+
+  var DefaultType = {
+    interval: '(number|boolean)',
+    keyboard: 'boolean',
+    slide: '(boolean|string)',
+    pause: '(string|boolean)',
+    wrap: 'boolean'
+  };
+
+  var Direction = {
+    NEXT: 'next',
+    PREVIOUS: 'prev'
+  };
+
+  var Event = {
+    SLIDE: 'slide' + EVENT_KEY,
+    SLID: 'slid' + EVENT_KEY,
+    KEYDOWN: 'keydown' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    CAROUSEL: 'carousel',
+    ACTIVE: 'active',
+    SLIDE: 'slide',
+    RIGHT: 'right',
+    LEFT: 'left',
+    ITEM: 'carousel-item'
+  };
+
+  var Selector = {
+    ACTIVE: '.active',
+    ACTIVE_ITEM: '.active.carousel-item',
+    ITEM: '.carousel-item',
+    NEXT_PREV: '.next, .prev',
+    INDICATORS: '.carousel-indicators',
+    DATA_SLIDE: '[data-slide], [data-slide-to]',
+    DATA_RIDE: '[data-ride="carousel"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Carousel = function () {
+    function Carousel(element, config) {
+      _classCallCheck(this, Carousel);
+
+      this._items = null;
+      this._interval = null;
+      this._activeElement = null;
+
+      this._isPaused = false;
+      this._isSliding = false;
+
+      this._config = this._getConfig(config);
+      this._element = $(element)[0];
+      this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Carousel.prototype.next = function next() {
+      if (!this._isSliding) {
+        this._slide(Direction.NEXT);
+      }
+    };
+
+    Carousel.prototype.nextWhenVisible = function nextWhenVisible() {
+      // Don't call next when the page isn't visible
+      if (!document.hidden) {
+        this.next();
+      }
+    };
+
+    Carousel.prototype.prev = function prev() {
+      if (!this._isSliding) {
+        this._slide(Direction.PREVIOUS);
+      }
+    };
+
+    Carousel.prototype.pause = function pause(event) {
+      if (!event) {
+        this._isPaused = true;
+      }
+
+      if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {
+        Util.triggerTransitionEnd(this._element);
+        this.cycle(true);
+      }
+
+      clearInterval(this._interval);
+      this._interval = null;
+    };
+
+    Carousel.prototype.cycle = function cycle(event) {
+      if (!event) {
+        this._isPaused = false;
+      }
+
+      if (this._interval) {
+        clearInterval(this._interval);
+        this._interval = null;
+      }
+
+      if (this._config.interval && !this._isPaused) {
+        this._interval = setInterval($.proxy(document.visibilityState ? this.nextWhenVisible : this.next, this), this._config.interval);
+      }
+    };
+
+    Carousel.prototype.to = function to(index) {
+      var _this2 = this;
+
+      this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+
+      var activeIndex = this._getItemIndex(this._activeElement);
+
+      if (index > this._items.length - 1 || index < 0) {
+        return;
+      }
+
+      if (this._isSliding) {
+        $(this._element).one(Event.SLID, function () {
+          return _this2.to(index);
+        });
+        return;
+      }
+
+      if (activeIndex === index) {
+        this.pause();
+        this.cycle();
+        return;
+      }
+
+      var direction = index > activeIndex ? Direction.NEXT : Direction.PREVIOUS;
+
+      this._slide(direction, this._items[index]);
+    };
+
+    Carousel.prototype.dispose = function dispose() {
+      $(this._element).off(EVENT_KEY);
+      $.removeData(this._element, DATA_KEY);
+
+      this._items = null;
+      this._config = null;
+      this._element = null;
+      this._interval = null;
+      this._isPaused = null;
+      this._isSliding = null;
+      this._activeElement = null;
+      this._indicatorsElement = null;
+    };
+
+    // private
+
+    Carousel.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Carousel.prototype._addEventListeners = function _addEventListeners() {
+      if (this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN, $.proxy(this._keydown, this));
+      }
+
+      if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
+        $(this._element).on(Event.MOUSEENTER, $.proxy(this.pause, this)).on(Event.MOUSELEAVE, $.proxy(this.cycle, this));
+      }
+    };
+
+    Carousel.prototype._keydown = function _keydown(event) {
+      event.preventDefault();
+
+      if (/input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      switch (event.which) {
+        case ARROW_LEFT_KEYCODE:
+          this.prev();
+          break;
+        case ARROW_RIGHT_KEYCODE:
+          this.next();
+          break;
+        default:
+          return;
+      }
+    };
+
+    Carousel.prototype._getItemIndex = function _getItemIndex(element) {
+      this._items = $.makeArray($(element).parent().find(Selector.ITEM));
+      return this._items.indexOf(element);
+    };
+
+    Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) {
+      var isNextDirection = direction === Direction.NEXT;
+      var isPrevDirection = direction === Direction.PREVIOUS;
+      var activeIndex = this._getItemIndex(activeElement);
+      var lastItemIndex = this._items.length - 1;
+      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
+
+      if (isGoingToWrap && !this._config.wrap) {
+        return activeElement;
+      }
+
+      var delta = direction === Direction.PREVIOUS ? -1 : 1;
+      var itemIndex = (activeIndex + delta) % this._items.length;
+
+      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
+    };
+
+    Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, directionalClassname) {
+      var slideEvent = $.Event(Event.SLIDE, {
+        relatedTarget: relatedTarget,
+        direction: directionalClassname
+      });
+
+      $(this._element).trigger(slideEvent);
+
+      return slideEvent;
+    };
+
+    Carousel.prototype._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
+      if (this._indicatorsElement) {
+        $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+
+        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
+
+        if (nextIndicator) {
+          $(nextIndicator).addClass(ClassName.ACTIVE);
+        }
+      }
+    };
+
+    Carousel.prototype._slide = function _slide(direction, element) {
+      var _this3 = this;
+
+      var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
+
+      var isCycling = Boolean(this._interval);
+
+      var directionalClassName = direction === Direction.NEXT ? ClassName.LEFT : ClassName.RIGHT;
+
+      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {
+        this._isSliding = false;
+        return;
+      }
+
+      var slideEvent = this._triggerSlideEvent(nextElement, directionalClassName);
+      if (slideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (!activeElement || !nextElement) {
+        // some weirdness is happening, so we bail
+        return;
+      }
+
+      this._isSliding = true;
+
+      if (isCycling) {
+        this.pause();
+      }
+
+      this._setActiveIndicatorElement(nextElement);
+
+      var slidEvent = $.Event(Event.SLID, {
+        relatedTarget: nextElement,
+        direction: directionalClassName
+      });
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {
+
+        $(nextElement).addClass(direction);
+
+        Util.reflow(nextElement);
+
+        $(activeElement).addClass(directionalClassName);
+        $(nextElement).addClass(directionalClassName);
+
+        $(activeElement).one(Util.TRANSITION_END, function () {
+          $(nextElement).removeClass(directionalClassName).removeClass(direction);
+
+          $(nextElement).addClass(ClassName.ACTIVE);
+
+          $(activeElement).removeClass(ClassName.ACTIVE).removeClass(direction).removeClass(directionalClassName);
+
+          _this3._isSliding = false;
+
+          setTimeout(function () {
+            return $(_this3._element).trigger(slidEvent);
+          }, 0);
+        }).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        $(activeElement).removeClass(ClassName.ACTIVE);
+        $(nextElement).addClass(ClassName.ACTIVE);
+
+        this._isSliding = false;
+        $(this._element).trigger(slidEvent);
+      }
+
+      if (isCycling) {
+        this.cycle();
+      }
+    };
+
+    // static
+
+    Carousel._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Default, $(this).data());
+
+        if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
+          $.extend(_config, config);
+        }
+
+        var action = typeof config === 'string' ? config : _config.slide;
+
+        if (!data) {
+          data = new Carousel(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'number') {
+          data.to(config);
+        } else if (typeof action === 'string') {
+          if (data[action] === undefined) {
+            throw new Error('No method named "' + action + '"');
+          }
+          data[action]();
+        } else if (_config.interval) {
+          data.pause();
+          data.cycle();
+        }
+      });
+    };
+
+    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
+      var selector = Util.getSelectorFromElement(this);
+
+      if (!selector) {
+        return;
+      }
+
+      var target = $(selector)[0];
+
+      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {
+        return;
+      }
+
+      var config = $.extend({}, $(target).data(), $(this).data());
+      var slideIndex = this.getAttribute('data-slide-to');
+
+      if (slideIndex) {
+        config.interval = false;
+      }
+
+      Carousel._jQueryInterface.call($(target), config);
+
+      if (slideIndex) {
+        $(target).data(DATA_KEY).to(slideIndex);
+      }
+
+      event.preventDefault();
+    };
+
+    _createClass(Carousel, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Carousel;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    $(Selector.DATA_RIDE).each(function () {
+      var $carousel = $(this);
+      Carousel._jQueryInterface.call($carousel, $carousel.data());
+    });
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Carousel._jQueryInterface;
+  $.fn[NAME].Constructor = Carousel;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Carousel._jQueryInterface;
+  };
+
+  return Carousel;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): collapse.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Collapse = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'collapse';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.collapse';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+
+  var Default = {
+    toggle: true,
+    parent: ''
+  };
+
+  var DefaultType = {
+    toggle: 'boolean',
+    parent: 'string'
+  };
+
+  var Event = {
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    IN: 'in',
+    COLLAPSE: 'collapse',
+    COLLAPSING: 'collapsing',
+    COLLAPSED: 'collapsed'
+  };
+
+  var Dimension = {
+    WIDTH: 'width',
+    HEIGHT: 'height'
+  };
+
+  var Selector = {
+    ACTIVES: '.card > .in, .card > .collapsing',
+    DATA_TOGGLE: '[data-toggle="collapse"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Collapse = function () {
+    function Collapse(element, config) {
+      _classCallCheck(this, Collapse);
+
+      this._isTransitioning = false;
+      this._element = element;
+      this._config = this._getConfig(config);
+      this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
+
+      this._parent = this._config.parent ? this._getParent() : null;
+
+      if (!this._config.parent) {
+        this._addAriaAndCollapsedClass(this._element, this._triggerArray);
+      }
+
+      if (this._config.toggle) {
+        this.toggle();
+      }
+    }
+
+    // getters
+
+    // public
+
+    Collapse.prototype.toggle = function toggle() {
+      if ($(this._element).hasClass(ClassName.IN)) {
+        this.hide();
+      } else {
+        this.show();
+      }
+    };
+
+    Collapse.prototype.show = function show() {
+      var _this4 = this;
+
+      if (this._isTransitioning || $(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var actives = void 0;
+      var activesData = void 0;
+
+      if (this._parent) {
+        actives = $.makeArray($(Selector.ACTIVES));
+        if (!actives.length) {
+          actives = null;
+        }
+      }
+
+      if (actives) {
+        activesData = $(actives).data(DATA_KEY);
+        if (activesData && activesData._isTransitioning) {
+          return;
+        }
+      }
+
+      var startEvent = $.Event(Event.SHOW);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (actives) {
+        Collapse._jQueryInterface.call($(actives), 'hide');
+        if (!activesData) {
+          $(actives).data(DATA_KEY, null);
+        }
+      }
+
+      var dimension = this._getDimension();
+
+      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
+
+      this._element.style[dimension] = 0;
+      this._element.setAttribute('aria-expanded', true);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        $(_this4._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.IN);
+
+        _this4._element.style[dimension] = '';
+
+        _this4.setTransitioning(false);
+
+        $(_this4._element).trigger(Event.SHOWN);
+      };
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
+      var scrollSize = 'scroll' + capitalizedDimension;
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+
+      this._element.style[dimension] = this._element[scrollSize] + 'px';
+    };
+
+    Collapse.prototype.hide = function hide() {
+      var _this5 = this;
+
+      if (this._isTransitioning || !$(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var startEvent = $.Event(Event.HIDE);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      var dimension = this._getDimension();
+      var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight';
+
+      this._element.style[dimension] = this._element[offsetDimension] + 'px';
+
+      Util.reflow(this._element);
+
+      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.IN);
+
+      this._element.setAttribute('aria-expanded', false);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        _this5.setTransitioning(false);
+        $(_this5._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
+      };
+
+      this._element.style[dimension] = '';
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Collapse.prototype.setTransitioning = function setTransitioning(isTransitioning) {
+      this._isTransitioning = isTransitioning;
+    };
+
+    Collapse.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      this._config = null;
+      this._parent = null;
+      this._element = null;
+      this._triggerArray = null;
+      this._isTransitioning = null;
+    };
+
+    // private
+
+    Collapse.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      config.toggle = Boolean(config.toggle); // coerce string values
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Collapse.prototype._getDimension = function _getDimension() {
+      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);
+      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
+    };
+
+    Collapse.prototype._getParent = function _getParent() {
+      var _this6 = this;
+
+      var parent = $(this._config.parent)[0];
+      var selector = '[data-toggle="collapse"][data-parent="' + this._config.parent + '"]';
+
+      $(parent).find(selector).each(function (i, element) {
+        _this6._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
+      });
+
+      return parent;
+    };
+
+    Collapse.prototype._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
+      if (element) {
+        var isOpen = $(element).hasClass(ClassName.IN);
+        element.setAttribute('aria-expanded', isOpen);
+
+        if (triggerArray.length) {
+          $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
+        }
+      }
+    };
+
+    // static
+
+    Collapse._getTargetFromElement = function _getTargetFromElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      return selector ? $(selector)[0] : null;
+    };
+
+    Collapse._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+        var _config = $.extend({}, Default, $this.data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data && _config.toggle && /show|hide/.test(config)) {
+          _config.toggle = false;
+        }
+
+        if (!data) {
+          data = new Collapse(this, _config);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Collapse, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Collapse;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+
+    var target = Collapse._getTargetFromElement(this);
+    var data = $(target).data(DATA_KEY);
+    var config = data ? 'toggle' : $(this).data();
+
+    Collapse._jQueryInterface.call($(target), config);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Collapse._jQueryInterface;
+  $.fn[NAME].Constructor = Collapse;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Collapse._jQueryInterface;
+  };
+
+  return Collapse;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): dropdown.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Dropdown = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'dropdown';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.dropdown';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
+  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
+  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    BACKDROP: 'dropdown-backdrop',
+    DISABLED: 'disabled',
+    OPEN: 'open'
+  };
+
+  var Selector = {
+    BACKDROP: '.dropdown-backdrop',
+    DATA_TOGGLE: '[data-toggle="dropdown"]',
+    FORM_CHILD: '.dropdown form',
+    ROLE_MENU: '[role="menu"]',
+    ROLE_LISTBOX: '[role="listbox"]',
+    NAVBAR_NAV: '.navbar-nav',
+    VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Dropdown = function () {
+    function Dropdown(element) {
+      _classCallCheck(this, Dropdown);
+
+      this._element = element;
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Dropdown.prototype.toggle = function toggle() {
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return false;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      Dropdown._clearMenus();
+
+      if (isActive) {
+        return false;
+      }
+
+      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
+
+        // if mobile we use a backdrop because click events don't delegate
+        var dropdown = document.createElement('div');
+        dropdown.className = ClassName.BACKDROP;
+        $(dropdown).insertBefore(this);
+        $(dropdown).on('click', Dropdown._clearMenus);
+      }
+
+      var relatedTarget = { relatedTarget: this };
+      var showEvent = $.Event(Event.SHOW, relatedTarget);
+
+      $(parent).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented()) {
+        return false;
+      }
+
+      this.focus();
+      this.setAttribute('aria-expanded', 'true');
+
+      $(parent).toggleClass(ClassName.OPEN);
+      $(parent).trigger($.Event(Event.SHOWN, relatedTarget));
+
+      return false;
+    };
+
+    Dropdown.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._element).off(EVENT_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Dropdown.prototype._addEventListeners = function _addEventListeners() {
+      $(this._element).on(Event.CLICK, this.toggle);
+    };
+
+    // static
+
+    Dropdown._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          $(this).data(DATA_KEY, data = new Dropdown(this));
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config].call(this);
+        }
+      });
+    };
+
+    Dropdown._clearMenus = function _clearMenus(event) {
+      if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
+        return;
+      }
+
+      var backdrop = $(Selector.BACKDROP)[0];
+      if (backdrop) {
+        backdrop.parentNode.removeChild(backdrop);
+      }
+
+      var toggles = $.makeArray($(Selector.DATA_TOGGLE));
+
+      for (var i = 0; i < toggles.length; i++) {
+        var parent = Dropdown._getParentFromElement(toggles[i]);
+        var relatedTarget = { relatedTarget: toggles[i] };
+
+        if (!$(parent).hasClass(ClassName.OPEN)) {
+          continue;
+        }
+
+        if (event && event.type === 'click' && /input|textarea/i.test(event.target.tagName) && $.contains(parent, event.target)) {
+          continue;
+        }
+
+        var hideEvent = $.Event(Event.HIDE, relatedTarget);
+        $(parent).trigger(hideEvent);
+        if (hideEvent.isDefaultPrevented()) {
+          continue;
+        }
+
+        toggles[i].setAttribute('aria-expanded', 'false');
+
+        $(parent).removeClass(ClassName.OPEN).trigger($.Event(Event.HIDDEN, relatedTarget));
+      }
+    };
+
+    Dropdown._getParentFromElement = function _getParentFromElement(element) {
+      var parent = void 0;
+      var selector = Util.getSelectorFromElement(element);
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      return parent || element.parentNode;
+    };
+
+    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
+      if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      event.preventDefault();
+      event.stopPropagation();
+
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {
+
+        if (event.which === ESCAPE_KEYCODE) {
+          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
+          $(toggle).trigger('focus');
+        }
+
+        $(this).trigger('click');
+        return;
+      }
+
+      var items = $.makeArray($(Selector.VISIBLE_ITEMS));
+
+      items = items.filter(function (item) {
+        return item.offsetWidth || item.offsetHeight;
+      });
+
+      if (!items.length) {
+        return;
+      }
+
+      var index = items.indexOf(event.target);
+
+      if (event.which === ARROW_UP_KEYCODE && index > 0) {
+        // up
+        index--;
+      }
+
+      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
+        // down
+        index++;
+      }
+
+      if (index < 0) {
+        index = 0;
+      }
+
+      items[index].focus();
+    };
+
+    _createClass(Dropdown, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Dropdown;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
+    e.stopPropagation();
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Dropdown._jQueryInterface;
+  $.fn[NAME].Constructor = Dropdown;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Dropdown._jQueryInterface;
+  };
+
+  return Dropdown;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): modal.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Modal = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'modal';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.modal';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 300;
+  var BACKDROP_TRANSITION_DURATION = 150;
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+
+  var Default = {
+    backdrop: true,
+    keyboard: true,
+    focus: true,
+    show: true
+  };
+
+  var DefaultType = {
+    backdrop: '(boolean|string)',
+    keyboard: 'boolean',
+    focus: 'boolean',
+    show: 'boolean'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    RESIZE: 'resize' + EVENT_KEY,
+    CLICK_DISMISS: 'click.dismiss' + EVENT_KEY,
+    KEYDOWN_DISMISS: 'keydown.dismiss' + EVENT_KEY,
+    MOUSEUP_DISMISS: 'mouseup.dismiss' + EVENT_KEY,
+    MOUSEDOWN_DISMISS: 'mousedown.dismiss' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
+    BACKDROP: 'modal-backdrop',
+    OPEN: 'modal-open',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    DIALOG: '.modal-dialog',
+    DATA_TOGGLE: '[data-toggle="modal"]',
+    DATA_DISMISS: '[data-dismiss="modal"]',
+    FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Modal = function () {
+    function Modal(element, config) {
+      _classCallCheck(this, Modal);
+
+      this._config = this._getConfig(config);
+      this._element = element;
+      this._dialog = $(element).find(Selector.DIALOG)[0];
+      this._backdrop = null;
+      this._isShown = false;
+      this._isBodyOverflowing = false;
+      this._ignoreBackdropClick = false;
+      this._originalBodyPadding = 0;
+      this._scrollbarWidth = 0;
+    }
+
+    // getters
+
+    // public
+
+    Modal.prototype.toggle = function toggle(relatedTarget) {
+      return this._isShown ? this.hide() : this.show(relatedTarget);
+    };
+
+    Modal.prototype.show = function show(relatedTarget) {
+      var _this7 = this;
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: relatedTarget
+      });
+
+      $(this._element).trigger(showEvent);
+
+      if (this._isShown || showEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = true;
+
+      this._checkScrollbar();
+      this._setScrollbar();
+
+      $(document.body).addClass(ClassName.OPEN);
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, $.proxy(this.hide, this));
+
+      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
+        $(_this7._element).one(Event.MOUSEUP_DISMISS, function (event) {
+          if ($(event.target).is(_this7._element)) {
+            _this7._ignoreBackdropClick = true;
+          }
+        });
+      });
+
+      this._showBackdrop($.proxy(this._showElement, this, relatedTarget));
+    };
+
+    Modal.prototype.hide = function hide(event) {
+      if (event) {
+        event.preventDefault();
+      }
+
+      var hideEvent = $.Event(Event.HIDE);
+
+      $(this._element).trigger(hideEvent);
+
+      if (!this._isShown || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = false;
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(document).off(Event.FOCUSIN);
+
+      $(this._element).removeClass(ClassName.IN);
+
+      $(this._element).off(Event.CLICK_DISMISS);
+      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+
+        $(this._element).one(Util.TRANSITION_END, $.proxy(this._hideModal, this)).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        this._hideModal();
+      }
+    };
+
+    Modal.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      $(window).off(EVENT_KEY);
+      $(document).off(EVENT_KEY);
+      $(this._element).off(EVENT_KEY);
+      $(this._backdrop).off(EVENT_KEY);
+
+      this._config = null;
+      this._element = null;
+      this._dialog = null;
+      this._backdrop = null;
+      this._isShown = null;
+      this._isBodyOverflowing = null;
+      this._ignoreBackdropClick = null;
+      this._originalBodyPadding = null;
+      this._scrollbarWidth = null;
+    };
+
+    // private
+
+    Modal.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Modal.prototype._showElement = function _showElement(relatedTarget) {
+      var _this8 = this;
+
+      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);
+
+      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
+        // don't move modals dom position
+        document.body.appendChild(this._element);
+      }
+
+      this._element.style.display = 'block';
+      this._element.removeAttribute('aria-hidden');
+      this._element.scrollTop = 0;
+
+      if (transition) {
+        Util.reflow(this._element);
+      }
+
+      $(this._element).addClass(ClassName.IN);
+
+      if (this._config.focus) {
+        this._enforceFocus();
+      }
+
+      var shownEvent = $.Event(Event.SHOWN, {
+        relatedTarget: relatedTarget
+      });
+
+      var transitionComplete = function transitionComplete() {
+        if (_this8._config.focus) {
+          _this8._element.focus();
+        }
+        $(_this8._element).trigger(shownEvent);
+      };
+
+      if (transition) {
+        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        transitionComplete();
+      }
+    };
+
+    Modal.prototype._enforceFocus = function _enforceFocus() {
+      var _this9 = this;
+
+      $(document).off(Event.FOCUSIN) // guard against infinite focus loop
+      .on(Event.FOCUSIN, function (event) {
+        if (document !== event.target && _this9._element !== event.target && !$(_this9._element).has(event.target).length) {
+          _this9._element.focus();
+        }
+      });
+    };
+
+    Modal.prototype._setEscapeEvent = function _setEscapeEvent() {
+      var _this10 = this;
+
+      if (this._isShown && this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
+          if (event.which === ESCAPE_KEYCODE) {
+            _this10.hide();
+          }
+        });
+      } else if (!this._isShown) {
+        $(this._element).off(Event.KEYDOWN_DISMISS);
+      }
+    };
+
+    Modal.prototype._setResizeEvent = function _setResizeEvent() {
+      if (this._isShown) {
+        $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this));
+      } else {
+        $(window).off(Event.RESIZE);
+      }
+    };
+
+    Modal.prototype._hideModal = function _hideModal() {
+      var _this11 = this;
+
+      this._element.style.display = 'none';
+      this._element.setAttribute('aria-hidden', 'true');
+      this._showBackdrop(function () {
+        $(document.body).removeClass(ClassName.OPEN);
+        _this11._resetAdjustments();
+        _this11._resetScrollbar();
+        $(_this11._element).trigger(Event.HIDDEN);
+      });
+    };
+
+    Modal.prototype._removeBackdrop = function _removeBackdrop() {
+      if (this._backdrop) {
+        $(this._backdrop).remove();
+        this._backdrop = null;
+      }
+    };
+
+    Modal.prototype._showBackdrop = function _showBackdrop(callback) {
+      var _this12 = this;
+
+      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
+
+      if (this._isShown && this._config.backdrop) {
+        var doAnimate = Util.supportsTransitionEnd() && animate;
+
+        this._backdrop = document.createElement('div');
+        this._backdrop.className = ClassName.BACKDROP;
+
+        if (animate) {
+          $(this._backdrop).addClass(animate);
+        }
+
+        $(this._backdrop).appendTo(document.body);
+
+        $(this._element).on(Event.CLICK_DISMISS, function (event) {
+          if (_this12._ignoreBackdropClick) {
+            _this12._ignoreBackdropClick = false;
+            return;
+          }
+          if (event.target !== event.currentTarget) {
+            return;
+          }
+          if (_this12._config.backdrop === 'static') {
+            _this12._element.focus();
+          } else {
+            _this12.hide();
+          }
+        });
+
+        if (doAnimate) {
+          Util.reflow(this._backdrop);
+        }
+
+        $(this._backdrop).addClass(ClassName.IN);
+
+        if (!callback) {
+          return;
+        }
+
+        if (!doAnimate) {
+          callback();
+          return;
+        }
+
+        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+      } else if (!this._isShown && this._backdrop) {
+        $(this._backdrop).removeClass(ClassName.IN);
+
+        var callbackRemove = function callbackRemove() {
+          _this12._removeBackdrop();
+          if (callback) {
+            callback();
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+        } else {
+          callbackRemove();
+        }
+      } else if (callback) {
+        callback();
+      }
+    };
+
+    // ----------------------------------------------------------------------
+    // the following methods are used to handle overflowing modals
+    // todo (fat): these should probably be refactored out of modal.js
+    // ----------------------------------------------------------------------
+
+    Modal.prototype._handleUpdate = function _handleUpdate() {
+      this._adjustDialog();
+    };
+
+    Modal.prototype._adjustDialog = function _adjustDialog() {
+      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+      if (!this._isBodyOverflowing && isModalOverflowing) {
+        this._element.style.paddingLeft = this._scrollbarWidth + 'px';
+      }
+
+      if (this._isBodyOverflowing && !isModalOverflowing) {
+        this._element.style.paddingRight = this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetAdjustments = function _resetAdjustments() {
+      this._element.style.paddingLeft = '';
+      this._element.style.paddingRight = '';
+    };
+
+    Modal.prototype._checkScrollbar = function _checkScrollbar() {
+      this._isBodyOverflowing = document.body.clientWidth < window.innerWidth;
+      this._scrollbarWidth = this._getScrollbarWidth();
+    };
+
+    Modal.prototype._setScrollbar = function _setScrollbar() {
+      var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10);
+
+      this._originalBodyPadding = document.body.style.paddingRight || '';
+
+      if (this._isBodyOverflowing) {
+        document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetScrollbar = function _resetScrollbar() {
+      document.body.style.paddingRight = this._originalBodyPadding;
+    };
+
+    Modal.prototype._getScrollbarWidth = function _getScrollbarWidth() {
+      // thx d.walsh
+      var scrollDiv = document.createElement('div');
+      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
+      document.body.appendChild(scrollDiv);
+      var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+      document.body.removeChild(scrollDiv);
+      return scrollbarWidth;
+    };
+
+    // static
+
+    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Modal.Default, $(this).data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data) {
+          data = new Modal(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config](relatedTarget);
+        } else if (_config.show) {
+          data.show(relatedTarget);
+        }
+      });
+    };
+
+    _createClass(Modal, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Modal;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    var _this13 = this;
+
+    var target = void 0;
+    var selector = Util.getSelectorFromElement(this);
+
+    if (selector) {
+      target = $(selector)[0];
+    }
+
+    var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data());
+
+    if (this.tagName === 'A') {
+      event.preventDefault();
+    }
+
+    var $target = $(target).one(Event.SHOW, function (showEvent) {
+      if (showEvent.isDefaultPrevented()) {
+        // only register focus restorer if modal will actually get shown
+        return;
+      }
+
+      $target.one(Event.HIDDEN, function () {
+        if ($(_this13).is(':visible')) {
+          _this13.focus();
+        }
+      });
+    });
+
+    Modal._jQueryInterface.call($(target), config, this);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Modal._jQueryInterface;
+  $.fn[NAME].Constructor = Modal;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Modal._jQueryInterface;
+  };
+
+  return Modal;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): scrollspy.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var ScrollSpy = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'scrollspy';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.scrollspy';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = {
+    offset: 10,
+    method: 'auto',
+    target: ''
+  };
+
+  var DefaultType = {
+    offset: 'number',
+    method: 'string',
+    target: '(string|element)'
+  };
+
+  var Event = {
+    ACTIVATE: 'activate' + EVENT_KEY,
+    SCROLL: 'scroll' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_ITEM: 'dropdown-item',
+    DROPDOWN_MENU: 'dropdown-menu',
+    NAV_LINK: 'nav-link',
+    NAV: 'nav',
+    ACTIVE: 'active'
+  };
+
+  var Selector = {
+    DATA_SPY: '[data-spy="scroll"]',
+    ACTIVE: '.active',
+    LIST_ITEM: '.list-item',
+    LI: 'li',
+    LI_DROPDOWN: 'li.dropdown',
+    NAV_LINKS: '.nav-link',
+    DROPDOWN: '.dropdown',
+    DROPDOWN_ITEMS: '.dropdown-item',
+    DROPDOWN_TOGGLE: '.dropdown-toggle'
+  };
+
+  var OffsetMethod = {
+    OFFSET: 'offset',
+    POSITION: 'position'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var ScrollSpy = function () {
+    function ScrollSpy(element, config) {
+      _classCallCheck(this, ScrollSpy);
+
+      this._element = element;
+      this._scrollElement = element.tagName === 'BODY' ? window : element;
+      this._config = this._getConfig(config);
+      this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
+      this._offsets = [];
+      this._targets = [];
+      this._activeTarget = null;
+      this._scrollHeight = 0;
+
+      $(this._scrollElement).on(Event.SCROLL, $.proxy(this._process, this));
+
+      this.refresh();
+      this._process();
+    }
+
+    // getters
+
+    // public
+
+    ScrollSpy.prototype.refresh = function refresh() {
+      var _this14 = this;
+
+      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
+
+      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
+
+      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
+
+      this._offsets = [];
+      this._targets = [];
+
+      this._scrollHeight = this._getScrollHeight();
+
+      var targets = $.makeArray($(this._selector));
+
+      targets.map(function (element) {
+        var target = void 0;
+        var targetSelector = Util.getSelectorFromElement(element);
+
+        if (targetSelector) {
+          target = $(targetSelector)[0];
+        }
+
+        if (target && (target.offsetWidth || target.offsetHeight)) {
+          // todo (fat): remove sketch reliance on jQuery position/offset
+          return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
+        }
+        return null;
+      }).filter(function (item) {
+        return item;
+      }).sort(function (a, b) {
+        return a[0] - b[0];
+      }).forEach(function (item) {
+        _this14._offsets.push(item[0]);
+        _this14._targets.push(item[1]);
+      });
+    };
+
+    ScrollSpy.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._scrollElement).off(EVENT_KEY);
+
+      this._element = null;
+      this._scrollElement = null;
+      this._config = null;
+      this._selector = null;
+      this._offsets = null;
+      this._targets = null;
+      this._activeTarget = null;
+      this._scrollHeight = null;
+    };
+
+    // private
+
+    ScrollSpy.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+
+      if (typeof config.target !== 'string') {
+        var id = $(config.target).attr('id');
+        if (!id) {
+          id = Util.getUID(NAME);
+          $(config.target).attr('id', id);
+        }
+        config.target = '#' + id;
+      }
+
+      Util.typeCheckConfig(NAME, config, DefaultType);
+
+      return config;
+    };
+
+    ScrollSpy.prototype._getScrollTop = function _getScrollTop() {
+      return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
+    };
+
+    ScrollSpy.prototype._getScrollHeight = function _getScrollHeight() {
+      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
+    };
+
+    ScrollSpy.prototype._process = function _process() {
+      var scrollTop = this._getScrollTop() + this._config.offset;
+      var scrollHeight = this._getScrollHeight();
+      var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight;
+
+      if (this._scrollHeight !== scrollHeight) {
+        this.refresh();
+      }
+
+      if (scrollTop >= maxScroll) {
+        var target = this._targets[this._targets.length - 1];
+
+        if (this._activeTarget !== target) {
+          this._activate(target);
+        }
+      }
+
+      if (this._activeTarget && scrollTop < this._offsets[0]) {
+        this._activeTarget = null;
+        this._clear();
+        return;
+      }
+
+      for (var i = this._offsets.length; i--;) {
+        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (this._offsets[i + 1] === undefined || scrollTop < this._offsets[i + 1]);
+
+        if (isActiveTarget) {
+          this._activate(this._targets[i]);
+        }
+      }
+    };
+
+    ScrollSpy.prototype._activate = function _activate(target) {
+      this._activeTarget = target;
+
+      this._clear();
+
+      var queries = this._selector.split(',');
+      queries = queries.map(function (selector) {
+        return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
+      });
+
+      var $link = $(queries.join(','));
+
+      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
+        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        $link.addClass(ClassName.ACTIVE);
+      } else {
+        // todo (fat) this is kinda sus...
+        // recursively add actives to tested nav-links
+        $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
+      }
+
+      $(this._scrollElement).trigger(Event.ACTIVATE, {
+        relatedTarget: target
+      });
+    };
+
+    ScrollSpy.prototype._clear = function _clear() {
+      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+    };
+
+    // static
+
+    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config || null;
+
+        if (!data) {
+          data = new ScrollSpy(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(ScrollSpy, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return ScrollSpy;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    var scrollSpys = $.makeArray($(Selector.DATA_SPY));
+
+    for (var i = scrollSpys.length; i--;) {
+      var $spy = $(scrollSpys[i]);
+      ScrollSpy._jQueryInterface.call($spy, $spy.data());
+    }
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = ScrollSpy._jQueryInterface;
+  $.fn[NAME].Constructor = ScrollSpy;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return ScrollSpy._jQueryInterface;
+  };
+
+  return ScrollSpy;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tab.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tab = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tab';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tab';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_MENU: 'dropdown-menu',
+    ACTIVE: 'active',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    A: 'a',
+    LI: 'li',
+    DROPDOWN: '.dropdown',
+    UL: 'ul:not(.dropdown-menu)',
+    FADE_CHILD: '> .nav-item .fade, > .fade',
+    ACTIVE: '.active',
+    ACTIVE_CHILD: '> .nav-item > .active, > .active',
+    DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"]',
+    DROPDOWN_TOGGLE: '.dropdown-toggle',
+    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tab = function () {
+    function Tab(element) {
+      _classCallCheck(this, Tab);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Tab.prototype.show = function show() {
+      var _this15 = this;
+
+      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE)) {
+        return;
+      }
+
+      var target = void 0;
+      var previous = void 0;
+      var ulElement = $(this._element).closest(Selector.UL)[0];
+      var selector = Util.getSelectorFromElement(this._element);
+
+      if (ulElement) {
+        previous = $.makeArray($(ulElement).find(Selector.ACTIVE));
+        previous = previous[previous.length - 1];
+      }
+
+      var hideEvent = $.Event(Event.HIDE, {
+        relatedTarget: this._element
+      });
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: previous
+      });
+
+      if (previous) {
+        $(previous).trigger(hideEvent);
+      }
+
+      $(this._element).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (selector) {
+        target = $(selector)[0];
+      }
+
+      this._activate(this._element, ulElement);
+
+      var complete = function complete() {
+        var hiddenEvent = $.Event(Event.HIDDEN, {
+          relatedTarget: _this15._element
+        });
+
+        var shownEvent = $.Event(Event.SHOWN, {
+          relatedTarget: previous
+        });
+
+        $(previous).trigger(hiddenEvent);
+        $(_this15._element).trigger(shownEvent);
+      };
+
+      if (target) {
+        this._activate(target, target.parentNode, complete);
+      } else {
+        complete();
+      }
+    };
+
+    Tab.prototype.dispose = function dispose() {
+      $.removeClass(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Tab.prototype._activate = function _activate(element, container, callback) {
+      var active = $(container).find(Selector.ACTIVE_CHILD)[0];
+      var isTransitioning = callback && Util.supportsTransitionEnd() && (active && $(active).hasClass(ClassName.FADE) || Boolean($(container).find(Selector.FADE_CHILD)[0]));
+
+      var complete = $.proxy(this._transitionComplete, this, element, active, isTransitioning, callback);
+
+      if (active && isTransitioning) {
+        $(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      if (active) {
+        $(active).removeClass(ClassName.IN);
+      }
+    };
+
+    Tab.prototype._transitionComplete = function _transitionComplete(element, active, isTransitioning, callback) {
+      if (active) {
+        $(active).removeClass(ClassName.ACTIVE);
+
+        var dropdownChild = $(active).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
+
+        if (dropdownChild) {
+          $(dropdownChild).removeClass(ClassName.ACTIVE);
+        }
+
+        active.setAttribute('aria-expanded', false);
+      }
+
+      $(element).addClass(ClassName.ACTIVE);
+      element.setAttribute('aria-expanded', true);
+
+      if (isTransitioning) {
+        Util.reflow(element);
+        $(element).addClass(ClassName.IN);
+      } else {
+        $(element).removeClass(ClassName.FADE);
+      }
+
+      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
+
+        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];
+        if (dropdownElement) {
+          $(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        }
+
+        element.setAttribute('aria-expanded', true);
+      }
+
+      if (callback) {
+        callback();
+      }
+    };
+
+    // static
+
+    Tab._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+
+        if (!data) {
+          data = data = new Tab(this);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tab, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Tab;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+    Tab._jQueryInterface.call($(this), 'show');
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tab._jQueryInterface;
+  $.fn[NAME].Constructor = Tab;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tab._jQueryInterface;
+  };
+
+  return Tab;
+}(jQuery);
+
+/* global Tether */
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tooltip.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tooltip = function ($) {
+
+  /**
+   * Check for Tether dependency
+   * Tether - http://tether.io/
+   */
+  if (window.Tether === undefined) {
+    throw new Error('Bootstrap tooltips require Tether (http://tether.io/)');
+  }
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tooltip';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tooltip';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+  var CLASS_PREFIX = 'bs-tether';
+
+  var Default = {
+    animation: true,
+    template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    selector: false,
+    placement: 'top',
+    offset: '0 0',
+    constraints: []
+  };
+
+  var DefaultType = {
+    animation: 'boolean',
+    template: 'string',
+    title: '(string|element|function)',
+    trigger: 'string',
+    delay: '(number|object)',
+    html: 'boolean',
+    selector: '(string|boolean)',
+    placement: '(string|function)',
+    offset: 'string',
+    constraints: 'array'
+  };
+
+  var AttachmentMap = {
+    TOP: 'bottom center',
+    RIGHT: 'middle left',
+    BOTTOM: 'top center',
+    LEFT: 'middle right'
+  };
+
+  var HoverState = {
+    IN: 'in',
+    OUT: 'out'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TOOLTIP: '.tooltip',
+    TOOLTIP_INNER: '.tooltip-inner'
+  };
+
+  var TetherClass = {
+    element: false,
+    enabled: false
+  };
+
+  var Trigger = {
+    HOVER: 'hover',
+    FOCUS: 'focus',
+    CLICK: 'click',
+    MANUAL: 'manual'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tooltip = function () {
+    function Tooltip(element, config) {
+      _classCallCheck(this, Tooltip);
+
+      // private
+      this._isEnabled = true;
+      this._timeout = 0;
+      this._hoverState = '';
+      this._activeTrigger = {};
+      this._tether = null;
+
+      // protected
+      this.element = element;
+      this.config = this._getConfig(config);
+      this.tip = null;
+
+      this._setListeners();
+    }
+
+    // getters
+
+    // public
+
+    Tooltip.prototype.enable = function enable() {
+      this._isEnabled = true;
+    };
+
+    Tooltip.prototype.disable = function disable() {
+      this._isEnabled = false;
+    };
+
+    Tooltip.prototype.toggleEnabled = function toggleEnabled() {
+      this._isEnabled = !this._isEnabled;
+    };
+
+    Tooltip.prototype.toggle = function toggle(event) {
+      if (event) {
+        var dataKey = this.constructor.DATA_KEY;
+        var context = $(event.currentTarget).data(dataKey);
+
+        if (!context) {
+          context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+          $(event.currentTarget).data(dataKey, context);
+        }
+
+        context._activeTrigger.click = !context._activeTrigger.click;
+
+        if (context._isWithActiveTrigger()) {
+          context._enter(null, context);
+        } else {
+          context._leave(null, context);
+        }
+      } else {
+
+        if ($(this.getTipElement()).hasClass(ClassName.IN)) {
+          this._leave(null, this);
+          return;
+        }
+
+        this._enter(null, this);
+      }
+    };
+
+    Tooltip.prototype.dispose = function dispose() {
+      clearTimeout(this._timeout);
+
+      this.cleanupTether();
+
+      $.removeData(this.element, this.constructor.DATA_KEY);
+
+      $(this.element).off(this.constructor.EVENT_KEY);
+
+      if (this.tip) {
+        $(this.tip).remove();
+      }
+
+      this._isEnabled = null;
+      this._timeout = null;
+      this._hoverState = null;
+      this._activeTrigger = null;
+      this._tether = null;
+
+      this.element = null;
+      this.config = null;
+      this.tip = null;
+    };
+
+    Tooltip.prototype.show = function show() {
+      var _this16 = this;
+
+      var showEvent = $.Event(this.constructor.Event.SHOW);
+
+      if (this.isWithContent() && this._isEnabled) {
+        $(this.element).trigger(showEvent);
+
+        var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
+
+        if (showEvent.isDefaultPrevented() || !isInTheDom) {
+          return;
+        }
+
+        var tip = this.getTipElement();
+        var tipId = Util.getUID(this.constructor.NAME);
+
+        tip.setAttribute('id', tipId);
+        this.element.setAttribute('aria-describedby', tipId);
+
+        this.setContent();
+
+        if (this.config.animation) {
+          $(tip).addClass(ClassName.FADE);
+        }
+
+        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
+
+        var attachment = this._getAttachment(placement);
+
+        $(tip).data(this.constructor.DATA_KEY, this).appendTo(document.body);
+
+        $(this.element).trigger(this.constructor.Event.INSERTED);
+
+        this._tether = new Tether({
+          attachment: attachment,
+          element: tip,
+          target: this.element,
+          classes: TetherClass,
+          classPrefix: CLASS_PREFIX,
+          offset: this.config.offset,
+          constraints: this.config.constraints,
+          addTargetClasses: false
+        });
+
+        Util.reflow(tip);
+        this._tether.position();
+
+        $(tip).addClass(ClassName.IN);
+
+        var complete = function complete() {
+          var prevHoverState = _this16._hoverState;
+          _this16._hoverState = null;
+
+          $(_this16.element).trigger(_this16.constructor.Event.SHOWN);
+
+          if (prevHoverState === HoverState.OUT) {
+            _this16._leave(null, _this16);
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
+          return;
+        }
+
+        complete();
+      }
+    };
+
+    Tooltip.prototype.hide = function hide(callback) {
+      var _this17 = this;
+
+      var tip = this.getTipElement();
+      var hideEvent = $.Event(this.constructor.Event.HIDE);
+      var complete = function complete() {
+        if (_this17._hoverState !== HoverState.IN && tip.parentNode) {
+          tip.parentNode.removeChild(tip);
+        }
+
+        _this17.element.removeAttribute('aria-describedby');
+        $(_this17.element).trigger(_this17.constructor.Event.HIDDEN);
+        _this17.cleanupTether();
+
+        if (callback) {
+          callback();
+        }
+      };
+
+      $(this.element).trigger(hideEvent);
+
+      if (hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      $(tip).removeClass(ClassName.IN);
+
+      if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+
+        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      this._hoverState = '';
+    };
+
+    // protected
+
+    Tooltip.prototype.isWithContent = function isWithContent() {
+      return Boolean(this.getTitle());
+    };
+
+    Tooltip.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Tooltip.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    Tooltip.prototype.setElementContent = function setElementContent($element, content) {
+      var html = this.config.html;
+      if ((typeof content === 'undefined' ? 'undefined' : _typeof(content)) === 'object' && (content.nodeType || content.jquery)) {
+        // content is a DOM node or a jQuery
+        if (html) {
+          if (!$(content).parent().is($element)) {
+            $element.empty().append(content);
+          }
+        } else {
+          $element.text($(content).text());
+        }
+      } else {
+        $element[html ? 'html' : 'text'](content);
+      }
+    };
+
+    Tooltip.prototype.getTitle = function getTitle() {
+      var title = this.element.getAttribute('data-original-title');
+
+      if (!title) {
+        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
+      }
+
+      return title;
+    };
+
+    Tooltip.prototype.cleanupTether = function cleanupTether() {
+      if (this._tether) {
+        this._tether.destroy();
+      }
+    };
+
+    // private
+
+    Tooltip.prototype._getAttachment = function _getAttachment(placement) {
+      return AttachmentMap[placement.toUpperCase()];
+    };
+
+    Tooltip.prototype._setListeners = function _setListeners() {
+      var _this18 = this;
+
+      var triggers = this.config.trigger.split(' ');
+
+      triggers.forEach(function (trigger) {
+        if (trigger === 'click') {
+          $(_this18.element).on(_this18.constructor.Event.CLICK, _this18.config.selector, $.proxy(_this18.toggle, _this18));
+        } else if (trigger !== Trigger.MANUAL) {
+          var eventIn = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSEENTER : _this18.constructor.Event.FOCUSIN;
+          var eventOut = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSELEAVE : _this18.constructor.Event.FOCUSOUT;
+
+          $(_this18.element).on(eventIn, _this18.config.selector, $.proxy(_this18._enter, _this18)).on(eventOut, _this18.config.selector, $.proxy(_this18._leave, _this18));
+        }
+      });
+
+      if (this.config.selector) {
+        this.config = $.extend({}, this.config, {
+          trigger: 'manual',
+          selector: ''
+        });
+      } else {
+        this._fixTitle();
+      }
+    };
+
+    Tooltip.prototype._fixTitle = function _fixTitle() {
+      var titleType = _typeof(this.element.getAttribute('data-original-title'));
+      if (this.element.getAttribute('title') || titleType !== 'string') {
+        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
+        this.element.setAttribute('title', '');
+      }
+    };
+
+    Tooltip.prototype._enter = function _enter(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
+      }
+
+      if ($(context.getTipElement()).hasClass(ClassName.IN) || context._hoverState === HoverState.IN) {
+        context._hoverState = HoverState.IN;
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.IN;
+
+      if (!context.config.delay || !context.config.delay.show) {
+        context.show();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.IN) {
+          context.show();
+        }
+      }, context.config.delay.show);
+    };
+
+    Tooltip.prototype._leave = function _leave(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
+      }
+
+      if (context._isWithActiveTrigger()) {
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.OUT;
+
+      if (!context.config.delay || !context.config.delay.hide) {
+        context.hide();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.OUT) {
+          context.hide();
+        }
+      }, context.config.delay.hide);
+    };
+
+    Tooltip.prototype._isWithActiveTrigger = function _isWithActiveTrigger() {
+      for (var trigger in this._activeTrigger) {
+        if (this._activeTrigger[trigger]) {
+          return true;
+        }
+      }
+
+      return false;
+    };
+
+    Tooltip.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, this.constructor.Default, $(this.element).data(), config);
+
+      if (config.delay && typeof config.delay === 'number') {
+        config.delay = {
+          show: config.delay,
+          hide: config.delay
+        };
+      }
+
+      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
+
+      return config;
+    };
+
+    Tooltip.prototype._getDelegateConfig = function _getDelegateConfig() {
+      var config = {};
+
+      if (this.config) {
+        for (var key in this.config) {
+          if (this.constructor.Default[key] !== this.config[key]) {
+            config[key] = this.config[key];
+          }
+        }
+      }
+
+      return config;
+    };
+
+    // static
+
+    Tooltip._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /dispose|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Tooltip(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tooltip, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Tooltip;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tooltip._jQueryInterface;
+  $.fn[NAME].Constructor = Tooltip;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tooltip._jQueryInterface;
+  };
+
+  return Tooltip;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Popover = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'popover';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.popover';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = $.extend({}, Tooltip.Default, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip">' + '<h3 class="popover-title"></h3>' + '<div class="popover-content"></div></div>'
+  });
+
+  var DefaultType = $.extend({}, Tooltip.DefaultType, {
+    content: '(string|element|function)'
+  });
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TITLE: '.popover-title',
+    CONTENT: '.popover-content'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Popover = function (_Tooltip) {
+    _inherits(Popover, _Tooltip);
+
+    function Popover() {
+      _classCallCheck(this, Popover);
+
+      return _possibleConstructorReturn(this, _Tooltip.apply(this, arguments));
+    }
+
+    // overrides
+
+    Popover.prototype.isWithContent = function isWithContent() {
+      return this.getTitle() || this._getContent();
+    };
+
+    Popover.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Popover.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      // we use append for html objects to maintain js events
+      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
+      this.setElementContent($tip.find(Selector.CONTENT), this._getContent());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    // private
+
+    Popover.prototype._getContent = function _getContent() {
+      return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);
+    };
+
+    // static
+
+    Popover._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /destroy|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Popover(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Popover, null, [{
+      key: 'VERSION',
+
+
+      // getters
+
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Popover;
+  }(Tooltip);
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Popover._jQueryInterface;
+  $.fn[NAME].Constructor = Popover;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Popover._jQueryInterface;
+  };
+
+  return Popover;
+}(jQuery);
+
+}();
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
new file mode 100644
index 0000000..f8559b3
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/resources/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(jQuery),+function(){function a(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function b(a,b){ [...]
+DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},o=function(){function b(a){c(this,b),this._element=a}return b.prototype.show=function(){var b=this;if(!this._element.parentNode||this._element.parentNode.nodeType!==Node.ELEMENT_NODE||!a(this._element).hasClass(m.ACTIVE)){var c=void 0,d=void 0,e=a(this._element).closest(n.UL)[0],g=f.getSelectorFromElement(this._element);e&&(d=a.makeArray(a(e).find(n.ACTIVE)),d=d[d.length-1]);var h=a.Event(l.HIDE,{related [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/tobago-config.xml b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/tobago-config.xml
new file mode 100644
index 0000000..7d0619f
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/resources/META-INF/tobago-config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+    version="3.0">
+  <name>tobago-theme-charlotteville</name>
+  <ordering>
+    <after>
+      <name>tobago-theme-standard</name>
+    </after>
+  </ordering>
+  <theme-definitions>
+    <theme-definition>
+      <name>charlotteville</name>
+      <display-name>Charlotteville</display-name>
+      <fallback>standard</fallback>
+      <versioned>true</versioned>
+      <resources production="true">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+        </excludes>
+        <script name="/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+        <style name="/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+      </resources>
+      <resources production="false">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+        </excludes>
+        <script name="/tobago/charlotteville/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+        <style name="/tobago/charlotteville/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/scss/_custom.scss b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/scss/_custom.scss
new file mode 100644
index 0000000..82508a6
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/scss/_custom.scss
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Bootstrap overrides
+//
+// Copy variables from `_variables.scss` to this file to override default values
+// without modifying source files.
+
+$body-bg:    #ffeecf !default;
+
+// todo: get this from the JAR
+@import "tobago";
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/scss/_tobago.scss b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/scss/_tobago.scss
new file mode 100644
index 0000000..b342151
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-charlotteville/src/main/scss/_tobago.scss
@@ -0,0 +1,918 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+
+/*
+ * theme: standard
+ * agent: standard
+ */
+
+/* box -------------------------------------------------------------- */
+
+.tobago-box-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+
+.tobago-flexLayout {
+    display: -webkit-flex; /* needed e.g. for Safari 8.0.2 */
+    display: -ms-flexbox; /* needed for IE 10 */
+    display: flex;
+    min-width: 0; /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+    flex-direction: column;
+    -webkit-flex-direction: column;
+    -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+    margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd{
+  justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween{
+  justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround{
+  justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  -moz-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+
+.tobago-gridLayout {
+    width: 100%;
+    height: 100%;
+/*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+    vertical-align: top;
+    padding: 0;
+    border-left: 5px solid transparent;
+    border-top: 5px solid transparent;
+    height: 100%; /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+    border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+    border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+
+.tobago-header {
+    margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+    margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+
+.tobago-image-markup-disabled {
+  filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  -webkit-border-radius: 6px 6px 6px 6px;
+  -moz-border-radius: 6px 6px 6px 6px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  -webkit-border-radius: 6px 0 6px 6px;
+  -moz-border-radius: 6px 0 6px 6px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+
+.tobago-selectManyShuttle {
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  flex: 1 0 0px;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: flex;
+  flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  flex: 1 0 0px;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: flex;
+  flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important; /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+.tobago-sheet-paging-markup-center {
+}
+
+.tobago-sheet-paging-markup-right {
+  float:right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important; /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+    padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+    background-color: #0097CF;
+    color: #FFFFFF;
+    cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+
+.tobago-tab {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}.form-horizontal .control-label {
+   margin-top: 10px;
+   margin-bottom: 5px;
+ }
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content:"*";
+  color:red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/pom.xml b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/pom.xml
new file mode 100644
index 0000000..a5054eb
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-theme</artifactId>
+    <version>3.0.3-SNAPSHOT</version>
+  </parent>
+  <artifactId>tobago-theme-richmond</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Theme Richmond</name>
+
+  <properties>
+    <theme.name>richmond</theme.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-standard</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..80ca0ee
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,4 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
+
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.css b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.css
new file mode 100644
index 0000000..a2000e9
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.css
@@ -0,0 +1,7681 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+/*
+ * theme: standard
+ * agent: standard
+ */
+/* box -------------------------------------------------------------- */
+.tobago-box-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+.tobago-flexLayout {
+  display: -webkit-flex;
+  /* needed e.g. for Safari 8.0.2 */
+  display: -ms-flexbox;
+  /* needed for IE 10 */
+  display: -webkit-box;
+  display: flex;
+  min-width: 0;
+  /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+          flex-direction: column;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  -webkit-box-align: baseline;
+  -webkit-align-items: baseline;
+      -ms-flex-align: baseline;
+          align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  -webkit-box-align: end;
+  -webkit-align-items: flex-end;
+      -ms-flex-align: end;
+          align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  -webkit-box-align: start;
+  -webkit-align-items: flex-start;
+      -ms-flex-align: start;
+          align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  -webkit-box-align: stretch;
+  -webkit-align-items: stretch;
+      -ms-flex-align: stretch;
+          align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  -webkit-box-pack: start;
+  -webkit-justify-content: flex-start;
+      -ms-flex-pack: start;
+          justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd {
+  -webkit-box-pack: end;
+  -webkit-justify-content: flex-end;
+      -ms-flex-pack: end;
+          justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween {
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround {
+  -webkit-justify-content: space-around;
+      -ms-flex-pack: distribute;
+          justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+  box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+.tobago-gridLayout {
+  width: 100%;
+  height: 100%;
+  /*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+  vertical-align: top;
+  padding: 0;
+  border-left: 5px solid transparent;
+  border-top: 5px solid transparent;
+  height: 100%;
+  /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+  border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+  border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+.tobago-header {
+  margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+  margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+.tobago-image-markup-disabled {
+  -webkit-filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+          filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal;
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+.tobago-selectManyShuttle {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  -webkit-flex-shrink: 0;
+      -ms-flex-negative: 0;
+          flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important;
+  /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+
+.tobago-sheet-paging-markup-right {
+  float: right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 1 auto;
+      -ms-flex: 1 1 auto;
+          flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important;
+  /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+  padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+  background-color: #0097CF;
+  color: #FFFFFF;
+  cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+.tobago-tab {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}
+
+.form-horizontal .control-label {
+  margin-top: 10px;
+  margin-bottom: 5px;
+}
+
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content: "*";
+  color: red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
+
+/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */
+html {
+  font-family: sans-serif;
+  line-height: 1.15;
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+}
+
+body {
+  margin: 0;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+  display: block;
+}
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+}
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+progress {
+  vertical-align: baseline;
+}
+
+template,
+[hidden] {
+  display: none;
+}
+
+a {
+  background-color: transparent;
+  -webkit-text-decoration-skip: objects;
+}
+
+a:active,
+a:hover {
+  outline-width: 0;
+}
+
+abbr[title] {
+  border-bottom: none;
+  text-decoration: underline;
+  text-decoration: underline dotted;
+}
+
+b,
+strong {
+  font-weight: inherit;
+}
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+dfn {
+  font-style: italic;
+}
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+
+small {
+  font-size: 80%;
+}
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+img {
+  border-style: none;
+}
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+figure {
+  margin: 1em 40px;
+}
+
+hr {
+  -webkit-box-sizing: content-box;
+          box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font: inherit;
+  margin: 0;
+}
+
+optgroup {
+  font-weight: bold;
+}
+
+button,
+input {
+  overflow: visible;
+}
+
+button,
+select {
+  text-transform: none;
+}
+
+button,
+html [type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+legend {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  color: inherit;
+  display: table;
+  max-width: 100%;
+  padding: 0;
+  white-space: normal;
+}
+
+textarea {
+  overflow: auto;
+}
+
+[type="checkbox"],
+[type="radio"] {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+[type="search"] {
+  -webkit-appearance: textfield;
+  outline-offset: -2px;
+}
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54;
+}
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  font: inherit;
+}
+
+@media print {
+  *,
+  *::before,
+  *::after,
+  *::first-letter,
+  p::first-line,
+  div::first-line,
+  blockquote::first-line,
+  li::first-line {
+    text-shadow: none !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  abbr[title]::after {
+    content: " (" attr(title) ")";
+  }
+  pre {
+    white-space: pre-wrap !important;
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  .navbar {
+    display: none;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .tag {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+
+html {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+  -webkit-box-sizing: inherit;
+          box-sizing: inherit;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+html {
+  font-size: 16px;
+  -ms-overflow-style: scrollbar;
+  -webkit-tap-highlight-color: transparent;
+}
+
+body {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-size: 1rem;
+  line-height: 1.5;
+  color: #5facff;
+  background-color: #eceeef;
+}
+
+[tabindex="-1"]:focus {
+  outline: none !important;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 0;
+  margin-bottom: .5rem;
+}
+
+p {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #818a91;
+}
+
+address {
+  margin-bottom: 1rem;
+  font-style: normal;
+  line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+  margin-bottom: 0;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-bottom: .5rem;
+  margin-left: 0;
+}
+
+blockquote {
+  margin: 0 0 1rem;
+}
+
+a {
+  color: #ffd080;
+  text-decoration: none;
+}
+
+a:focus, a:hover {
+  color: #ffb434;
+  text-decoration: underline;
+}
+
+a:focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+a:not([href]):not([tabindex]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus {
+  outline: none;
+}
+
+pre {
+  margin-top: 0;
+  margin-bottom: 1rem;
+  overflow: auto;
+}
+
+figure {
+  margin: 0 0 1rem;
+}
+
+img {
+  vertical-align: middle;
+}
+
+[role="button"] {
+  cursor: pointer;
+}
+
+a,
+area,
+button,
+[role="button"],
+input,
+label,
+select,
+summary,
+textarea {
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+}
+
+table {
+  border-collapse: collapse;
+  background-color: transparent;
+}
+
+caption {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  color: #818a91;
+  text-align: left;
+  caption-side: bottom;
+}
+
+th {
+  text-align: left;
+}
+
+label {
+  display: inline-block;
+  margin-bottom: .5rem;
+}
+
+button:focus {
+  outline: 1px dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+textarea {
+  line-height: inherit;
+}
+
+input[type="radio"]:disabled,
+input[type="checkbox"]:disabled {
+  cursor: not-allowed;
+}
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  -webkit-appearance: listbox;
+}
+
+textarea {
+  resize: vertical;
+}
+
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: .5rem;
+  font-size: 1.5rem;
+  line-height: inherit;
+}
+
+input[type="search"] {
+  -webkit-appearance: none;
+}
+
+output {
+  display: inline-block;
+}
+
+[hidden] {
+  display: none !important;
+}
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  margin-bottom: 0.5rem;
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+
+h1, .h1 {
+  font-size: 2.5rem;
+}
+
+h2, .h2 {
+  font-size: 2rem;
+}
+
+h3, .h3 {
+  font-size: 1.75rem;
+}
+
+h4, .h4 {
+  font-size: 1.5rem;
+}
+
+h5, .h5 {
+  font-size: 1.25rem;
+}
+
+h6, .h6 {
+  font-size: 1rem;
+}
+
+.lead {
+  font-size: 1.25rem;
+  font-weight: 300;
+}
+
+.display-1 {
+  font-size: 6rem;
+  font-weight: 300;
+}
+
+.display-2 {
+  font-size: 5.5rem;
+  font-weight: 300;
+}
+
+.display-3 {
+  font-size: 4.5rem;
+  font-weight: 300;
+}
+
+.display-4 {
+  font-size: 3.5rem;
+  font-weight: 300;
+}
+
+hr {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+small,
+.small {
+  font-size: 80%;
+  font-weight: normal;
+}
+
+mark,
+.mark {
+  padding: 0.2em;
+  background-color: #fcf8e3;
+}
+
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline-item {
+  display: inline-block;
+}
+
+.list-inline-item:not(:last-child) {
+  margin-right: 5px;
+}
+
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+.blockquote {
+  padding: 0.5rem 1rem;
+  margin-bottom: 1rem;
+  font-size: 1.25rem;
+  border-left: 0.25rem solid #eceeef;
+}
+
+.blockquote-footer {
+  display: block;
+  font-size: 80%;
+  color: #818a91;
+}
+
+.blockquote-footer::before {
+  content: "\2014 \00A0";
+}
+
+.blockquote-reverse {
+  padding-right: 1rem;
+  padding-left: 0;
+  text-align: right;
+  border-right: 0.25rem solid #eceeef;
+  border-left: 0;
+}
+
+.blockquote-reverse .blockquote-footer::before {
+  content: "";
+}
+
+.blockquote-reverse .blockquote-footer::after {
+  content: "\00A0 \2014";
+}
+
+dl.row > dd + dt {
+  clear: left;
+}
+
+.img-fluid, .carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  max-width: 100%;
+  height: auto;
+}
+
+.img-thumbnail {
+  padding: 0.25rem;
+  background-color: #eceeef;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  -webkit-transition: all .2s ease-in-out;
+  -o-transition: all .2s ease-in-out;
+  transition: all .2s ease-in-out;
+  max-width: 100%;
+  height: auto;
+}
+
+.figure {
+  display: inline-block;
+}
+
+.figure-img {
+  margin-bottom: 0.5rem;
+  line-height: 1;
+}
+
+.figure-caption {
+  font-size: 90%;
+  color: #818a91;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+code {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #bd4147;
+  background-color: #f7f7f9;
+  border-radius: 0.25rem;
+}
+
+kbd {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 0.2rem;
+}
+
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: bold;
+}
+
+pre {
+  display: block;
+  margin-top: 0;
+  margin-bottom: 1rem;
+  font-size: 90%;
+  color: #373a3c;
+}
+
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  background-color: transparent;
+  border-radius: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+.container {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .container {
+    width: 540px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 768px) {
+  .container {
+    width: 720px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 992px) {
+  .container {
+    width: 960px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container {
+    width: 1140px;
+    max-width: 100%;
+  }
+}
+
+.container-fluid {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container-fluid::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.row::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+.col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg [...]
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+@media (min-width: 576px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+.col-xs-1 {
+  float: left;
+  width: 8.333333%;
+}
+
+.col-xs-2 {
+  float: left;
+  width: 16.666667%;
+}
+
+.col-xs-3 {
+  float: left;
+  width: 25%;
+}
+
+.col-xs-4 {
+  float: left;
+  width: 33.333333%;
+}
+
+.col-xs-5 {
+  float: left;
+  width: 41.666667%;
+}
+
+.col-xs-6 {
+  float: left;
+  width: 50%;
+}
+
+.col-xs-7 {
+  float: left;
+  width: 58.333333%;
+}
+
+.col-xs-8 {
+  float: left;
+  width: 66.666667%;
+}
+
+.col-xs-9 {
+  float: left;
+  width: 75%;
+}
+
+.col-xs-10 {
+  float: left;
+  width: 83.333333%;
+}
+
+.col-xs-11 {
+  float: left;
+  width: 91.666667%;
+}
+
+.col-xs-12 {
+  float: left;
+  width: 100%;
+}
+
+.pull-xs-0 {
+  right: auto;
+}
+
+.pull-xs-1 {
+  right: 8.333333%;
+}
+
+.pull-xs-2 {
+  right: 16.666667%;
+}
+
+.pull-xs-3 {
+  right: 25%;
+}
+
+.pull-xs-4 {
+  right: 33.333333%;
+}
+
+.pull-xs-5 {
+  right: 41.666667%;
+}
+
+.pull-xs-6 {
+  right: 50%;
+}
+
+.pull-xs-7 {
+  right: 58.333333%;
+}
+
+.pull-xs-8 {
+  right: 66.666667%;
+}
+
+.pull-xs-9 {
+  right: 75%;
+}
+
+.pull-xs-10 {
+  right: 83.333333%;
+}
+
+.pull-xs-11 {
+  right: 91.666667%;
+}
+
+.pull-xs-12 {
+  right: 100%;
+}
+
+.push-xs-0 {
+  left: auto;
+}
+
+.push-xs-1 {
+  left: 8.333333%;
+}
+
+.push-xs-2 {
+  left: 16.666667%;
+}
+
+.push-xs-3 {
+  left: 25%;
+}
+
+.push-xs-4 {
+  left: 33.333333%;
+}
+
+.push-xs-5 {
+  left: 41.666667%;
+}
+
+.push-xs-6 {
+  left: 50%;
+}
+
+.push-xs-7 {
+  left: 58.333333%;
+}
+
+.push-xs-8 {
+  left: 66.666667%;
+}
+
+.push-xs-9 {
+  left: 75%;
+}
+
+.push-xs-10 {
+  left: 83.333333%;
+}
+
+.push-xs-11 {
+  left: 91.666667%;
+}
+
+.push-xs-12 {
+  left: 100%;
+}
+
+.offset-xs-1 {
+  margin-left: 8.333333%;
+}
+
+.offset-xs-2 {
+  margin-left: 16.666667%;
+}
+
+.offset-xs-3 {
+  margin-left: 25%;
+}
+
+.offset-xs-4 {
+  margin-left: 33.333333%;
+}
+
+.offset-xs-5 {
+  margin-left: 41.666667%;
+}
+
+.offset-xs-6 {
+  margin-left: 50%;
+}
+
+.offset-xs-7 {
+  margin-left: 58.333333%;
+}
+
+.offset-xs-8 {
+  margin-left: 66.666667%;
+}
+
+.offset-xs-9 {
+  margin-left: 75%;
+}
+
+.offset-xs-10 {
+  margin-left: 83.333333%;
+}
+
+.offset-xs-11 {
+  margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+  .col-sm-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-sm-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-sm-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-sm-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-sm-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-sm-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-sm-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-sm-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-sm-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-sm-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-sm-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-sm-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-sm-0 {
+    right: auto;
+  }
+  .pull-sm-1 {
+    right: 8.333333%;
+  }
+  .pull-sm-2 {
+    right: 16.666667%;
+  }
+  .pull-sm-3 {
+    right: 25%;
+  }
+  .pull-sm-4 {
+    right: 33.333333%;
+  }
+  .pull-sm-5 {
+    right: 41.666667%;
+  }
+  .pull-sm-6 {
+    right: 50%;
+  }
+  .pull-sm-7 {
+    right: 58.333333%;
+  }
+  .pull-sm-8 {
+    right: 66.666667%;
+  }
+  .pull-sm-9 {
+    right: 75%;
+  }
+  .pull-sm-10 {
+    right: 83.333333%;
+  }
+  .pull-sm-11 {
+    right: 91.666667%;
+  }
+  .pull-sm-12 {
+    right: 100%;
+  }
+  .push-sm-0 {
+    left: auto;
+  }
+  .push-sm-1 {
+    left: 8.333333%;
+  }
+  .push-sm-2 {
+    left: 16.666667%;
+  }
+  .push-sm-3 {
+    left: 25%;
+  }
+  .push-sm-4 {
+    left: 33.333333%;
+  }
+  .push-sm-5 {
+    left: 41.666667%;
+  }
+  .push-sm-6 {
+    left: 50%;
+  }
+  .push-sm-7 {
+    left: 58.333333%;
+  }
+  .push-sm-8 {
+    left: 66.666667%;
+  }
+  .push-sm-9 {
+    left: 75%;
+  }
+  .push-sm-10 {
+    left: 83.333333%;
+  }
+  .push-sm-11 {
+    left: 91.666667%;
+  }
+  .push-sm-12 {
+    left: 100%;
+  }
+  .offset-sm-0 {
+    margin-left: 0%;
+  }
+  .offset-sm-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-sm-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-sm-3 {
+    margin-left: 25%;
+  }
+  .offset-sm-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-sm-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-sm-6 {
+    margin-left: 50%;
+  }
+  .offset-sm-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-sm-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-sm-9 {
+    margin-left: 75%;
+  }
+  .offset-sm-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-sm-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-md-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-md-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-md-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-md-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-md-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-md-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-md-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-md-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-md-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-md-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-md-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-md-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-md-0 {
+    right: auto;
+  }
+  .pull-md-1 {
+    right: 8.333333%;
+  }
+  .pull-md-2 {
+    right: 16.666667%;
+  }
+  .pull-md-3 {
+    right: 25%;
+  }
+  .pull-md-4 {
+    right: 33.333333%;
+  }
+  .pull-md-5 {
+    right: 41.666667%;
+  }
+  .pull-md-6 {
+    right: 50%;
+  }
+  .pull-md-7 {
+    right: 58.333333%;
+  }
+  .pull-md-8 {
+    right: 66.666667%;
+  }
+  .pull-md-9 {
+    right: 75%;
+  }
+  .pull-md-10 {
+    right: 83.333333%;
+  }
+  .pull-md-11 {
+    right: 91.666667%;
+  }
+  .pull-md-12 {
+    right: 100%;
+  }
+  .push-md-0 {
+    left: auto;
+  }
+  .push-md-1 {
+    left: 8.333333%;
+  }
+  .push-md-2 {
+    left: 16.666667%;
+  }
+  .push-md-3 {
+    left: 25%;
+  }
+  .push-md-4 {
+    left: 33.333333%;
+  }
+  .push-md-5 {
+    left: 41.666667%;
+  }
+  .push-md-6 {
+    left: 50%;
+  }
+  .push-md-7 {
+    left: 58.333333%;
+  }
+  .push-md-8 {
+    left: 66.666667%;
+  }
+  .push-md-9 {
+    left: 75%;
+  }
+  .push-md-10 {
+    left: 83.333333%;
+  }
+  .push-md-11 {
+    left: 91.666667%;
+  }
+  .push-md-12 {
+    left: 100%;
+  }
+  .offset-md-0 {
+    margin-left: 0%;
+  }
+  .offset-md-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-md-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-md-3 {
+    margin-left: 25%;
+  }
+  .offset-md-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-md-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-md-6 {
+    margin-left: 50%;
+  }
+  .offset-md-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-md-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-md-9 {
+    margin-left: 75%;
+  }
+  .offset-md-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-md-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-lg-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-lg-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-lg-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-lg-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-lg-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-lg-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-lg-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-lg-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-lg-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-lg-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-lg-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-lg-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-lg-0 {
+    right: auto;
+  }
+  .pull-lg-1 {
+    right: 8.333333%;
+  }
+  .pull-lg-2 {
+    right: 16.666667%;
+  }
+  .pull-lg-3 {
+    right: 25%;
+  }
+  .pull-lg-4 {
+    right: 33.333333%;
+  }
+  .pull-lg-5 {
+    right: 41.666667%;
+  }
+  .pull-lg-6 {
+    right: 50%;
+  }
+  .pull-lg-7 {
+    right: 58.333333%;
+  }
+  .pull-lg-8 {
+    right: 66.666667%;
+  }
+  .pull-lg-9 {
+    right: 75%;
+  }
+  .pull-lg-10 {
+    right: 83.333333%;
+  }
+  .pull-lg-11 {
+    right: 91.666667%;
+  }
+  .pull-lg-12 {
+    right: 100%;
+  }
+  .push-lg-0 {
+    left: auto;
+  }
+  .push-lg-1 {
+    left: 8.333333%;
+  }
+  .push-lg-2 {
+    left: 16.666667%;
+  }
+  .push-lg-3 {
+    left: 25%;
+  }
+  .push-lg-4 {
+    left: 33.333333%;
+  }
+  .push-lg-5 {
+    left: 41.666667%;
+  }
+  .push-lg-6 {
+    left: 50%;
+  }
+  .push-lg-7 {
+    left: 58.333333%;
+  }
+  .push-lg-8 {
+    left: 66.666667%;
+  }
+  .push-lg-9 {
+    left: 75%;
+  }
+  .push-lg-10 {
+    left: 83.333333%;
+  }
+  .push-lg-11 {
+    left: 91.666667%;
+  }
+  .push-lg-12 {
+    left: 100%;
+  }
+  .offset-lg-0 {
+    margin-left: 0%;
+  }
+  .offset-lg-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-lg-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-lg-3 {
+    margin-left: 25%;
+  }
+  .offset-lg-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-lg-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-lg-6 {
+    margin-left: 50%;
+  }
+  .offset-lg-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-lg-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-lg-9 {
+    margin-left: 75%;
+  }
+  .offset-lg-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-lg-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xl-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-xl-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-xl-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-xl-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-xl-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-xl-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-xl-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-xl-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-xl-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-xl-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-xl-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-xl-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-xl-0 {
+    right: auto;
+  }
+  .pull-xl-1 {
+    right: 8.333333%;
+  }
+  .pull-xl-2 {
+    right: 16.666667%;
+  }
+  .pull-xl-3 {
+    right: 25%;
+  }
+  .pull-xl-4 {
+    right: 33.333333%;
+  }
+  .pull-xl-5 {
+    right: 41.666667%;
+  }
+  .pull-xl-6 {
+    right: 50%;
+  }
+  .pull-xl-7 {
+    right: 58.333333%;
+  }
+  .pull-xl-8 {
+    right: 66.666667%;
+  }
+  .pull-xl-9 {
+    right: 75%;
+  }
+  .pull-xl-10 {
+    right: 83.333333%;
+  }
+  .pull-xl-11 {
+    right: 91.666667%;
+  }
+  .pull-xl-12 {
+    right: 100%;
+  }
+  .push-xl-0 {
+    left: auto;
+  }
+  .push-xl-1 {
+    left: 8.333333%;
+  }
+  .push-xl-2 {
+    left: 16.666667%;
+  }
+  .push-xl-3 {
+    left: 25%;
+  }
+  .push-xl-4 {
+    left: 33.333333%;
+  }
+  .push-xl-5 {
+    left: 41.666667%;
+  }
+  .push-xl-6 {
+    left: 50%;
+  }
+  .push-xl-7 {
+    left: 58.333333%;
+  }
+  .push-xl-8 {
+    left: 66.666667%;
+  }
+  .push-xl-9 {
+    left: 75%;
+  }
+  .push-xl-10 {
+    left: 83.333333%;
+  }
+  .push-xl-11 {
+    left: 91.666667%;
+  }
+  .push-xl-12 {
+    left: 100%;
+  }
+  .offset-xl-0 {
+    margin-left: 0%;
+  }
+  .offset-xl-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-xl-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-xl-3 {
+    margin-left: 25%;
+  }
+  .offset-xl-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-xl-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-xl-6 {
+    margin-left: 50%;
+  }
+  .offset-xl-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-xl-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-xl-9 {
+    margin-left: 75%;
+  }
+  .offset-xl-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-xl-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 1rem;
+}
+
+.table th,
+.table td {
+  padding: 0.75rem;
+  vertical-align: top;
+  border-top: 1px solid #eceeef;
+}
+
+.table thead th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #eceeef;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #eceeef;
+}
+
+.table .table {
+  background-color: #eceeef;
+}
+
+.table-sm th,
+.table-sm td {
+  padding: 0.3rem;
+}
+
+.table-bordered {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered thead th,
+.table-bordered thead td {
+  border-bottom-width: 2px;
+}
+
+.table-striped tbody tr:nth-of-type(odd) {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+
+.table-hover tbody tr:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-active,
+.table-active > th,
+.table-active > td {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover > td,
+.table-hover .table-active:hover > th {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-success,
+.table-success > th,
+.table-success > td {
+  background-color: #dff0d8;
+}
+
+.table-hover .table-success:hover {
+  background-color: #d0e9c6;
+}
+
+.table-hover .table-success:hover > td,
+.table-hover .table-success:hover > th {
+  background-color: #d0e9c6;
+}
+
+.table-info,
+.table-info > th,
+.table-info > td {
+  background-color: #d9edf7;
+}
+
+.table-hover .table-info:hover {
+  background-color: #c4e3f3;
+}
+
+.table-hover .table-info:hover > td,
+.table-hover .table-info:hover > th {
+  background-color: #c4e3f3;
+}
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+  background-color: #fcf8e3;
+}
+
+.table-hover .table-warning:hover {
+  background-color: #faf2cc;
+}
+
+.table-hover .table-warning:hover > td,
+.table-hover .table-warning:hover > th {
+  background-color: #faf2cc;
+}
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+  background-color: #f2dede;
+}
+
+.table-hover .table-danger:hover {
+  background-color: #ebcccc;
+}
+
+.table-hover .table-danger:hover > td,
+.table-hover .table-danger:hover > th {
+  background-color: #ebcccc;
+}
+
+.thead-inverse th {
+  color: #fff;
+  background-color: #373a3c;
+}
+
+.thead-default th {
+  color: #55595c;
+  background-color: #eceeef;
+}
+
+.table-inverse {
+  color: #eceeef;
+  background-color: #373a3c;
+}
+
+.table-inverse th,
+.table-inverse td,
+.table-inverse thead th {
+  border-color: #55595c;
+}
+
+.table-inverse.table-bordered {
+  border: 0;
+}
+
+.table-responsive {
+  display: block;
+  width: 100%;
+  min-height: 0%;
+  overflow-x: auto;
+}
+
+.table-reflow thead {
+  float: left;
+}
+
+.table-reflow tbody {
+  display: block;
+  white-space: nowrap;
+}
+
+.table-reflow th,
+.table-reflow td {
+  border-top: 1px solid #eceeef;
+  border-left: 1px solid #eceeef;
+}
+
+.table-reflow th:last-child,
+.table-reflow td:last-child {
+  border-right: 1px solid #eceeef;
+}
+
+.table-reflow thead:last-child tr:last-child th,
+.table-reflow thead:last-child tr:last-child td,
+.table-reflow tbody:last-child tr:last-child th,
+.table-reflow tbody:last-child tr:last-child td,
+.table-reflow tfoot:last-child tr:last-child th,
+.table-reflow tfoot:last-child tr:last-child td {
+  border-bottom: 1px solid #eceeef;
+}
+
+.table-reflow tr {
+  float: left;
+}
+
+.table-reflow tr th,
+.table-reflow tr td {
+  display: block !important;
+  border: 1px solid #eceeef;
+}
+
+.form-control {
+  display: block;
+  width: 100%;
+  padding: 0.5rem 0.75rem;
+  font-size: 1rem;
+  line-height: 1.25;
+  color: #55595c;
+  background-color: #fff;
+  background-image: none;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.form-control::-ms-expand {
+  background-color: transparent;
+  border: 0;
+}
+
+.form-control:focus {
+  color: #55595c;
+  background-color: #fff;
+  border-color: #66afe9;
+  outline: none;
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::-moz-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:disabled, .form-control[readonly] {
+  background-color: #eceeef;
+  opacity: 1;
+}
+
+.form-control:disabled {
+  cursor: not-allowed;
+}
+
+select.form-control:not([size]):not([multiple]) {
+  height: calc(2.5rem - 2px);
+}
+
+select.form-control:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.form-control-file,
+.form-control-range {
+  display: block;
+}
+
+.col-form-label {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+}
+
+.col-form-label-lg {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  font-size: 1.25rem;
+}
+
+.col-form-label-sm {
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  font-size: 0.875rem;
+}
+
+.col-form-legend {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+}
+
+.form-control-static {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  line-height: 1.25;
+  border: solid transparent;
+  border-width: 1px 0;
+}
+
+.form-control-static.form-control-sm, .input-group-sm > .form-control-static.form-control,
+.input-group-sm > .form-control-static.input-group-addon,
+.input-group-sm > .input-group-btn > .form-control-static.btn, .form-control-static.form-control-lg, .input-group-lg > .form-control-static.form-control,
+.input-group-lg > .form-control-static.input-group-addon,
+.input-group-lg > .input-group-btn > .form-control-static.btn {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.form-control-sm, .input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),
+.input-group-sm > select.input-group-addon:not([size]):not([multiple]),
+.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 1.8125rem;
+}
+
+.form-control-lg, .input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),
+.input-group-lg > select.input-group-addon:not([size]):not([multiple]),
+.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 3.166667rem;
+}
+
+.form-group {
+  margin-bottom: 1rem;
+}
+
+.form-text {
+  display: block;
+  margin-top: 0.25rem;
+}
+
+.form-check {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+}
+
+.form-check + .form-check {
+  margin-top: -.25rem;
+}
+
+.form-check.disabled .form-check-label {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-check-label {
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  cursor: pointer;
+}
+
+.form-check-input {
+  position: absolute;
+  margin-top: .25rem;
+  margin-left: -1.25rem;
+}
+
+.form-check-input:only-child {
+  position: static;
+}
+
+.form-check-inline {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  vertical-align: middle;
+  cursor: pointer;
+}
+
+.form-check-inline + .form-check-inline {
+  margin-left: .75rem;
+}
+
+.form-check-inline.disabled {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-control-feedback {
+  margin-top: 0.25rem;
+}
+
+.form-control-success,
+.form-control-warning,
+.form-control-danger {
+  padding-right: 2.25rem;
+  background-repeat: no-repeat;
+  background-position: center right 0.625rem;
+  -webkit-background-size: 1.25rem 1.25rem;
+          background-size: 1.25rem 1.25rem;
+}
+
+.has-success .form-control-feedback,
+.has-success .form-control-label,
+.has-success .form-check-label,
+.has-success .form-check-inline,
+.has-success .custom-control {
+  color: #bcf8ac;
+}
+
+.has-success .form-control {
+  border-color: #bcf8ac;
+}
+
+.has-success .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px white;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px white;
+}
+
+.has-success .input-group-addon {
+  color: #bcf8ac;
+  border-color: #bcf8ac;
+  background-color: white;
+}
+
+.has-success .form-control-success {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#bcf8ac' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");
+}
+
+.has-warning .form-control-feedback,
+.has-warning .form-control-label,
+.has-warning .form-check-label,
+.has-warning .form-check-inline,
+.has-warning .custom-control {
+  color: #f0fd4e;
+}
+
+.has-warning .form-control {
+  border-color: #f0fd4e;
+}
+
+.has-warning .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f9feb3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f9feb3;
+}
+
+.has-warning .input-group-addon {
+  color: #f0fd4e;
+  border-color: #f0fd4e;
+  background-color: white;
+}
+
+.has-warning .form-control-warning {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#f0fd4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E");
+}
+
+.has-danger .form-control-feedback,
+.has-danger .form-control-label,
+.has-danger .form-check-label,
+.has-danger .form-check-inline,
+.has-danger .custom-control {
+  color: #ffa9a9;
+}
+
+.has-danger .form-control {
+  border-color: #ffa9a9;
+}
+
+.has-danger .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px white;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px white;
+}
+
+.has-danger .input-group-addon {
+  color: #ffa9a9;
+  border-color: #ffa9a9;
+  background-color: white;
+}
+
+.has-danger .form-control-danger {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#ffa9a9' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E");
+}
+
+@media (min-width: 576px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-static {
+    display: inline-block;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .form-control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check-label {
+    padding-left: 0;
+  }
+  .form-inline .form-check-input {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+
+.btn {
+  display: inline-block;
+  font-weight: normal;
+  line-height: 1.25;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  border: 1px solid transparent;
+  padding: 0.5rem 1rem;
+  font-size: 1rem;
+  border-radius: 0.25rem;
+}
+
+.btn:focus, .btn.focus, .btn:active:focus, .btn:active.focus, .btn.active:focus, .btn.active.focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn:focus, .btn:hover {
+  text-decoration: none;
+}
+
+.btn.focus {
+  text-decoration: none;
+}
+
+.btn:active, .btn.active {
+  background-image: none;
+  outline: 0;
+}
+
+.btn.disabled, .btn:disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+a.btn.disabled,
+fieldset[disabled] a.btn {
+  pointer-events: none;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.btn-primary:hover {
+  color: #fff;
+  background-color: #ffbd4d;
+  border-color: #ffb943;
+}
+
+.btn-primary:focus, .btn-primary.focus {
+  color: #fff;
+  background-color: #ffbd4d;
+  border-color: #ffb943;
+}
+
+.btn-primary:active, .btn-primary.active,
+.open > .btn-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #ffbd4d;
+  border-color: #ffb943;
+  background-image: none;
+}
+
+.btn-primary:active:hover, .btn-primary:active:focus, .btn-primary:active.focus, .btn-primary.active:hover, .btn-primary.active:focus, .btn-primary.active.focus,
+.open > .btn-primary.dropdown-toggle:hover,
+.open > .btn-primary.dropdown-toggle:focus,
+.open > .btn-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ffb029;
+  border-color: #ffa101;
+}
+
+.btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary:disabled:focus, .btn-primary:disabled.focus {
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.btn-primary.disabled:hover, .btn-primary:disabled:hover {
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.btn-secondary {
+  color: #373a3c;
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary:hover {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:focus, .btn-secondary.focus {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:active, .btn-secondary.active,
+.open > .btn-secondary.dropdown-toggle {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+  background-image: none;
+}
+
+.btn-secondary:active:hover, .btn-secondary:active:focus, .btn-secondary:active.focus, .btn-secondary.active:hover, .btn-secondary.active:focus, .btn-secondary.active.focus,
+.open > .btn-secondary.dropdown-toggle:hover,
+.open > .btn-secondary.dropdown-toggle:focus,
+.open > .btn-secondary.dropdown-toggle.focus {
+  color: #373a3c;
+  background-color: #d4d4d4;
+  border-color: #8c8c8c;
+}
+
+.btn-secondary.disabled:focus, .btn-secondary.disabled.focus, .btn-secondary:disabled:focus, .btn-secondary:disabled.focus {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary.disabled:hover, .btn-secondary:disabled:hover {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-info {
+  color: #fff;
+  background-color: #00ffff;
+  border-color: #00ffff;
+}
+
+.btn-info:hover {
+  color: #fff;
+  background-color: #00cccc;
+  border-color: #00c2c2;
+}
+
+.btn-info:focus, .btn-info.focus {
+  color: #fff;
+  background-color: #00cccc;
+  border-color: #00c2c2;
+}
+
+.btn-info:active, .btn-info.active,
+.open > .btn-info.dropdown-toggle {
+  color: #fff;
+  background-color: #00cccc;
+  border-color: #00c2c2;
+  background-image: none;
+}
+
+.btn-info:active:hover, .btn-info:active:focus, .btn-info:active.focus, .btn-info.active:hover, .btn-info.active:focus, .btn-info.active.focus,
+.open > .btn-info.dropdown-toggle:hover,
+.open > .btn-info.dropdown-toggle:focus,
+.open > .btn-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #00a8a8;
+  border-color: teal;
+}
+
+.btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info:disabled:focus, .btn-info:disabled.focus {
+  background-color: #00ffff;
+  border-color: #00ffff;
+}
+
+.btn-info.disabled:hover, .btn-info:disabled:hover {
+  background-color: #00ffff;
+  border-color: #00ffff;
+}
+
+.btn-success {
+  color: #fff;
+  background-color: #bcf8ac;
+  border-color: #bcf8ac;
+}
+
+.btn-success:hover {
+  color: #fff;
+  background-color: #96f47d;
+  border-color: #8ef374;
+}
+
+.btn-success:focus, .btn-success.focus {
+  color: #fff;
+  background-color: #96f47d;
+  border-color: #8ef374;
+}
+
+.btn-success:active, .btn-success.active,
+.open > .btn-success.dropdown-toggle {
+  color: #fff;
+  background-color: #96f47d;
+  border-color: #8ef374;
+  background-image: none;
+}
+
+.btn-success:active:hover, .btn-success:active:focus, .btn-success:active.focus, .btn-success.active:hover, .btn-success.active:focus, .btn-success.active.focus,
+.open > .btn-success.dropdown-toggle:hover,
+.open > .btn-success.dropdown-toggle:focus,
+.open > .btn-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #7bf15c;
+  border-color: #5dee36;
+}
+
+.btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success:disabled:focus, .btn-success:disabled.focus {
+  background-color: #bcf8ac;
+  border-color: #bcf8ac;
+}
+
+.btn-success.disabled:hover, .btn-success:disabled:hover {
+  background-color: #bcf8ac;
+  border-color: #bcf8ac;
+}
+
+.btn-warning {
+  color: #fff;
+  background-color: #f0fd4e;
+  border-color: #f0fd4e;
+}
+
+.btn-warning:hover {
+  color: #fff;
+  background-color: #ecfc1c;
+  border-color: #ebfc11;
+}
+
+.btn-warning:focus, .btn-warning.focus {
+  color: #fff;
+  background-color: #ecfc1c;
+  border-color: #ebfc11;
+}
+
+.btn-warning:active, .btn-warning.active,
+.open > .btn-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #ecfc1c;
+  border-color: #ebfc11;
+  background-image: none;
+}
+
+.btn-warning:active:hover, .btn-warning:active:focus, .btn-warning:active.focus, .btn-warning.active:hover, .btn-warning.active:focus, .btn-warning.active.focus,
+.open > .btn-warning.dropdown-toggle:hover,
+.open > .btn-warning.dropdown-toggle:focus,
+.open > .btn-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #e0f203;
+  border-color: #bac902;
+}
+
+.btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning:disabled:focus, .btn-warning:disabled.focus {
+  background-color: #f0fd4e;
+  border-color: #f0fd4e;
+}
+
+.btn-warning.disabled:hover, .btn-warning:disabled:hover {
+  background-color: #f0fd4e;
+  border-color: #f0fd4e;
+}
+
+.btn-danger {
+  color: #fff;
+  background-color: #ffa9a9;
+  border-color: #ffa9a9;
+}
+
+.btn-danger:hover {
+  color: #fff;
+  background-color: #ff7676;
+  border-color: #ff6c6c;
+}
+
+.btn-danger:focus, .btn-danger.focus {
+  color: #fff;
+  background-color: #ff7676;
+  border-color: #ff6c6c;
+}
+
+.btn-danger:active, .btn-danger.active,
+.open > .btn-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #ff7676;
+  border-color: #ff6c6c;
+  background-image: none;
+}
+
+.btn-danger:active:hover, .btn-danger:active:focus, .btn-danger:active.focus, .btn-danger.active:hover, .btn-danger.active:focus, .btn-danger.active.focus,
+.open > .btn-danger.dropdown-toggle:hover,
+.open > .btn-danger.dropdown-toggle:focus,
+.open > .btn-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ff5252;
+  border-color: #ff2a2a;
+}
+
+.btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger:disabled:focus, .btn-danger:disabled.focus {
+  background-color: #ffa9a9;
+  border-color: #ffa9a9;
+}
+
+.btn-danger.disabled:hover, .btn-danger:disabled:hover {
+  background-color: #ffa9a9;
+  border-color: #ffa9a9;
+}
+
+.btn-outline-primary {
+  color: #ffd080;
+  background-image: none;
+  background-color: transparent;
+  border-color: #ffd080;
+}
+
+.btn-outline-primary:hover {
+  color: #fff;
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.btn-outline-primary:focus, .btn-outline-primary.focus {
+  color: #fff;
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.btn-outline-primary:active, .btn-outline-primary.active,
+.open > .btn-outline-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.btn-outline-primary:active:hover, .btn-outline-primary:active:focus, .btn-outline-primary:active.focus, .btn-outline-primary.active:hover, .btn-outline-primary.active:focus, .btn-outline-primary.active.focus,
+.open > .btn-outline-primary.dropdown-toggle:hover,
+.open > .btn-outline-primary.dropdown-toggle:focus,
+.open > .btn-outline-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ffb029;
+  border-color: #ffa101;
+}
+
+.btn-outline-primary.disabled:focus, .btn-outline-primary.disabled.focus, .btn-outline-primary:disabled:focus, .btn-outline-primary:disabled.focus {
+  border-color: #fff6e6;
+}
+
+.btn-outline-primary.disabled:hover, .btn-outline-primary:disabled:hover {
+  border-color: #fff6e6;
+}
+
+.btn-outline-secondary {
+  color: #ccc;
+  background-image: none;
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:hover {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:focus, .btn-outline-secondary.focus {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active, .btn-outline-secondary.active,
+.open > .btn-outline-secondary.dropdown-toggle {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active:hover, .btn-outline-secondary:active:focus, .btn-outline-secondary:active.focus, .btn-outline-secondary.active:hover, .btn-outline-secondary.active:focus, .btn-outline-secondary.active.focus,
+.open > .btn-outline-secondary.dropdown-toggle:hover,
+.open > .btn-outline-secondary.dropdown-toggle:focus,
+.open > .btn-outline-secondary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #a1a1a1;
+  border-color: #8c8c8c;
+}
+
+.btn-outline-secondary.disabled:focus, .btn-outline-secondary.disabled.focus, .btn-outline-secondary:disabled:focus, .btn-outline-secondary:disabled.focus {
+  border-color: white;
+}
+
+.btn-outline-secondary.disabled:hover, .btn-outline-secondary:disabled:hover {
+  border-color: white;
+}
+
+.btn-outline-info {
+  color: #00ffff;
+  background-image: none;
+  background-color: transparent;
+  border-color: #00ffff;
+}
+
+.btn-outline-info:hover {
+  color: #fff;
+  background-color: #00ffff;
+  border-color: #00ffff;
+}
+
+.btn-outline-info:focus, .btn-outline-info.focus {
+  color: #fff;
+  background-color: #00ffff;
+  border-color: #00ffff;
+}
+
+.btn-outline-info:active, .btn-outline-info.active,
+.open > .btn-outline-info.dropdown-toggle {
+  color: #fff;
+  background-color: #00ffff;
+  border-color: #00ffff;
+}
+
+.btn-outline-info:active:hover, .btn-outline-info:active:focus, .btn-outline-info:active.focus, .btn-outline-info.active:hover, .btn-outline-info.active:focus, .btn-outline-info.active.focus,
+.open > .btn-outline-info.dropdown-toggle:hover,
+.open > .btn-outline-info.dropdown-toggle:focus,
+.open > .btn-outline-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #00a8a8;
+  border-color: teal;
+}
+
+.btn-outline-info.disabled:focus, .btn-outline-info.disabled.focus, .btn-outline-info:disabled:focus, .btn-outline-info:disabled.focus {
+  border-color: #66ffff;
+}
+
+.btn-outline-info.disabled:hover, .btn-outline-info:disabled:hover {
+  border-color: #66ffff;
+}
+
+.btn-outline-success {
+  color: #bcf8ac;
+  background-image: none;
+  background-color: transparent;
+  border-color: #bcf8ac;
+}
+
+.btn-outline-success:hover {
+  color: #fff;
+  background-color: #bcf8ac;
+  border-color: #bcf8ac;
+}
+
+.btn-outline-success:focus, .btn-outline-success.focus {
+  color: #fff;
+  background-color: #bcf8ac;
+  border-color: #bcf8ac;
+}
+
+.btn-outline-success:active, .btn-outline-success.active,
+.open > .btn-outline-success.dropdown-toggle {
+  color: #fff;
+  background-color: #bcf8ac;
+  border-color: #bcf8ac;
+}
+
+.btn-outline-success:active:hover, .btn-outline-success:active:focus, .btn-outline-success:active.focus, .btn-outline-success.active:hover, .btn-outline-success.active:focus, .btn-outline-success.active.focus,
+.open > .btn-outline-success.dropdown-toggle:hover,
+.open > .btn-outline-success.dropdown-toggle:focus,
+.open > .btn-outline-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #7bf15c;
+  border-color: #5dee36;
+}
+
+.btn-outline-success.disabled:focus, .btn-outline-success.disabled.focus, .btn-outline-success:disabled:focus, .btn-outline-success:disabled.focus {
+  border-color: white;
+}
+
+.btn-outline-success.disabled:hover, .btn-outline-success:disabled:hover {
+  border-color: white;
+}
+
+.btn-outline-warning {
+  color: #f0fd4e;
+  background-image: none;
+  background-color: transparent;
+  border-color: #f0fd4e;
+}
+
+.btn-outline-warning:hover {
+  color: #fff;
+  background-color: #f0fd4e;
+  border-color: #f0fd4e;
+}
+
+.btn-outline-warning:focus, .btn-outline-warning.focus {
+  color: #fff;
+  background-color: #f0fd4e;
+  border-color: #f0fd4e;
+}
+
+.btn-outline-warning:active, .btn-outline-warning.active,
+.open > .btn-outline-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #f0fd4e;
+  border-color: #f0fd4e;
+}
+
+.btn-outline-warning:active:hover, .btn-outline-warning:active:focus, .btn-outline-warning:active.focus, .btn-outline-warning.active:hover, .btn-outline-warning.active:focus, .btn-outline-warning.active.focus,
+.open > .btn-outline-warning.dropdown-toggle:hover,
+.open > .btn-outline-warning.dropdown-toggle:focus,
+.open > .btn-outline-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #e0f203;
+  border-color: #bac902;
+}
+
+.btn-outline-warning.disabled:focus, .btn-outline-warning.disabled.focus, .btn-outline-warning:disabled:focus, .btn-outline-warning:disabled.focus {
+  border-color: #f9feb3;
+}
+
+.btn-outline-warning.disabled:hover, .btn-outline-warning:disabled:hover {
+  border-color: #f9feb3;
+}
+
+.btn-outline-danger {
+  color: #ffa9a9;
+  background-image: none;
+  background-color: transparent;
+  border-color: #ffa9a9;
+}
+
+.btn-outline-danger:hover {
+  color: #fff;
+  background-color: #ffa9a9;
+  border-color: #ffa9a9;
+}
+
+.btn-outline-danger:focus, .btn-outline-danger.focus {
+  color: #fff;
+  background-color: #ffa9a9;
+  border-color: #ffa9a9;
+}
+
+.btn-outline-danger:active, .btn-outline-danger.active,
+.open > .btn-outline-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #ffa9a9;
+  border-color: #ffa9a9;
+}
+
+.btn-outline-danger:active:hover, .btn-outline-danger:active:focus, .btn-outline-danger:active.focus, .btn-outline-danger.active:hover, .btn-outline-danger.active:focus, .btn-outline-danger.active.focus,
+.open > .btn-outline-danger.dropdown-toggle:hover,
+.open > .btn-outline-danger.dropdown-toggle:focus,
+.open > .btn-outline-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ff5252;
+  border-color: #ff2a2a;
+}
+
+.btn-outline-danger.disabled:focus, .btn-outline-danger.disabled.focus, .btn-outline-danger:disabled:focus, .btn-outline-danger:disabled.focus {
+  border-color: white;
+}
+
+.btn-outline-danger.disabled:hover, .btn-outline-danger:disabled:hover {
+  border-color: white;
+}
+
+.btn-link {
+  font-weight: normal;
+  color: #ffd080;
+  border-radius: 0;
+}
+
+.btn-link, .btn-link:active, .btn-link.active, .btn-link:disabled {
+  background-color: transparent;
+}
+
+.btn-link, .btn-link:focus, .btn-link:active {
+  border-color: transparent;
+}
+
+.btn-link:hover {
+  border-color: transparent;
+}
+
+.btn-link:focus, .btn-link:hover {
+  color: #ffb434;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link:disabled:focus, .btn-link:disabled:hover {
+  color: #818a91;
+  text-decoration: none;
+}
+
+.btn-lg, .btn-group-lg > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.btn-sm, .btn-group-sm > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+}
+
+.btn-block + .btn-block {
+  margin-top: 0.5rem;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+  -o-transition: opacity .15s linear;
+  transition: opacity .15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  display: none;
+}
+
+.collapse.in {
+  display: block;
+}
+
+tr.collapse.in {
+  display: table-row;
+}
+
+tbody.collapse.in {
+  display: table-row-group;
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition-timing-function: ease;
+       -o-transition-timing-function: ease;
+          transition-timing-function: ease;
+  -webkit-transition-duration: .35s;
+       -o-transition-duration: .35s;
+          transition-duration: .35s;
+  -webkit-transition-property: height;
+  -o-transition-property: height;
+  transition-property: height;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.3em;
+  vertical-align: middle;
+  content: "";
+  border-top: 0.3em solid;
+  border-right: 0.3em solid transparent;
+  border-left: 0.3em solid transparent;
+}
+
+.dropdown-toggle:focus {
+  outline: 0;
+}
+
+.dropup .dropdown-toggle::after {
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 10rem;
+  padding: 0.5rem 0;
+  margin: 0.125rem 0 0;
+  font-size: 1rem;
+  color: #5facff;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.dropdown-divider {
+  height: 1px;
+  margin: 0.5rem 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+
+.dropdown-item {
+  display: block;
+  width: 100%;
+  padding: 3px 1.5rem;
+  clear: both;
+  font-weight: normal;
+  color: #373a3c;
+  text-align: inherit;
+  white-space: nowrap;
+  background: none;
+  border: 0;
+}
+
+.dropdown-item:focus, .dropdown-item:hover {
+  color: #2b2d2f;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.dropdown-item.active, .dropdown-item.active:focus, .dropdown-item.active:hover {
+  color: #fff;
+  text-decoration: none;
+  background-color: #ffd080;
+  outline: 0;
+}
+
+.dropdown-item.disabled, .dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  color: #818a91;
+}
+
+.dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: "progid:DXImageTransform.Microsoft.gradient(enabled = false)";
+}
+
+.open > .dropdown-menu {
+  display: block;
+}
+
+.open > a {
+  outline: 0;
+}
+
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+
+.dropdown-header {
+  display: block;
+  padding: 0.5rem 1.5rem;
+  margin-bottom: 0;
+  font-size: 0.875rem;
+  color: #818a91;
+  white-space: nowrap;
+}
+
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 0.125rem;
+}
+
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+  margin-bottom: 0;
+}
+
+.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+.btn-group-vertical > .btn:focus,
+.btn-group-vertical > .btn:active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover {
+  z-index: 2;
+}
+
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+
+.btn-toolbar {
+  margin-left: -0.5rem;
+}
+
+.btn-toolbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 0.5rem;
+}
+
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group > .btn-group {
+  float: left;
+}
+
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+.btn + .dropdown-toggle-split {
+  padding-right: 0.75rem;
+  padding-left: 0.75rem;
+}
+
+.btn + .dropdown-toggle-split::after {
+  margin-left: 0;
+}
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+  padding-right: 0.375rem;
+  padding-left: 0.375rem;
+}
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+  padding-right: 1.125rem;
+  padding-left: 1.125rem;
+}
+
+.btn .caret {
+  margin-left: 0;
+}
+
+.btn-lg .caret, .btn-group-lg > .btn .caret {
+  border-width: 0.3em 0.3em 0;
+  border-bottom-width: 0;
+}
+
+.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret {
+  border-width: 0 0.3em 0.3em;
+}
+
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+
+.btn-group-vertical > .btn-group::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+  position: absolute;
+  clip: rect(0, 0, 0, 0);
+  pointer-events: none;
+}
+
+.input-group {
+  position: relative;
+  width: 100%;
+  display: table;
+  border-collapse: separate;
+}
+
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+
+.input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {
+  z-index: 3;
+}
+
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+
+.input-group-addon {
+  padding: 0.5rem 0.75rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+  font-weight: normal;
+  line-height: 1.25;
+  color: #55595c;
+  text-align: center;
+  background-color: #eceeef;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.input-group-addon.form-control-sm,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .input-group-addon.btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.input-group-addon.form-control-lg,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .input-group-addon.btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+
+.input-group .form-control:not(:last-child),
+.input-group-addon:not(:last-child),
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group > .btn,
+.input-group-btn:not(:last-child) > .dropdown-toggle,
+.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.input-group-addon:not(:last-child) {
+  border-right: 0;
+}
+
+.input-group .form-control:not(:first-child),
+.input-group-addon:not(:first-child),
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group > .btn,
+.input-group-btn:not(:first-child) > .dropdown-toggle,
+.input-group-btn:not(:last-child) > .btn:not(:first-child),
+.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.form-control + .input-group-addon:not(:first-child) {
+  border-left: 0;
+}
+
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+
+.input-group-btn > .btn {
+  position: relative;
+}
+
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+
+.input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {
+  z-index: 3;
+}
+
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group {
+  margin-right: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group {
+  z-index: 2;
+  margin-left: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,
+.input-group-btn:not(:first-child) > .btn-group:focus,
+.input-group-btn:not(:first-child) > .btn-group:active,
+.input-group-btn:not(:first-child) > .btn-group:hover {
+  z-index: 3;
+}
+
+.custom-control {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.5rem;
+  cursor: pointer;
+}
+
+.custom-control + .custom-control {
+  margin-left: 1rem;
+}
+
+.custom-control-input {
+  position: absolute;
+  z-index: -1;
+  opacity: 0;
+}
+
+.custom-control-input:checked ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #0074d9;
+}
+
+.custom-control-input:focus ~ .custom-control-indicator {
+  -webkit-box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+          box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+}
+
+.custom-control-input:active ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #84c6ff;
+}
+
+.custom-control-input:disabled ~ .custom-control-indicator {
+  cursor: not-allowed;
+  background-color: #eee;
+}
+
+.custom-control-input:disabled ~ .custom-control-description {
+  color: #767676;
+  cursor: not-allowed;
+}
+
+.custom-control-indicator {
+  position: absolute;
+  top: .25rem;
+  left: 0;
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  pointer-events: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #ddd;
+  background-repeat: no-repeat;
+  background-position: center center;
+  -webkit-background-size: 50% 50%;
+          background-size: 50% 50%;
+}
+
+.custom-checkbox .custom-control-indicator {
+  border-radius: 0.25rem;
+}
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
+}
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {
+  background-color: #0074d9;
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#fff' d='M0 2h4'/%3E%3C/svg%3E");
+}
+
+.custom-radio .custom-control-indicator {
+  border-radius: 50%;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#fff'/%3E%3C/svg%3E");
+}
+
+.custom-controls-stacked .custom-control {
+  float: left;
+  clear: left;
+}
+
+.custom-controls-stacked .custom-control + .custom-control {
+  margin-left: 0;
+}
+
+.custom-select {
+  display: inline-block;
+  max-width: 100%;
+  height: calc(2.5rem - 2px);
+  padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+  padding-right: 0.75rem \9;
+  color: #55595c;
+  vertical-align: middle;
+  background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;
+  background-image: none \9;
+  -webkit-background-size: 8px 10px;
+          background-size: 8px 10px;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+  -moz-appearance: none;
+  -webkit-appearance: none;
+}
+
+.custom-select:focus {
+  border-color: #51a7e8;
+  outline: none;
+}
+
+.custom-select:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.custom-select:disabled {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.custom-select::-ms-expand {
+  opacity: 0;
+}
+
+.custom-select-sm {
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  font-size: 75%;
+}
+
+.custom-file {
+  position: relative;
+  display: inline-block;
+  max-width: 100%;
+  height: 2.5rem;
+  cursor: pointer;
+}
+
+.custom-file-input {
+  min-width: 14rem;
+  max-width: 100%;
+  margin: 0;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+
+.custom-file-control {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 5;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+}
+
+.custom-file-control:lang(en)::after {
+  content: "Choose file...";
+}
+
+.custom-file-control::before {
+  position: absolute;
+  top: -1px;
+  right: -1px;
+  bottom: -1px;
+  z-index: 6;
+  display: block;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  background-color: #eee;
+  border: 1px solid #ddd;
+  border-radius: 0 0.25rem 0.25rem 0;
+}
+
+.custom-file-control:lang(en)::before {
+  content: "Browse";
+}
+
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.nav-link {
+  display: inline-block;
+}
+
+.nav-link:focus, .nav-link:hover {
+  text-decoration: none;
+}
+
+.nav-link.disabled {
+  color: #818a91;
+}
+
+.nav-link.disabled, .nav-link.disabled:focus, .nav-link.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+
+.nav-inline .nav-item {
+  display: inline-block;
+}
+
+.nav-inline .nav-item + .nav-item,
+.nav-inline .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-tabs .nav-item {
+  float: left;
+  margin-bottom: -1px;
+}
+
+.nav-tabs .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-tabs .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border: 1px solid transparent;
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover {
+  border-color: #eceeef #eceeef #ddd;
+}
+
+.nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:focus, .nav-tabs .nav-link.disabled:hover {
+  color: #818a91;
+  background-color: transparent;
+  border-color: transparent;
+}
+
+.nav-tabs .nav-link.active, .nav-tabs .nav-link.active:focus, .nav-tabs .nav-link.active:hover,
+.nav-tabs .nav-item.open .nav-link,
+.nav-tabs .nav-item.open .nav-link:focus,
+.nav-tabs .nav-item.open .nav-link:hover {
+  color: #55595c;
+  background-color: #eceeef;
+  border-color: #ddd #ddd transparent;
+}
+
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.nav-pills::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-pills .nav-item {
+  float: left;
+}
+
+.nav-pills .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-pills .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border-radius: 0.25rem;
+}
+
+.nav-pills .nav-link.active, .nav-pills .nav-link.active:focus, .nav-pills .nav-link.active:hover,
+.nav-pills .nav-item.open .nav-link,
+.nav-pills .nav-item.open .nav-link:focus,
+.nav-pills .nav-item.open .nav-link:hover {
+  color: #fff;
+  cursor: default;
+  background-color: #ffd080;
+}
+
+.nav-stacked .nav-item {
+  display: block;
+  float: none;
+}
+
+.nav-stacked .nav-item + .nav-item {
+  margin-top: 0.2rem;
+  margin-left: 0;
+}
+
+.tab-content > .tab-pane {
+  display: none;
+}
+
+.tab-content > .active {
+  display: block;
+}
+
+.navbar {
+  position: relative;
+  padding: 0.5rem 1rem;
+}
+
+.navbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .navbar {
+    border-radius: 0.25rem;
+  }
+}
+
+.navbar-full {
+  z-index: 1000;
+}
+
+@media (min-width: 576px) {
+  .navbar-full {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+@media (min-width: 576px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top {
+  top: 0;
+}
+
+.navbar-fixed-bottom {
+  bottom: 0;
+}
+
+.navbar-sticky-top {
+  position: -webkit-sticky;
+  position: sticky;
+  top: 0;
+  z-index: 1030;
+  width: 100%;
+}
+
+@media (min-width: 576px) {
+  .navbar-sticky-top {
+    border-radius: 0;
+  }
+}
+
+.navbar-brand {
+  float: left;
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  margin-right: 1rem;
+  font-size: 1.25rem;
+  line-height: inherit;
+}
+
+.navbar-brand:focus, .navbar-brand:hover {
+  text-decoration: none;
+}
+
+.navbar-divider {
+  float: left;
+  width: 1px;
+  padding-top: 0.425rem;
+  padding-bottom: 0.425rem;
+  margin-right: 1rem;
+  margin-left: 1rem;
+  overflow: hidden;
+}
+
+.navbar-divider::before {
+  content: "\00a0";
+}
+
+.navbar-text {
+  display: inline-block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-toggler {
+  width: 2.5em;
+  height: 2em;
+  padding: 0.5rem 0.75rem;
+  font-size: 1.25rem;
+  line-height: 1;
+  background: transparent no-repeat center center;
+  -webkit-background-size: 24px 24px;
+          background-size: 24px 24px;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.navbar-toggler:focus, .navbar-toggler:hover {
+  text-decoration: none;
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-xs .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-xs .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-sm .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-sm .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-md .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-md .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block;
+  }
+}
+
+.navbar-toggleable-lg::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 1199px) {
+  .navbar-toggleable-lg .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-lg .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-lg .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 1200px) {
+  .navbar-toggleable-lg {
+    display: block;
+  }
+}
+
+.navbar-toggleable-xl {
+  display: block;
+}
+
+.navbar-toggleable-xl::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.navbar-toggleable-xl .navbar-brand {
+  display: block;
+  float: none;
+  margin-top: .5rem;
+  margin-right: 0;
+}
+
+.navbar-toggleable-xl .navbar-nav {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+
+.navbar-toggleable-xl .navbar-nav .dropdown-menu {
+  position: static;
+  float: none;
+}
+
+.navbar-nav .nav-item {
+  float: left;
+}
+
+.navbar-nav .nav-link {
+  display: block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-nav .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.navbar-nav .nav-item + .nav-item {
+  margin-left: 1rem;
+}
+
+.navbar-light .navbar-brand,
+.navbar-light .navbar-toggler {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover,
+.navbar-light .navbar-toggler:focus,
+.navbar-light .navbar-toggler:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-nav .nav-link {
+  color: rgba(0, 0, 0, 0.5);
+}
+
+.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover {
+  color: rgba(0, 0, 0, 0.7);
+}
+
+.navbar-light .navbar-nav .open > .nav-link, .navbar-light .navbar-nav .open > .nav-link:focus, .navbar-light .navbar-nav .open > .nav-link:hover,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link:focus,
+.navbar-light .navbar-nav .active > .nav-link:hover,
+.navbar-light .navbar-nav .nav-link.open,
+.navbar-light .navbar-nav .nav-link.open:focus,
+.navbar-light .navbar-nav .nav-link.open:hover,
+.navbar-light .navbar-nav .nav-link.active,
+.navbar-light .navbar-nav .nav-link.active:focus,
+.navbar-light .navbar-nav .nav-link.active:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.navbar-light .navbar-divider {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.navbar-dark .navbar-brand,
+.navbar-dark .navbar-toggler {
+  color: white;
+}
+
+.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover,
+.navbar-dark .navbar-toggler:focus,
+.navbar-dark .navbar-toggler:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-nav .nav-link {
+  color: rgba(255, 255, 255, 0.5);
+}
+
+.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.navbar-dark .navbar-nav .open > .nav-link, .navbar-dark .navbar-nav .open > .nav-link:focus, .navbar-dark .navbar-nav .open > .nav-link:hover,
+.navbar-dark .navbar-nav .active > .nav-link,
+.navbar-dark .navbar-nav .active > .nav-link:focus,
+.navbar-dark .navbar-nav .active > .nav-link:hover,
+.navbar-dark .navbar-nav .nav-link.open,
+.navbar-dark .navbar-nav .nav-link.open:focus,
+.navbar-dark .navbar-nav .nav-link.open:hover,
+.navbar-dark .navbar-nav .nav-link.active,
+.navbar-dark .navbar-nav .nav-link.active:focus,
+.navbar-dark .navbar-nav .nav-link.active:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(255, 255, 255, 0.1);
+}
+
+.navbar-dark .navbar-divider {
+  background-color: rgba(255, 255, 255, 0.075);
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block !important;
+  }
+}
+
+.card {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+  background-color: #fff;
+  border-radius: 0.25rem;
+  border: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-block {
+  padding: 1.25rem;
+}
+
+.card-block::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-title {
+  margin-bottom: 0.75rem;
+}
+
+.card-subtitle {
+  margin-top: -0.375rem;
+  margin-bottom: 0;
+}
+
+.card-text:last-child {
+  margin-bottom: 0;
+}
+
+.card-link:hover {
+  text-decoration: none;
+}
+
+.card-link + .card-link {
+  margin-left: 1.25rem;
+}
+
+.card > .list-group:first-child .list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.card > .list-group:last-child .list-group-item:last-child {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.card-header {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 0;
+  background-color: #f5f5f5;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-header:first-child {
+  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
+}
+
+.card-footer {
+  padding: 0.75rem 1.25rem;
+  background-color: #f5f5f5;
+  border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-footer:last-child {
+  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);
+}
+
+.card-header-tabs {
+  margin-right: -0.625rem;
+  margin-bottom: -0.75rem;
+  margin-left: -0.625rem;
+  border-bottom: 0;
+}
+
+.card-header-pills {
+  margin-right: -0.625rem;
+  margin-left: -0.625rem;
+}
+
+.card-primary {
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.card-primary .card-header,
+.card-primary .card-footer {
+  background-color: transparent;
+}
+
+.card-success {
+  background-color: #bcf8ac;
+  border-color: #bcf8ac;
+}
+
+.card-success .card-header,
+.card-success .card-footer {
+  background-color: transparent;
+}
+
+.card-info {
+  background-color: #00ffff;
+  border-color: #00ffff;
+}
+
+.card-info .card-header,
+.card-info .card-footer {
+  background-color: transparent;
+}
+
+.card-warning {
+  background-color: #f0fd4e;
+  border-color: #f0fd4e;
+}
+
+.card-warning .card-header,
+.card-warning .card-footer {
+  background-color: transparent;
+}
+
+.card-danger {
+  background-color: #ffa9a9;
+  border-color: #ffa9a9;
+}
+
+.card-danger .card-header,
+.card-danger .card-footer {
+  background-color: transparent;
+}
+
+.card-outline-primary {
+  background-color: transparent;
+  border-color: #ffd080;
+}
+
+.card-outline-secondary {
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.card-outline-info {
+  background-color: transparent;
+  border-color: #00ffff;
+}
+
+.card-outline-success {
+  background-color: transparent;
+  border-color: #bcf8ac;
+}
+
+.card-outline-warning {
+  background-color: transparent;
+  border-color: #f0fd4e;
+}
+
+.card-outline-danger {
+  background-color: transparent;
+  border-color: #ffa9a9;
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer {
+  border-color: rgba(255, 255, 255, 0.2);
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer,
+.card-inverse .card-title,
+.card-inverse .card-blockquote {
+  color: #fff;
+}
+
+.card-inverse .card-link,
+.card-inverse .card-text,
+.card-inverse .card-subtitle,
+.card-inverse .card-blockquote .blockquote-footer {
+  color: rgba(255, 255, 255, 0.65);
+}
+
+.card-inverse .card-link:focus, .card-inverse .card-link:hover {
+  color: #fff;
+}
+
+.card-blockquote {
+  padding: 0;
+  margin-bottom: 0;
+  border-left: 0;
+}
+
+.card-img {
+  border-radius: calc(0.25rem - 1px);
+}
+
+.card-img-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1.25rem;
+}
+
+.card-img-top {
+  border-top-right-radius: calc(0.25rem - 1px);
+  border-top-left-radius: calc(0.25rem - 1px);
+}
+
+.card-img-bottom {
+  border-bottom-right-radius: calc(0.25rem - 1px);
+  border-bottom-left-radius: calc(0.25rem - 1px);
+}
+
+@media (min-width: 576px) {
+  .card-deck {
+    display: table;
+    width: 100%;
+    margin-bottom: 0.75rem;
+    table-layout: fixed;
+    border-spacing: 1.25rem 0;
+  }
+  .card-deck .card {
+    display: table-cell;
+    margin-bottom: 0;
+    vertical-align: top;
+  }
+  .card-deck-wrapper {
+    margin-right: -1.25rem;
+    margin-left: -1.25rem;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-group {
+    display: table;
+    width: 100%;
+    table-layout: fixed;
+  }
+  .card-group .card {
+    display: table-cell;
+    vertical-align: top;
+  }
+  .card-group .card + .card {
+    margin-left: 0;
+    border-left: 0;
+  }
+  .card-group .card:first-child {
+    border-bottom-right-radius: 0;
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-top {
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-bottom {
+    border-bottom-right-radius: 0;
+  }
+  .card-group .card:last-child {
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-top {
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-bottom {
+    border-bottom-left-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) {
+    border-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) .card-img-top,
+  .card-group .card:not(:first-child):not(:last-child) .card-img-bottom {
+    border-radius: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-columns {
+    -webkit-column-count: 3;
+       -moz-column-count: 3;
+            column-count: 3;
+    -webkit-column-gap: 1.25rem;
+       -moz-column-gap: 1.25rem;
+            column-gap: 1.25rem;
+  }
+  .card-columns .card {
+    display: inline-block;
+    width: 100%;
+  }
+}
+
+.breadcrumb {
+  padding: 0.75rem 1rem;
+  margin-bottom: 1rem;
+  list-style: none;
+  background-color: #eceeef;
+  border-radius: 0.25rem;
+}
+
+.breadcrumb::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.breadcrumb-item {
+  float: left;
+}
+
+.breadcrumb-item + .breadcrumb-item::before {
+  display: inline-block;
+  padding-right: 0.5rem;
+  padding-left: 0.5rem;
+  color: #818a91;
+  content: "/";
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: underline;
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: none;
+}
+
+.breadcrumb-item.active {
+  color: #818a91;
+}
+
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border-radius: 0.25rem;
+}
+
+.page-item {
+  display: inline;
+}
+
+.page-item:first-child .page-link {
+  margin-left: 0;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.page-item:last-child .page-link {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.page-item.active .page-link, .page-item.active .page-link:focus, .page-item.active .page-link:hover {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.page-item.disabled .page-link, .page-item.disabled .page-link:focus, .page-item.disabled .page-link:hover {
+  color: #818a91;
+  pointer-events: none;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+
+.page-link {
+  position: relative;
+  float: left;
+  padding: 0.5rem 0.75rem;
+  margin-left: -1px;
+  color: #ffd080;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.page-link:focus, .page-link:hover {
+  color: #ffb434;
+  background-color: #eceeef;
+  border-color: #ddd;
+}
+
+.pagination-lg .page-link {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+}
+
+.pagination-lg .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.3rem;
+  border-top-left-radius: 0.3rem;
+}
+
+.pagination-lg .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.3rem;
+  border-top-right-radius: 0.3rem;
+}
+
+.pagination-sm .page-link {
+  padding: 0.275rem 0.75rem;
+  font-size: 0.875rem;
+}
+
+.pagination-sm .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.2rem;
+  border-top-left-radius: 0.2rem;
+}
+
+.pagination-sm .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.2rem;
+  border-top-right-radius: 0.2rem;
+}
+
+.tag {
+  display: inline-block;
+  padding: 0.25em 0.4em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: 0.25rem;
+}
+
+.tag:empty {
+  display: none;
+}
+
+.btn .tag {
+  position: relative;
+  top: -1px;
+}
+
+a.tag:focus, a.tag:hover {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.tag-pill {
+  padding-right: 0.6em;
+  padding-left: 0.6em;
+  border-radius: 10rem;
+}
+
+.tag-default {
+  background-color: #818a91;
+}
+
+.tag-default[href]:focus, .tag-default[href]:hover {
+  background-color: #687077;
+}
+
+.tag-primary {
+  background-color: #ffd080;
+}
+
+.tag-primary[href]:focus, .tag-primary[href]:hover {
+  background-color: #ffbd4d;
+}
+
+.tag-success {
+  background-color: #bcf8ac;
+}
+
+.tag-success[href]:focus, .tag-success[href]:hover {
+  background-color: #96f47d;
+}
+
+.tag-info {
+  background-color: #00ffff;
+}
+
+.tag-info[href]:focus, .tag-info[href]:hover {
+  background-color: #00cccc;
+}
+
+.tag-warning {
+  background-color: #f0fd4e;
+}
+
+.tag-warning[href]:focus, .tag-warning[href]:hover {
+  background-color: #ecfc1c;
+}
+
+.tag-danger {
+  background-color: #ffa9a9;
+}
+
+.tag-danger[href]:focus, .tag-danger[href]:hover {
+  background-color: #ff7676;
+}
+
+.jumbotron {
+  padding: 2rem 1rem;
+  margin-bottom: 2rem;
+  background-color: #eceeef;
+  border-radius: 0.3rem;
+}
+
+@media (min-width: 576px) {
+  .jumbotron {
+    padding: 4rem 2rem;
+  }
+}
+
+.jumbotron-hr {
+  border-top-color: #d0d5d8;
+}
+
+.jumbotron-fluid {
+  padding-right: 0;
+  padding-left: 0;
+  border-radius: 0;
+}
+
+.alert {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 1rem;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.alert-heading {
+  color: inherit;
+}
+
+.alert-link {
+  font-weight: bold;
+}
+
+.alert-dismissible {
+  padding-right: 2.5rem;
+}
+
+.alert-dismissible .close {
+  position: relative;
+  top: -.125rem;
+  right: -1.25rem;
+  color: inherit;
+}
+
+.alert-success {
+  background-color: #dff0d8;
+  border-color: #d0e9c6;
+  color: #3c763d;
+}
+
+.alert-success hr {
+  border-top-color: #c1e2b3;
+}
+
+.alert-success .alert-link {
+  color: #2b542c;
+}
+
+.alert-info {
+  background-color: #d9edf7;
+  border-color: #bcdff1;
+  color: #31708f;
+}
+
+.alert-info hr {
+  border-top-color: #a6d5ec;
+}
+
+.alert-info .alert-link {
+  color: #245269;
+}
+
+.alert-warning {
+  background-color: #fcf8e3;
+  border-color: #faf2cc;
+  color: #8a6d3b;
+}
+
+.alert-warning hr {
+  border-top-color: #f7ecb5;
+}
+
+.alert-warning .alert-link {
+  color: #66512c;
+}
+
+.alert-danger {
+  background-color: #f2dede;
+  border-color: #ebcccc;
+  color: #a94442;
+}
+
+.alert-danger hr {
+  border-top-color: #e4b9b9;
+}
+
+.alert-danger .alert-link {
+  color: #843534;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  display: block;
+  width: 100%;
+  height: 1rem;
+  margin-bottom: 1rem;
+}
+
+.progress[value] {
+  background-color: #eee;
+  border: 0;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  border-radius: 0.25rem;
+}
+
+.progress[value]::-ms-fill {
+  background-color: #0074d9;
+  border: 0;
+}
+
+.progress[value]::-moz-progress-bar {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-value {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value="100"]::-moz-progress-bar {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value="100"]::-webkit-progress-value {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-bar {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+base::-moz-progress-bar,
+.progress[value] {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress {
+    background-color: #eee;
+    border-radius: 0.25rem;
+  }
+  .progress-bar {
+    display: inline-block;
+    height: 1rem;
+    text-indent: -999rem;
+    background-color: #0074d9;
+    border-bottom-left-radius: 0.25rem;
+    border-top-left-radius: 0.25rem;
+  }
+  .progress[width="100%"] {
+    border-bottom-right-radius: 0.25rem;
+    border-top-right-radius: 0.25rem;
+  }
+}
+
+.progress-striped[value]::-webkit-progress-value {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 1rem 1rem;
+          background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-moz-progress-bar {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-ms-fill {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-bar-striped {
+    background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    -webkit-background-size: 1rem 1rem;
+            background-size: 1rem 1rem;
+  }
+}
+
+.progress-animated[value]::-webkit-progress-value {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-animated[value]::-moz-progress-bar {
+  animation: progress-bar-stripes 2s linear infinite;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-animated .progress-bar-striped {
+    -webkit-animation: progress-bar-stripes 2s linear infinite;
+         -o-animation: progress-bar-stripes 2s linear infinite;
+            animation: progress-bar-stripes 2s linear infinite;
+  }
+}
+
+.progress-success[value]::-webkit-progress-value {
+  background-color: #bcf8ac;
+}
+
+.progress-success[value]::-moz-progress-bar {
+  background-color: #bcf8ac;
+}
+
+.progress-success[value]::-ms-fill {
+  background-color: #bcf8ac;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-success .progress-bar {
+    background-color: #bcf8ac;
+  }
+}
+
+.progress-info[value]::-webkit-progress-value {
+  background-color: #00ffff;
+}
+
+.progress-info[value]::-moz-progress-bar {
+  background-color: #00ffff;
+}
+
+.progress-info[value]::-ms-fill {
+  background-color: #00ffff;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-info .progress-bar {
+    background-color: #00ffff;
+  }
+}
+
+.progress-warning[value]::-webkit-progress-value {
+  background-color: #f0fd4e;
+}
+
+.progress-warning[value]::-moz-progress-bar {
+  background-color: #f0fd4e;
+}
+
+.progress-warning[value]::-ms-fill {
+  background-color: #f0fd4e;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-warning .progress-bar {
+    background-color: #f0fd4e;
+  }
+}
+
+.progress-danger[value]::-webkit-progress-value {
+  background-color: #ffa9a9;
+}
+
+.progress-danger[value]::-moz-progress-bar {
+  background-color: #ffa9a9;
+}
+
+.progress-danger[value]::-ms-fill {
+  background-color: #ffa9a9;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-danger .progress-bar {
+    background-color: #ffa9a9;
+  }
+}
+
+.media,
+.media-body {
+  overflow: hidden;
+}
+
+.media-body {
+  width: 10000px;
+}
+
+.media-left,
+.media-right,
+.media-body {
+  display: table-cell;
+  vertical-align: top;
+}
+
+.media-middle {
+  vertical-align: middle;
+}
+
+.media-bottom {
+  vertical-align: bottom;
+}
+
+.media-object {
+  display: block;
+}
+
+.media-object.img-thumbnail {
+  max-width: none;
+}
+
+.media-right {
+  padding-left: 10px;
+}
+
+.media-left {
+  padding-right: 10px;
+}
+
+.media-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-group {
+  padding-left: 0;
+  margin-bottom: 0;
+}
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 0.75rem 1.25rem;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.list-group-item.disabled, .list-group-item.disabled:focus, .list-group-item.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading {
+  color: inherit;
+}
+
+.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text {
+  color: #818a91;
+}
+
+.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover {
+  z-index: 2;
+  color: #fff;
+  text-decoration: none;
+  background-color: #ffd080;
+  border-color: #ffd080;
+}
+
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > .small {
+  color: inherit;
+}
+
+.list-group-item.active .list-group-item-text, .list-group-item.active:focus .list-group-item-text, .list-group-item.active:hover .list-group-item-text {
+  color: white;
+}
+
+.list-group-flush .list-group-item {
+  border-right: 0;
+  border-left: 0;
+  border-radius: 0;
+}
+
+.list-group-item-action {
+  width: 100%;
+  color: #555;
+  text-align: inherit;
+}
+
+.list-group-item-action .list-group-item-heading {
+  color: #333;
+}
+
+.list-group-item-action:focus, .list-group-item-action:hover {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+
+a.list-group-item-success,
+button.list-group-item-success {
+  color: #3c763d;
+}
+
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-success:focus, a.list-group-item-success:hover,
+button.list-group-item-success:focus,
+button.list-group-item-success:hover {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+
+a.list-group-item-success.active, a.list-group-item-success.active:focus, a.list-group-item-success.active:hover,
+button.list-group-item-success.active,
+button.list-group-item-success.active:focus,
+button.list-group-item-success.active:hover {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+
+a.list-group-item-info,
+button.list-group-item-info {
+  color: #31708f;
+}
+
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-info:focus, a.list-group-item-info:hover,
+button.list-group-item-info:focus,
+button.list-group-item-info:hover {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+
+a.list-group-item-info.active, a.list-group-item-info.active:focus, a.list-group-item-info.active:hover,
+button.list-group-item-info.active,
+button.list-group-item-info.active:focus,
+button.list-group-item-info.active:hover {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+
+a.list-group-item-warning,
+button.list-group-item-warning {
+  color: #8a6d3b;
+}
+
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-warning:focus, a.list-group-item-warning:hover,
+button.list-group-item-warning:focus,
+button.list-group-item-warning:hover {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+
+a.list-group-item-warning.active, a.list-group-item-warning.active:focus, a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active,
+button.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:hover {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+
+a.list-group-item-danger,
+button.list-group-item-danger {
+  color: #a94442;
+}
+
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-danger:focus, a.list-group-item-danger:hover,
+button.list-group-item-danger:focus,
+button.list-group-item-danger:hover {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+
+a.list-group-item-danger.active, a.list-group-item-danger.active:focus, a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active,
+button.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:hover {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+.embed-responsive-21by9 {
+  padding-bottom: 42.857143%;
+}
+
+.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+
+.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+
+.embed-responsive-1by1 {
+  padding-bottom: 100%;
+}
+
+.close {
+  float: right;
+  font-size: 1.5rem;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  opacity: .2;
+}
+
+.close:focus, .close:hover {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  opacity: .5;
+}
+
+button.close {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.modal-open {
+  overflow: hidden;
+}
+
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  outline: 0;
+}
+
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+  transition: -webkit-transform .3s ease-out;
+  -o-transition: -o-transform .3s ease-out;
+  transition: transform .3s ease-out;
+  transition: transform .3s ease-out, -webkit-transform .3s ease-out, -o-transform .3s ease-out;
+  -webkit-transform: translate(0, -25%);
+      -ms-transform: translate(0, -25%);
+       -o-transform: translate(0, -25%);
+          transform: translate(0, -25%);
+}
+
+.modal.in .modal-dialog {
+  -webkit-transform: translate(0, 0);
+      -ms-transform: translate(0, 0);
+       -o-transform: translate(0, 0);
+          transform: translate(0, 0);
+}
+
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+  outline: 0;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop.in {
+  opacity: 0.5;
+}
+
+.modal-header {
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+.modal-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-header .close {
+  margin-top: -2px;
+}
+
+.modal-title {
+  margin: 0;
+  line-height: 1.5;
+}
+
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+
+.modal-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+
+@media (min-width: 576px) {
+  .modal-dialog {
+    max-width: 600px;
+    margin: 30px auto;
+  }
+  .modal-sm {
+    max-width: 300px;
+  }
+}
+
+@media (min-width: 992px) {
+  .modal-lg {
+    max-width: 900px;
+  }
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  opacity: 0;
+}
+
+.tooltip.in {
+  opacity: 0.9;
+}
+
+.tooltip.tooltip-top, .tooltip.bs-tether-element-attached-bottom {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+
+.tooltip.tooltip-top .tooltip-inner::before, .tooltip.bs-tether-element-attached-bottom .tooltip-inner::before {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+
+.tooltip.tooltip-right, .tooltip.bs-tether-element-attached-left {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+
+.tooltip.tooltip-right .tooltip-inner::before, .tooltip.bs-tether-element-attached-left .tooltip-inner::before {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+
+.tooltip.tooltip-bottom, .tooltip.bs-tether-element-attached-top {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+
+.tooltip.tooltip-bottom .tooltip-inner::before, .tooltip.bs-tether-element-attached-top .tooltip-inner::before {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+
+.tooltip.tooltip-left, .tooltip.bs-tether-element-attached-right {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+
+.tooltip.tooltip-left .tooltip-inner::before, .tooltip.bs-tether-element-attached-right .tooltip-inner::before {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  background-color: #000;
+  border-radius: 0.25rem;
+}
+
+.tooltip-inner::before {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: block;
+  max-width: 276px;
+  padding: 1px;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+}
+
+.popover.popover-top, .popover.bs-tether-element-attached-bottom {
+  margin-top: -10px;
+}
+
+.popover.popover-top::before, .popover.popover-top::after, .popover.bs-tether-element-attached-bottom::before, .popover.bs-tether-element-attached-bottom::after {
+  left: 50%;
+  border-bottom-width: 0;
+}
+
+.popover.popover-top::before, .popover.bs-tether-element-attached-bottom::before {
+  bottom: -11px;
+  margin-left: -11px;
+  border-top-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-top::after, .popover.bs-tether-element-attached-bottom::after {
+  bottom: -10px;
+  margin-left: -10px;
+  border-top-color: #fff;
+}
+
+.popover.popover-right, .popover.bs-tether-element-attached-left {
+  margin-left: 10px;
+}
+
+.popover.popover-right::before, .popover.popover-right::after, .popover.bs-tether-element-attached-left::before, .popover.bs-tether-element-attached-left::after {
+  top: 50%;
+  border-left-width: 0;
+}
+
+.popover.popover-right::before, .popover.bs-tether-element-attached-left::before {
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-right::after, .popover.bs-tether-element-attached-left::after {
+  left: -10px;
+  margin-top: -10px;
+  border-right-color: #fff;
+}
+
+.popover.popover-bottom, .popover.bs-tether-element-attached-top {
+  margin-top: 10px;
+}
+
+.popover.popover-bottom::before, .popover.popover-bottom::after, .popover.bs-tether-element-attached-top::before, .popover.bs-tether-element-attached-top::after {
+  left: 50%;
+  border-top-width: 0;
+}
+
+.popover.popover-bottom::before, .popover.bs-tether-element-attached-top::before {
+  top: -11px;
+  margin-left: -11px;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-bottom::after, .popover.bs-tether-element-attached-top::after {
+  top: -10px;
+  margin-left: -10px;
+  border-bottom-color: #f7f7f7;
+}
+
+.popover.popover-bottom .popover-title::before, .popover.bs-tether-element-attached-top .popover-title::before {
+  position: absolute;
+  top: 0;
+  left: 50%;
+  display: block;
+  width: 20px;
+  margin-left: -10px;
+  content: "";
+  border-bottom: 1px solid #f7f7f7;
+}
+
+.popover.popover-left, .popover.bs-tether-element-attached-right {
+  margin-left: -10px;
+}
+
+.popover.popover-left::before, .popover.popover-left::after, .popover.bs-tether-element-attached-right::before, .popover.bs-tether-element-attached-right::after {
+  top: 50%;
+  border-right-width: 0;
+}
+
+.popover.popover-left::before, .popover.bs-tether-element-attached-right::before {
+  right: -11px;
+  margin-top: -11px;
+  border-left-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-left::after, .popover.bs-tether-element-attached-right::after {
+  right: -10px;
+  margin-top: -10px;
+  border-left-color: #fff;
+}
+
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 1rem;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 0.2375rem 0.2375rem 0 0;
+}
+
+.popover-title:empty {
+  display: none;
+}
+
+.popover-content {
+  padding: 9px 14px;
+}
+
+.popover::before,
+.popover::after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover::before {
+  content: "";
+  border-width: 11px;
+}
+
+.popover::after {
+  content: "";
+  border-width: 10px;
+}
+
+.carousel {
+  position: relative;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-inner > .carousel-item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+  -o-transition: .6s ease-in-out left;
+  transition: .6s ease-in-out left;
+}
+
+.carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  line-height: 1;
+}
+
+@media all and (transform-3d), (-webkit-transform-3d) {
+  .carousel-inner > .carousel-item {
+    -webkit-transition: -webkit-transform .6s ease-in-out;
+    transition: -webkit-transform .6s ease-in-out;
+    -o-transition: -o-transform .6s ease-in-out;
+    transition: transform .6s ease-in-out;
+    transition: transform .6s ease-in-out, -webkit-transform .6s ease-in-out, -o-transform .6s ease-in-out;
+    -webkit-backface-visibility: hidden;
+            backface-visibility: hidden;
+    -webkit-perspective: 1000px;
+            perspective: 1000px;
+  }
+  .carousel-inner > .carousel-item.next, .carousel-inner > .carousel-item.active.right {
+    left: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+            transform: translate3d(100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.prev, .carousel-inner > .carousel-item.active.left {
+    left: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+            transform: translate3d(-100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.next.left, .carousel-inner > .carousel-item.prev.right, .carousel-inner > .carousel-item.active {
+    left: 0;
+    -webkit-transform: translate3d(0, 0, 0);
+            transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+
+.carousel-inner > .active {
+  left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.carousel-inner > .next {
+  left: 100%;
+}
+
+.carousel-inner > .prev {
+  left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+
+.carousel-inner > .active.left {
+  left: -100%;
+}
+
+.carousel-inner > .active.right {
+  left: 100%;
+}
+
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+  opacity: 0.5;
+}
+
+.carousel-control.left {
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+
+.carousel-control:focus, .carousel-control:hover {
+  color: #fff;
+  text-decoration: none;
+  outline: 0;
+  opacity: .9;
+}
+
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+  line-height: 1;
+}
+
+.carousel-control .icon-prev {
+  left: 50%;
+  margin-left: -10px;
+}
+
+.carousel-control .icon-next {
+  right: 50%;
+  margin-right: -10px;
+}
+
+.carousel-control .icon-prev::before {
+  content: "\2039";
+}
+
+.carousel-control .icon-next::before {
+  content: "\203a";
+}
+
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: transparent;
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+
+.carousel-caption .btn {
+  text-shadow: none;
+}
+
+@media (min-width: 576px) {
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+
+.align-baseline {
+  vertical-align: baseline !important;
+}
+
+.align-top {
+  vertical-align: top !important;
+}
+
+.align-middle {
+  vertical-align: middle !important;
+}
+
+.align-bottom {
+  vertical-align: bottom !important;
+}
+
+.align-text-bottom {
+  vertical-align: text-bottom !important;
+}
+
+.align-text-top {
+  vertical-align: text-top !important;
+}
+
+.bg-faded {
+  background-color: #f7f7f9;
+}
+
+.bg-primary {
+  background-color: #ffd080 !important;
+}
+
+a.bg-primary:focus, a.bg-primary:hover {
+  background-color: #ffbd4d !important;
+}
+
+.bg-success {
+  background-color: #bcf8ac !important;
+}
+
+a.bg-success:focus, a.bg-success:hover {
+  background-color: #96f47d !important;
+}
+
+.bg-info {
+  background-color: #00ffff !important;
+}
+
+a.bg-info:focus, a.bg-info:hover {
+  background-color: #00cccc !important;
+}
+
+.bg-warning {
+  background-color: #f0fd4e !important;
+}
+
+a.bg-warning:focus, a.bg-warning:hover {
+  background-color: #ecfc1c !important;
+}
+
+.bg-danger {
+  background-color: #ffa9a9 !important;
+}
+
+a.bg-danger:focus, a.bg-danger:hover {
+  background-color: #ff7676 !important;
+}
+
+.bg-inverse {
+  background-color: #373a3c !important;
+}
+
+a.bg-inverse:focus, a.bg-inverse:hover {
+  background-color: #1f2021 !important;
+}
+
+.rounded {
+  border-radius: 0.25rem;
+}
+
+.rounded-top {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-right {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.rounded-bottom {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.rounded-left {
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-circle {
+  border-radius: 50%;
+}
+
+.clearfix::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.d-block {
+  display: block !important;
+}
+
+.d-inline-block {
+  display: inline-block !important;
+}
+
+.d-inline {
+  display: inline !important;
+}
+
+.float-xs-left {
+  float: left !important;
+}
+
+.float-xs-right {
+  float: right !important;
+}
+
+.float-xs-none {
+  float: none !important;
+}
+
+@media (min-width: 576px) {
+  .float-sm-left {
+    float: left !important;
+  }
+  .float-sm-right {
+    float: right !important;
+  }
+  .float-sm-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .float-md-left {
+    float: left !important;
+  }
+  .float-md-right {
+    float: right !important;
+  }
+  .float-md-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .float-lg-left {
+    float: left !important;
+  }
+  .float-lg-right {
+    float: right !important;
+  }
+  .float-lg-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .float-xl-left {
+    float: left !important;
+  }
+  .float-xl-right {
+    float: right !important;
+  }
+  .float-xl-none {
+    float: none !important;
+  }
+}
+
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+
+.w-100 {
+  width: 100% !important;
+}
+
+.h-100 {
+  height: 100% !important;
+}
+
+.mx-auto {
+  margin-right: auto !important;
+  margin-left: auto !important;
+}
+
+.m-0 {
+  margin: 0 0 !important;
+}
+
+.mt-0 {
+  margin-top: 0 !important;
+}
+
+.mr-0 {
+  margin-right: 0 !important;
+}
+
+.mb-0 {
+  margin-bottom: 0 !important;
+}
+
+.ml-0 {
+  margin-left: 0 !important;
+}
+
+.mx-0 {
+  margin-right: 0 !important;
+  margin-left: 0 !important;
+}
+
+.my-0 {
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+
+.m-1 {
+  margin: 1rem 1rem !important;
+}
+
+.mt-1 {
+  margin-top: 1rem !important;
+}
+
+.mr-1 {
+  margin-right: 1rem !important;
+}
+
+.mb-1 {
+  margin-bottom: 1rem !important;
+}
+
+.ml-1 {
+  margin-left: 1rem !important;
+}
+
+.mx-1 {
+  margin-right: 1rem !important;
+  margin-left: 1rem !important;
+}
+
+.my-1 {
+  margin-top: 1rem !important;
+  margin-bottom: 1rem !important;
+}
+
+.m-2 {
+  margin: 1.5rem 1.5rem !important;
+}
+
+.mt-2 {
+  margin-top: 1.5rem !important;
+}
+
+.mr-2 {
+  margin-right: 1.5rem !important;
+}
+
+.mb-2 {
+  margin-bottom: 1.5rem !important;
+}
+
+.ml-2 {
+  margin-left: 1.5rem !important;
+}
+
+.mx-2 {
+  margin-right: 1.5rem !important;
+  margin-left: 1.5rem !important;
+}
+
+.my-2 {
+  margin-top: 1.5rem !important;
+  margin-bottom: 1.5rem !important;
+}
+
+.m-3 {
+  margin: 3rem 3rem !important;
+}
+
+.mt-3 {
+  margin-top: 3rem !important;
+}
+
+.mr-3 {
+  margin-right: 3rem !important;
+}
+
+.mb-3 {
+  margin-bottom: 3rem !important;
+}
+
+.ml-3 {
+  margin-left: 3rem !important;
+}
+
+.mx-3 {
+  margin-right: 3rem !important;
+  margin-left: 3rem !important;
+}
+
+.my-3 {
+  margin-top: 3rem !important;
+  margin-bottom: 3rem !important;
+}
+
+.p-0 {
+  padding: 0 0 !important;
+}
+
+.pt-0 {
+  padding-top: 0 !important;
+}
+
+.pr-0 {
+  padding-right: 0 !important;
+}
+
+.pb-0 {
+  padding-bottom: 0 !important;
+}
+
+.pl-0 {
+  padding-left: 0 !important;
+}
+
+.px-0 {
+  padding-right: 0 !important;
+  padding-left: 0 !important;
+}
+
+.py-0 {
+  padding-top: 0 !important;
+  padding-bottom: 0 !important;
+}
+
+.p-1 {
+  padding: 1rem 1rem !important;
+}
+
+.pt-1 {
+  padding-top: 1rem !important;
+}
+
+.pr-1 {
+  padding-right: 1rem !important;
+}
+
+.pb-1 {
+  padding-bottom: 1rem !important;
+}
+
+.pl-1 {
+  padding-left: 1rem !important;
+}
+
+.px-1 {
+  padding-right: 1rem !important;
+  padding-left: 1rem !important;
+}
+
+.py-1 {
+  padding-top: 1rem !important;
+  padding-bottom: 1rem !important;
+}
+
+.p-2 {
+  padding: 1.5rem 1.5rem !important;
+}
+
+.pt-2 {
+  padding-top: 1.5rem !important;
+}
+
+.pr-2 {
+  padding-right: 1.5rem !important;
+}
+
+.pb-2 {
+  padding-bottom: 1.5rem !important;
+}
+
+.pl-2 {
+  padding-left: 1.5rem !important;
+}
+
+.px-2 {
+  padding-right: 1.5rem !important;
+  padding-left: 1.5rem !important;
+}
+
+.py-2 {
+  padding-top: 1.5rem !important;
+  padding-bottom: 1.5rem !important;
+}
+
+.p-3 {
+  padding: 3rem 3rem !important;
+}
+
+.pt-3 {
+  padding-top: 3rem !important;
+}
+
+.pr-3 {
+  padding-right: 3rem !important;
+}
+
+.pb-3 {
+  padding-bottom: 3rem !important;
+}
+
+.pl-3 {
+  padding-left: 3rem !important;
+}
+
+.px-3 {
+  padding-right: 3rem !important;
+  padding-left: 3rem !important;
+}
+
+.py-3 {
+  padding-top: 3rem !important;
+  padding-bottom: 3rem !important;
+}
+
+.pos-f-t {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+.text-justify {
+  text-align: justify !important;
+}
+
+.text-nowrap {
+  white-space: nowrap !important;
+}
+
+.text-truncate {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.text-xs-left {
+  text-align: left !important;
+}
+
+.text-xs-right {
+  text-align: right !important;
+}
+
+.text-xs-center {
+  text-align: center !important;
+}
+
+@media (min-width: 576px) {
+  .text-sm-left {
+    text-align: left !important;
+  }
+  .text-sm-right {
+    text-align: right !important;
+  }
+  .text-sm-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .text-md-left {
+    text-align: left !important;
+  }
+  .text-md-right {
+    text-align: right !important;
+  }
+  .text-md-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .text-lg-left {
+    text-align: left !important;
+  }
+  .text-lg-right {
+    text-align: right !important;
+  }
+  .text-lg-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .text-xl-left {
+    text-align: left !important;
+  }
+  .text-xl-right {
+    text-align: right !important;
+  }
+  .text-xl-center {
+    text-align: center !important;
+  }
+}
+
+.text-lowercase {
+  text-transform: lowercase !important;
+}
+
+.text-uppercase {
+  text-transform: uppercase !important;
+}
+
+.text-capitalize {
+  text-transform: capitalize !important;
+}
+
+.font-weight-normal {
+  font-weight: normal;
+}
+
+.font-weight-bold {
+  font-weight: bold;
+}
+
+.font-italic {
+  font-style: italic;
+}
+
+.text-white {
+  color: #fff !important;
+}
+
+.text-muted {
+  color: #818a91 !important;
+}
+
+a.text-muted:focus, a.text-muted:hover {
+  color: #687077 !important;
+}
+
+.text-primary {
+  color: #ffd080 !important;
+}
+
+a.text-primary:focus, a.text-primary:hover {
+  color: #ffbd4d !important;
+}
+
+.text-success {
+  color: #bcf8ac !important;
+}
+
+a.text-success:focus, a.text-success:hover {
+  color: #96f47d !important;
+}
+
+.text-info {
+  color: #00ffff !important;
+}
+
+a.text-info:focus, a.text-info:hover {
+  color: #00cccc !important;
+}
+
+.text-warning {
+  color: #f0fd4e !important;
+}
+
+a.text-warning:focus, a.text-warning:hover {
+  color: #ecfc1c !important;
+}
+
+.text-danger {
+  color: #ffa9a9 !important;
+}
+
+a.text-danger:focus, a.text-danger:hover {
+  color: #ff7676 !important;
+}
+
+.text-gray-dark {
+  color: #373a3c !important;
+}
+
+a.text-gray-dark:focus, a.text-gray-dark:hover {
+  color: #1f2021 !important;
+}
+
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.invisible {
+  visibility: hidden !important;
+}
+
+.hidden-xs-up {
+  display: none !important;
+}
+
+@media (max-width: 575px) {
+  .hidden-xs-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 576px) {
+  .hidden-sm-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-sm-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .hidden-md-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 991px) {
+  .hidden-md-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .hidden-lg-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 1199px) {
+  .hidden-lg-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .hidden-xl-up {
+    display: none !important;
+  }
+}
+
+.hidden-xl-down {
+  display: none !important;
+}
+
+.visible-print-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+
+.visible-print-inline {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+
+.visible-print-inline-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
new file mode 100644
index 0000000..6e72356
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_custom.scss","../../scss/_tobago.scss","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_hover.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
new file mode 100644
index 0000000..86bd8a7
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.tobago-box-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center}.tobago-button>img{margin-top:-1px;margin-bottom:-1px}.tobago-collapsed.tobago-box .card-block,.tobago-collapsed.tobago-panel,.tobago-collapsed.tobago-section .tobago-section-content{display:none}.tobago-d [...]
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
new file mode 100644
index 0000000..4bbf9e2
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/_tobago.scss","dist/css/bootstrap.css","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_cle [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.js b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.js
new file mode 100644
index 0000000..0a37e60
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.js
@@ -0,0 +1,3430 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+if (typeof jQuery === 'undefined') {
+  throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+  var version = $.fn.jquery.split(' ')[0].split('.')
+  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {
+    throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
+  }
+}(jQuery);
+
+
++function () {
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) [...]
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): util.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Util = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Private TransitionEnd Helpers
+   * ------------------------------------------------------------------------
+   */
+
+  var transition = false;
+
+  var MAX_UID = 1000000;
+
+  var TransitionEndEvent = {
+    WebkitTransition: 'webkitTransitionEnd',
+    MozTransition: 'transitionend',
+    OTransition: 'oTransitionEnd otransitionend',
+    transition: 'transitionend'
+  };
+
+  // shoutout AngusCroll (https://goo.gl/pxwQGp)
+  function toType(obj) {
+    return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
+  }
+
+  function isElement(obj) {
+    return (obj[0] || obj).nodeType;
+  }
+
+  function getSpecialTransitionEndEvent() {
+    return {
+      bindType: transition.end,
+      delegateType: transition.end,
+      handle: function handle(event) {
+        if ($(event.target).is(this)) {
+          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
+        }
+        return undefined;
+      }
+    };
+  }
+
+  function transitionEndTest() {
+    if (window.QUnit) {
+      return false;
+    }
+
+    var el = document.createElement('bootstrap');
+
+    for (var name in TransitionEndEvent) {
+      if (el.style[name] !== undefined) {
+        return { end: TransitionEndEvent[name] };
+      }
+    }
+
+    return false;
+  }
+
+  function transitionEndEmulator(duration) {
+    var _this = this;
+
+    var called = false;
+
+    $(this).one(Util.TRANSITION_END, function () {
+      called = true;
+    });
+
+    setTimeout(function () {
+      if (!called) {
+        Util.triggerTransitionEnd(_this);
+      }
+    }, duration);
+
+    return this;
+  }
+
+  function setTransitionEndSupport() {
+    transition = transitionEndTest();
+
+    $.fn.emulateTransitionEnd = transitionEndEmulator;
+
+    if (Util.supportsTransitionEnd()) {
+      $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
+    }
+  }
+
+  /**
+   * --------------------------------------------------------------------------
+   * Public Util Api
+   * --------------------------------------------------------------------------
+   */
+
+  var Util = {
+
+    TRANSITION_END: 'bsTransitionEnd',
+
+    getUID: function getUID(prefix) {
+      do {
+        /* eslint-disable no-bitwise */
+        prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
+        /* eslint-enable no-bitwise */
+      } while (document.getElementById(prefix));
+      return prefix;
+    },
+    getSelectorFromElement: function getSelectorFromElement(element) {
+      var selector = element.getAttribute('data-target');
+
+      if (!selector) {
+        selector = element.getAttribute('href') || '';
+        selector = /^#[a-z]/i.test(selector) ? selector : null;
+      }
+
+      return selector;
+    },
+    reflow: function reflow(element) {
+      new Function('bs', 'return bs')(element.offsetHeight);
+    },
+    triggerTransitionEnd: function triggerTransitionEnd(element) {
+      $(element).trigger(transition.end);
+    },
+    supportsTransitionEnd: function supportsTransitionEnd() {
+      return Boolean(transition);
+    },
+    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
+      for (var property in configTypes) {
+        if (configTypes.hasOwnProperty(property)) {
+          var expectedTypes = configTypes[property];
+          var value = config[property];
+          var valueType = void 0;
+
+          if (value && isElement(value)) {
+            valueType = 'element';
+          } else {
+            valueType = toType(value);
+          }
+
+          if (!new RegExp(expectedTypes).test(valueType)) {
+            throw new Error(componentName.toUpperCase() + ': ' + ('Option "' + property + '" provided type "' + valueType + '" ') + ('but expected type "' + expectedTypes + '".'));
+          }
+        }
+      }
+    }
+  };
+
+  setTransitionEndSupport();
+
+  return Util;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): alert.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Alert = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'alert';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.alert';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Selector = {
+    DISMISS: '[data-dismiss="alert"]'
+  };
+
+  var Event = {
+    CLOSE: 'close' + EVENT_KEY,
+    CLOSED: 'closed' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    ALERT: 'alert',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Alert = function () {
+    function Alert(element) {
+      _classCallCheck(this, Alert);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Alert.prototype.close = function close(element) {
+      element = element || this._element;
+
+      var rootElement = this._getRootElement(element);
+      var customEvent = this._triggerCloseEvent(rootElement);
+
+      if (customEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._removeElement(rootElement);
+    };
+
+    Alert.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Alert.prototype._getRootElement = function _getRootElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      var parent = false;
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      if (!parent) {
+        parent = $(element).closest('.' + ClassName.ALERT)[0];
+      }
+
+      return parent;
+    };
+
+    Alert.prototype._triggerCloseEvent = function _triggerCloseEvent(element) {
+      var closeEvent = $.Event(Event.CLOSE);
+
+      $(element).trigger(closeEvent);
+      return closeEvent;
+    };
+
+    Alert.prototype._removeElement = function _removeElement(element) {
+      $(element).removeClass(ClassName.IN);
+
+      if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {
+        this._destroyElement(element);
+        return;
+      }
+
+      $(element).one(Util.TRANSITION_END, $.proxy(this._destroyElement, this, element)).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Alert.prototype._destroyElement = function _destroyElement(element) {
+      $(element).detach().trigger(Event.CLOSED).remove();
+    };
+
+    // static
+
+    Alert._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $element = $(this);
+        var data = $element.data(DATA_KEY);
+
+        if (!data) {
+          data = new Alert(this);
+          $element.data(DATA_KEY, data);
+        }
+
+        if (config === 'close') {
+          data[config](this);
+        }
+      });
+    };
+
+    Alert._handleDismiss = function _handleDismiss(alertInstance) {
+      return function (event) {
+        if (event) {
+          event.preventDefault();
+        }
+
+        alertInstance.close(this);
+      };
+    };
+
+    _createClass(Alert, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Alert;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Alert._jQueryInterface;
+  $.fn[NAME].Constructor = Alert;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Alert._jQueryInterface;
+  };
+
+  return Alert;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): button.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Button = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'button';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.button';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var ClassName = {
+    ACTIVE: 'active',
+    BUTTON: 'btn',
+    FOCUS: 'focus'
+  };
+
+  var Selector = {
+    DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
+    DATA_TOGGLE: '[data-toggle="buttons"]',
+    INPUT: 'input',
+    ACTIVE: '.active',
+    BUTTON: '.btn'
+  };
+
+  var Event = {
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    FOCUS_BLUR_DATA_API: 'focus' + EVENT_KEY + DATA_API_KEY + ' ' + ('blur' + EVENT_KEY + DATA_API_KEY)
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Button = function () {
+    function Button(element) {
+      _classCallCheck(this, Button);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Button.prototype.toggle = function toggle() {
+      var triggerChangeEvent = true;
+      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];
+
+      if (rootElement) {
+        var input = $(this._element).find(Selector.INPUT)[0];
+
+        if (input) {
+          if (input.type === 'radio') {
+            if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) {
+              triggerChangeEvent = false;
+            } else {
+              var activeElement = $(rootElement).find(Selector.ACTIVE)[0];
+
+              if (activeElement) {
+                $(activeElement).removeClass(ClassName.ACTIVE);
+              }
+            }
+          }
+
+          if (triggerChangeEvent) {
+            input.checked = !$(this._element).hasClass(ClassName.ACTIVE);
+            $(this._element).trigger('change');
+          }
+
+          input.focus();
+        }
+      } else {
+        this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));
+      }
+
+      if (triggerChangeEvent) {
+        $(this._element).toggleClass(ClassName.ACTIVE);
+      }
+    };
+
+    Button.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // static
+
+    Button._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          data = new Button(this);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (config === 'toggle') {
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Button, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Button;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    event.preventDefault();
+
+    var button = event.target;
+
+    if (!$(button).hasClass(ClassName.BUTTON)) {
+      button = $(button).closest(Selector.BUTTON);
+    }
+
+    Button._jQueryInterface.call($(button), 'toggle');
+  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    var button = $(event.target).closest(Selector.BUTTON)[0];
+    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Button._jQueryInterface;
+  $.fn[NAME].Constructor = Button;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Button._jQueryInterface;
+  };
+
+  return Button;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): carousel.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Carousel = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'carousel';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.carousel';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
+  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
+
+  var Default = {
+    interval: 5000,
+    keyboard: true,
+    slide: false,
+    pause: 'hover',
+    wrap: true
+  };
+
+  var DefaultType = {
+    interval: '(number|boolean)',
+    keyboard: 'boolean',
+    slide: '(boolean|string)',
+    pause: '(string|boolean)',
+    wrap: 'boolean'
+  };
+
+  var Direction = {
+    NEXT: 'next',
+    PREVIOUS: 'prev'
+  };
+
+  var Event = {
+    SLIDE: 'slide' + EVENT_KEY,
+    SLID: 'slid' + EVENT_KEY,
+    KEYDOWN: 'keydown' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    CAROUSEL: 'carousel',
+    ACTIVE: 'active',
+    SLIDE: 'slide',
+    RIGHT: 'right',
+    LEFT: 'left',
+    ITEM: 'carousel-item'
+  };
+
+  var Selector = {
+    ACTIVE: '.active',
+    ACTIVE_ITEM: '.active.carousel-item',
+    ITEM: '.carousel-item',
+    NEXT_PREV: '.next, .prev',
+    INDICATORS: '.carousel-indicators',
+    DATA_SLIDE: '[data-slide], [data-slide-to]',
+    DATA_RIDE: '[data-ride="carousel"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Carousel = function () {
+    function Carousel(element, config) {
+      _classCallCheck(this, Carousel);
+
+      this._items = null;
+      this._interval = null;
+      this._activeElement = null;
+
+      this._isPaused = false;
+      this._isSliding = false;
+
+      this._config = this._getConfig(config);
+      this._element = $(element)[0];
+      this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Carousel.prototype.next = function next() {
+      if (!this._isSliding) {
+        this._slide(Direction.NEXT);
+      }
+    };
+
+    Carousel.prototype.nextWhenVisible = function nextWhenVisible() {
+      // Don't call next when the page isn't visible
+      if (!document.hidden) {
+        this.next();
+      }
+    };
+
+    Carousel.prototype.prev = function prev() {
+      if (!this._isSliding) {
+        this._slide(Direction.PREVIOUS);
+      }
+    };
+
+    Carousel.prototype.pause = function pause(event) {
+      if (!event) {
+        this._isPaused = true;
+      }
+
+      if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {
+        Util.triggerTransitionEnd(this._element);
+        this.cycle(true);
+      }
+
+      clearInterval(this._interval);
+      this._interval = null;
+    };
+
+    Carousel.prototype.cycle = function cycle(event) {
+      if (!event) {
+        this._isPaused = false;
+      }
+
+      if (this._interval) {
+        clearInterval(this._interval);
+        this._interval = null;
+      }
+
+      if (this._config.interval && !this._isPaused) {
+        this._interval = setInterval($.proxy(document.visibilityState ? this.nextWhenVisible : this.next, this), this._config.interval);
+      }
+    };
+
+    Carousel.prototype.to = function to(index) {
+      var _this2 = this;
+
+      this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+
+      var activeIndex = this._getItemIndex(this._activeElement);
+
+      if (index > this._items.length - 1 || index < 0) {
+        return;
+      }
+
+      if (this._isSliding) {
+        $(this._element).one(Event.SLID, function () {
+          return _this2.to(index);
+        });
+        return;
+      }
+
+      if (activeIndex === index) {
+        this.pause();
+        this.cycle();
+        return;
+      }
+
+      var direction = index > activeIndex ? Direction.NEXT : Direction.PREVIOUS;
+
+      this._slide(direction, this._items[index]);
+    };
+
+    Carousel.prototype.dispose = function dispose() {
+      $(this._element).off(EVENT_KEY);
+      $.removeData(this._element, DATA_KEY);
+
+      this._items = null;
+      this._config = null;
+      this._element = null;
+      this._interval = null;
+      this._isPaused = null;
+      this._isSliding = null;
+      this._activeElement = null;
+      this._indicatorsElement = null;
+    };
+
+    // private
+
+    Carousel.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Carousel.prototype._addEventListeners = function _addEventListeners() {
+      if (this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN, $.proxy(this._keydown, this));
+      }
+
+      if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
+        $(this._element).on(Event.MOUSEENTER, $.proxy(this.pause, this)).on(Event.MOUSELEAVE, $.proxy(this.cycle, this));
+      }
+    };
+
+    Carousel.prototype._keydown = function _keydown(event) {
+      event.preventDefault();
+
+      if (/input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      switch (event.which) {
+        case ARROW_LEFT_KEYCODE:
+          this.prev();
+          break;
+        case ARROW_RIGHT_KEYCODE:
+          this.next();
+          break;
+        default:
+          return;
+      }
+    };
+
+    Carousel.prototype._getItemIndex = function _getItemIndex(element) {
+      this._items = $.makeArray($(element).parent().find(Selector.ITEM));
+      return this._items.indexOf(element);
+    };
+
+    Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) {
+      var isNextDirection = direction === Direction.NEXT;
+      var isPrevDirection = direction === Direction.PREVIOUS;
+      var activeIndex = this._getItemIndex(activeElement);
+      var lastItemIndex = this._items.length - 1;
+      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
+
+      if (isGoingToWrap && !this._config.wrap) {
+        return activeElement;
+      }
+
+      var delta = direction === Direction.PREVIOUS ? -1 : 1;
+      var itemIndex = (activeIndex + delta) % this._items.length;
+
+      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
+    };
+
+    Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, directionalClassname) {
+      var slideEvent = $.Event(Event.SLIDE, {
+        relatedTarget: relatedTarget,
+        direction: directionalClassname
+      });
+
+      $(this._element).trigger(slideEvent);
+
+      return slideEvent;
+    };
+
+    Carousel.prototype._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
+      if (this._indicatorsElement) {
+        $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+
+        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
+
+        if (nextIndicator) {
+          $(nextIndicator).addClass(ClassName.ACTIVE);
+        }
+      }
+    };
+
+    Carousel.prototype._slide = function _slide(direction, element) {
+      var _this3 = this;
+
+      var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
+
+      var isCycling = Boolean(this._interval);
+
+      var directionalClassName = direction === Direction.NEXT ? ClassName.LEFT : ClassName.RIGHT;
+
+      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {
+        this._isSliding = false;
+        return;
+      }
+
+      var slideEvent = this._triggerSlideEvent(nextElement, directionalClassName);
+      if (slideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (!activeElement || !nextElement) {
+        // some weirdness is happening, so we bail
+        return;
+      }
+
+      this._isSliding = true;
+
+      if (isCycling) {
+        this.pause();
+      }
+
+      this._setActiveIndicatorElement(nextElement);
+
+      var slidEvent = $.Event(Event.SLID, {
+        relatedTarget: nextElement,
+        direction: directionalClassName
+      });
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {
+
+        $(nextElement).addClass(direction);
+
+        Util.reflow(nextElement);
+
+        $(activeElement).addClass(directionalClassName);
+        $(nextElement).addClass(directionalClassName);
+
+        $(activeElement).one(Util.TRANSITION_END, function () {
+          $(nextElement).removeClass(directionalClassName).removeClass(direction);
+
+          $(nextElement).addClass(ClassName.ACTIVE);
+
+          $(activeElement).removeClass(ClassName.ACTIVE).removeClass(direction).removeClass(directionalClassName);
+
+          _this3._isSliding = false;
+
+          setTimeout(function () {
+            return $(_this3._element).trigger(slidEvent);
+          }, 0);
+        }).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        $(activeElement).removeClass(ClassName.ACTIVE);
+        $(nextElement).addClass(ClassName.ACTIVE);
+
+        this._isSliding = false;
+        $(this._element).trigger(slidEvent);
+      }
+
+      if (isCycling) {
+        this.cycle();
+      }
+    };
+
+    // static
+
+    Carousel._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Default, $(this).data());
+
+        if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
+          $.extend(_config, config);
+        }
+
+        var action = typeof config === 'string' ? config : _config.slide;
+
+        if (!data) {
+          data = new Carousel(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'number') {
+          data.to(config);
+        } else if (typeof action === 'string') {
+          if (data[action] === undefined) {
+            throw new Error('No method named "' + action + '"');
+          }
+          data[action]();
+        } else if (_config.interval) {
+          data.pause();
+          data.cycle();
+        }
+      });
+    };
+
+    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
+      var selector = Util.getSelectorFromElement(this);
+
+      if (!selector) {
+        return;
+      }
+
+      var target = $(selector)[0];
+
+      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {
+        return;
+      }
+
+      var config = $.extend({}, $(target).data(), $(this).data());
+      var slideIndex = this.getAttribute('data-slide-to');
+
+      if (slideIndex) {
+        config.interval = false;
+      }
+
+      Carousel._jQueryInterface.call($(target), config);
+
+      if (slideIndex) {
+        $(target).data(DATA_KEY).to(slideIndex);
+      }
+
+      event.preventDefault();
+    };
+
+    _createClass(Carousel, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Carousel;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    $(Selector.DATA_RIDE).each(function () {
+      var $carousel = $(this);
+      Carousel._jQueryInterface.call($carousel, $carousel.data());
+    });
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Carousel._jQueryInterface;
+  $.fn[NAME].Constructor = Carousel;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Carousel._jQueryInterface;
+  };
+
+  return Carousel;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): collapse.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Collapse = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'collapse';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.collapse';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+
+  var Default = {
+    toggle: true,
+    parent: ''
+  };
+
+  var DefaultType = {
+    toggle: 'boolean',
+    parent: 'string'
+  };
+
+  var Event = {
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    IN: 'in',
+    COLLAPSE: 'collapse',
+    COLLAPSING: 'collapsing',
+    COLLAPSED: 'collapsed'
+  };
+
+  var Dimension = {
+    WIDTH: 'width',
+    HEIGHT: 'height'
+  };
+
+  var Selector = {
+    ACTIVES: '.card > .in, .card > .collapsing',
+    DATA_TOGGLE: '[data-toggle="collapse"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Collapse = function () {
+    function Collapse(element, config) {
+      _classCallCheck(this, Collapse);
+
+      this._isTransitioning = false;
+      this._element = element;
+      this._config = this._getConfig(config);
+      this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
+
+      this._parent = this._config.parent ? this._getParent() : null;
+
+      if (!this._config.parent) {
+        this._addAriaAndCollapsedClass(this._element, this._triggerArray);
+      }
+
+      if (this._config.toggle) {
+        this.toggle();
+      }
+    }
+
+    // getters
+
+    // public
+
+    Collapse.prototype.toggle = function toggle() {
+      if ($(this._element).hasClass(ClassName.IN)) {
+        this.hide();
+      } else {
+        this.show();
+      }
+    };
+
+    Collapse.prototype.show = function show() {
+      var _this4 = this;
+
+      if (this._isTransitioning || $(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var actives = void 0;
+      var activesData = void 0;
+
+      if (this._parent) {
+        actives = $.makeArray($(Selector.ACTIVES));
+        if (!actives.length) {
+          actives = null;
+        }
+      }
+
+      if (actives) {
+        activesData = $(actives).data(DATA_KEY);
+        if (activesData && activesData._isTransitioning) {
+          return;
+        }
+      }
+
+      var startEvent = $.Event(Event.SHOW);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (actives) {
+        Collapse._jQueryInterface.call($(actives), 'hide');
+        if (!activesData) {
+          $(actives).data(DATA_KEY, null);
+        }
+      }
+
+      var dimension = this._getDimension();
+
+      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
+
+      this._element.style[dimension] = 0;
+      this._element.setAttribute('aria-expanded', true);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        $(_this4._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.IN);
+
+        _this4._element.style[dimension] = '';
+
+        _this4.setTransitioning(false);
+
+        $(_this4._element).trigger(Event.SHOWN);
+      };
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
+      var scrollSize = 'scroll' + capitalizedDimension;
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+
+      this._element.style[dimension] = this._element[scrollSize] + 'px';
+    };
+
+    Collapse.prototype.hide = function hide() {
+      var _this5 = this;
+
+      if (this._isTransitioning || !$(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var startEvent = $.Event(Event.HIDE);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      var dimension = this._getDimension();
+      var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight';
+
+      this._element.style[dimension] = this._element[offsetDimension] + 'px';
+
+      Util.reflow(this._element);
+
+      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.IN);
+
+      this._element.setAttribute('aria-expanded', false);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        _this5.setTransitioning(false);
+        $(_this5._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
+      };
+
+      this._element.style[dimension] = '';
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Collapse.prototype.setTransitioning = function setTransitioning(isTransitioning) {
+      this._isTransitioning = isTransitioning;
+    };
+
+    Collapse.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      this._config = null;
+      this._parent = null;
+      this._element = null;
+      this._triggerArray = null;
+      this._isTransitioning = null;
+    };
+
+    // private
+
+    Collapse.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      config.toggle = Boolean(config.toggle); // coerce string values
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Collapse.prototype._getDimension = function _getDimension() {
+      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);
+      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
+    };
+
+    Collapse.prototype._getParent = function _getParent() {
+      var _this6 = this;
+
+      var parent = $(this._config.parent)[0];
+      var selector = '[data-toggle="collapse"][data-parent="' + this._config.parent + '"]';
+
+      $(parent).find(selector).each(function (i, element) {
+        _this6._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
+      });
+
+      return parent;
+    };
+
+    Collapse.prototype._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
+      if (element) {
+        var isOpen = $(element).hasClass(ClassName.IN);
+        element.setAttribute('aria-expanded', isOpen);
+
+        if (triggerArray.length) {
+          $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
+        }
+      }
+    };
+
+    // static
+
+    Collapse._getTargetFromElement = function _getTargetFromElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      return selector ? $(selector)[0] : null;
+    };
+
+    Collapse._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+        var _config = $.extend({}, Default, $this.data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data && _config.toggle && /show|hide/.test(config)) {
+          _config.toggle = false;
+        }
+
+        if (!data) {
+          data = new Collapse(this, _config);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Collapse, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Collapse;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+
+    var target = Collapse._getTargetFromElement(this);
+    var data = $(target).data(DATA_KEY);
+    var config = data ? 'toggle' : $(this).data();
+
+    Collapse._jQueryInterface.call($(target), config);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Collapse._jQueryInterface;
+  $.fn[NAME].Constructor = Collapse;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Collapse._jQueryInterface;
+  };
+
+  return Collapse;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): dropdown.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Dropdown = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'dropdown';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.dropdown';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
+  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
+  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    BACKDROP: 'dropdown-backdrop',
+    DISABLED: 'disabled',
+    OPEN: 'open'
+  };
+
+  var Selector = {
+    BACKDROP: '.dropdown-backdrop',
+    DATA_TOGGLE: '[data-toggle="dropdown"]',
+    FORM_CHILD: '.dropdown form',
+    ROLE_MENU: '[role="menu"]',
+    ROLE_LISTBOX: '[role="listbox"]',
+    NAVBAR_NAV: '.navbar-nav',
+    VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Dropdown = function () {
+    function Dropdown(element) {
+      _classCallCheck(this, Dropdown);
+
+      this._element = element;
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Dropdown.prototype.toggle = function toggle() {
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return false;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      Dropdown._clearMenus();
+
+      if (isActive) {
+        return false;
+      }
+
+      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
+
+        // if mobile we use a backdrop because click events don't delegate
+        var dropdown = document.createElement('div');
+        dropdown.className = ClassName.BACKDROP;
+        $(dropdown).insertBefore(this);
+        $(dropdown).on('click', Dropdown._clearMenus);
+      }
+
+      var relatedTarget = { relatedTarget: this };
+      var showEvent = $.Event(Event.SHOW, relatedTarget);
+
+      $(parent).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented()) {
+        return false;
+      }
+
+      this.focus();
+      this.setAttribute('aria-expanded', 'true');
+
+      $(parent).toggleClass(ClassName.OPEN);
+      $(parent).trigger($.Event(Event.SHOWN, relatedTarget));
+
+      return false;
+    };
+
+    Dropdown.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._element).off(EVENT_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Dropdown.prototype._addEventListeners = function _addEventListeners() {
+      $(this._element).on(Event.CLICK, this.toggle);
+    };
+
+    // static
+
+    Dropdown._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          $(this).data(DATA_KEY, data = new Dropdown(this));
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config].call(this);
+        }
+      });
+    };
+
+    Dropdown._clearMenus = function _clearMenus(event) {
+      if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
+        return;
+      }
+
+      var backdrop = $(Selector.BACKDROP)[0];
+      if (backdrop) {
+        backdrop.parentNode.removeChild(backdrop);
+      }
+
+      var toggles = $.makeArray($(Selector.DATA_TOGGLE));
+
+      for (var i = 0; i < toggles.length; i++) {
+        var parent = Dropdown._getParentFromElement(toggles[i]);
+        var relatedTarget = { relatedTarget: toggles[i] };
+
+        if (!$(parent).hasClass(ClassName.OPEN)) {
+          continue;
+        }
+
+        if (event && event.type === 'click' && /input|textarea/i.test(event.target.tagName) && $.contains(parent, event.target)) {
+          continue;
+        }
+
+        var hideEvent = $.Event(Event.HIDE, relatedTarget);
+        $(parent).trigger(hideEvent);
+        if (hideEvent.isDefaultPrevented()) {
+          continue;
+        }
+
+        toggles[i].setAttribute('aria-expanded', 'false');
+
+        $(parent).removeClass(ClassName.OPEN).trigger($.Event(Event.HIDDEN, relatedTarget));
+      }
+    };
+
+    Dropdown._getParentFromElement = function _getParentFromElement(element) {
+      var parent = void 0;
+      var selector = Util.getSelectorFromElement(element);
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      return parent || element.parentNode;
+    };
+
+    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
+      if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      event.preventDefault();
+      event.stopPropagation();
+
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {
+
+        if (event.which === ESCAPE_KEYCODE) {
+          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
+          $(toggle).trigger('focus');
+        }
+
+        $(this).trigger('click');
+        return;
+      }
+
+      var items = $.makeArray($(Selector.VISIBLE_ITEMS));
+
+      items = items.filter(function (item) {
+        return item.offsetWidth || item.offsetHeight;
+      });
+
+      if (!items.length) {
+        return;
+      }
+
+      var index = items.indexOf(event.target);
+
+      if (event.which === ARROW_UP_KEYCODE && index > 0) {
+        // up
+        index--;
+      }
+
+      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
+        // down
+        index++;
+      }
+
+      if (index < 0) {
+        index = 0;
+      }
+
+      items[index].focus();
+    };
+
+    _createClass(Dropdown, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Dropdown;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
+    e.stopPropagation();
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Dropdown._jQueryInterface;
+  $.fn[NAME].Constructor = Dropdown;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Dropdown._jQueryInterface;
+  };
+
+  return Dropdown;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): modal.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Modal = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'modal';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.modal';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 300;
+  var BACKDROP_TRANSITION_DURATION = 150;
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+
+  var Default = {
+    backdrop: true,
+    keyboard: true,
+    focus: true,
+    show: true
+  };
+
+  var DefaultType = {
+    backdrop: '(boolean|string)',
+    keyboard: 'boolean',
+    focus: 'boolean',
+    show: 'boolean'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    RESIZE: 'resize' + EVENT_KEY,
+    CLICK_DISMISS: 'click.dismiss' + EVENT_KEY,
+    KEYDOWN_DISMISS: 'keydown.dismiss' + EVENT_KEY,
+    MOUSEUP_DISMISS: 'mouseup.dismiss' + EVENT_KEY,
+    MOUSEDOWN_DISMISS: 'mousedown.dismiss' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
+    BACKDROP: 'modal-backdrop',
+    OPEN: 'modal-open',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    DIALOG: '.modal-dialog',
+    DATA_TOGGLE: '[data-toggle="modal"]',
+    DATA_DISMISS: '[data-dismiss="modal"]',
+    FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Modal = function () {
+    function Modal(element, config) {
+      _classCallCheck(this, Modal);
+
+      this._config = this._getConfig(config);
+      this._element = element;
+      this._dialog = $(element).find(Selector.DIALOG)[0];
+      this._backdrop = null;
+      this._isShown = false;
+      this._isBodyOverflowing = false;
+      this._ignoreBackdropClick = false;
+      this._originalBodyPadding = 0;
+      this._scrollbarWidth = 0;
+    }
+
+    // getters
+
+    // public
+
+    Modal.prototype.toggle = function toggle(relatedTarget) {
+      return this._isShown ? this.hide() : this.show(relatedTarget);
+    };
+
+    Modal.prototype.show = function show(relatedTarget) {
+      var _this7 = this;
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: relatedTarget
+      });
+
+      $(this._element).trigger(showEvent);
+
+      if (this._isShown || showEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = true;
+
+      this._checkScrollbar();
+      this._setScrollbar();
+
+      $(document.body).addClass(ClassName.OPEN);
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, $.proxy(this.hide, this));
+
+      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
+        $(_this7._element).one(Event.MOUSEUP_DISMISS, function (event) {
+          if ($(event.target).is(_this7._element)) {
+            _this7._ignoreBackdropClick = true;
+          }
+        });
+      });
+
+      this._showBackdrop($.proxy(this._showElement, this, relatedTarget));
+    };
+
+    Modal.prototype.hide = function hide(event) {
+      if (event) {
+        event.preventDefault();
+      }
+
+      var hideEvent = $.Event(Event.HIDE);
+
+      $(this._element).trigger(hideEvent);
+
+      if (!this._isShown || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = false;
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(document).off(Event.FOCUSIN);
+
+      $(this._element).removeClass(ClassName.IN);
+
+      $(this._element).off(Event.CLICK_DISMISS);
+      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+
+        $(this._element).one(Util.TRANSITION_END, $.proxy(this._hideModal, this)).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        this._hideModal();
+      }
+    };
+
+    Modal.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      $(window).off(EVENT_KEY);
+      $(document).off(EVENT_KEY);
+      $(this._element).off(EVENT_KEY);
+      $(this._backdrop).off(EVENT_KEY);
+
+      this._config = null;
+      this._element = null;
+      this._dialog = null;
+      this._backdrop = null;
+      this._isShown = null;
+      this._isBodyOverflowing = null;
+      this._ignoreBackdropClick = null;
+      this._originalBodyPadding = null;
+      this._scrollbarWidth = null;
+    };
+
+    // private
+
+    Modal.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Modal.prototype._showElement = function _showElement(relatedTarget) {
+      var _this8 = this;
+
+      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);
+
+      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
+        // don't move modals dom position
+        document.body.appendChild(this._element);
+      }
+
+      this._element.style.display = 'block';
+      this._element.removeAttribute('aria-hidden');
+      this._element.scrollTop = 0;
+
+      if (transition) {
+        Util.reflow(this._element);
+      }
+
+      $(this._element).addClass(ClassName.IN);
+
+      if (this._config.focus) {
+        this._enforceFocus();
+      }
+
+      var shownEvent = $.Event(Event.SHOWN, {
+        relatedTarget: relatedTarget
+      });
+
+      var transitionComplete = function transitionComplete() {
+        if (_this8._config.focus) {
+          _this8._element.focus();
+        }
+        $(_this8._element).trigger(shownEvent);
+      };
+
+      if (transition) {
+        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        transitionComplete();
+      }
+    };
+
+    Modal.prototype._enforceFocus = function _enforceFocus() {
+      var _this9 = this;
+
+      $(document).off(Event.FOCUSIN) // guard against infinite focus loop
+      .on(Event.FOCUSIN, function (event) {
+        if (document !== event.target && _this9._element !== event.target && !$(_this9._element).has(event.target).length) {
+          _this9._element.focus();
+        }
+      });
+    };
+
+    Modal.prototype._setEscapeEvent = function _setEscapeEvent() {
+      var _this10 = this;
+
+      if (this._isShown && this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
+          if (event.which === ESCAPE_KEYCODE) {
+            _this10.hide();
+          }
+        });
+      } else if (!this._isShown) {
+        $(this._element).off(Event.KEYDOWN_DISMISS);
+      }
+    };
+
+    Modal.prototype._setResizeEvent = function _setResizeEvent() {
+      if (this._isShown) {
+        $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this));
+      } else {
+        $(window).off(Event.RESIZE);
+      }
+    };
+
+    Modal.prototype._hideModal = function _hideModal() {
+      var _this11 = this;
+
+      this._element.style.display = 'none';
+      this._element.setAttribute('aria-hidden', 'true');
+      this._showBackdrop(function () {
+        $(document.body).removeClass(ClassName.OPEN);
+        _this11._resetAdjustments();
+        _this11._resetScrollbar();
+        $(_this11._element).trigger(Event.HIDDEN);
+      });
+    };
+
+    Modal.prototype._removeBackdrop = function _removeBackdrop() {
+      if (this._backdrop) {
+        $(this._backdrop).remove();
+        this._backdrop = null;
+      }
+    };
+
+    Modal.prototype._showBackdrop = function _showBackdrop(callback) {
+      var _this12 = this;
+
+      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
+
+      if (this._isShown && this._config.backdrop) {
+        var doAnimate = Util.supportsTransitionEnd() && animate;
+
+        this._backdrop = document.createElement('div');
+        this._backdrop.className = ClassName.BACKDROP;
+
+        if (animate) {
+          $(this._backdrop).addClass(animate);
+        }
+
+        $(this._backdrop).appendTo(document.body);
+
+        $(this._element).on(Event.CLICK_DISMISS, function (event) {
+          if (_this12._ignoreBackdropClick) {
+            _this12._ignoreBackdropClick = false;
+            return;
+          }
+          if (event.target !== event.currentTarget) {
+            return;
+          }
+          if (_this12._config.backdrop === 'static') {
+            _this12._element.focus();
+          } else {
+            _this12.hide();
+          }
+        });
+
+        if (doAnimate) {
+          Util.reflow(this._backdrop);
+        }
+
+        $(this._backdrop).addClass(ClassName.IN);
+
+        if (!callback) {
+          return;
+        }
+
+        if (!doAnimate) {
+          callback();
+          return;
+        }
+
+        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+      } else if (!this._isShown && this._backdrop) {
+        $(this._backdrop).removeClass(ClassName.IN);
+
+        var callbackRemove = function callbackRemove() {
+          _this12._removeBackdrop();
+          if (callback) {
+            callback();
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+        } else {
+          callbackRemove();
+        }
+      } else if (callback) {
+        callback();
+      }
+    };
+
+    // ----------------------------------------------------------------------
+    // the following methods are used to handle overflowing modals
+    // todo (fat): these should probably be refactored out of modal.js
+    // ----------------------------------------------------------------------
+
+    Modal.prototype._handleUpdate = function _handleUpdate() {
+      this._adjustDialog();
+    };
+
+    Modal.prototype._adjustDialog = function _adjustDialog() {
+      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+      if (!this._isBodyOverflowing && isModalOverflowing) {
+        this._element.style.paddingLeft = this._scrollbarWidth + 'px';
+      }
+
+      if (this._isBodyOverflowing && !isModalOverflowing) {
+        this._element.style.paddingRight = this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetAdjustments = function _resetAdjustments() {
+      this._element.style.paddingLeft = '';
+      this._element.style.paddingRight = '';
+    };
+
+    Modal.prototype._checkScrollbar = function _checkScrollbar() {
+      this._isBodyOverflowing = document.body.clientWidth < window.innerWidth;
+      this._scrollbarWidth = this._getScrollbarWidth();
+    };
+
+    Modal.prototype._setScrollbar = function _setScrollbar() {
+      var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10);
+
+      this._originalBodyPadding = document.body.style.paddingRight || '';
+
+      if (this._isBodyOverflowing) {
+        document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetScrollbar = function _resetScrollbar() {
+      document.body.style.paddingRight = this._originalBodyPadding;
+    };
+
+    Modal.prototype._getScrollbarWidth = function _getScrollbarWidth() {
+      // thx d.walsh
+      var scrollDiv = document.createElement('div');
+      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
+      document.body.appendChild(scrollDiv);
+      var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+      document.body.removeChild(scrollDiv);
+      return scrollbarWidth;
+    };
+
+    // static
+
+    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Modal.Default, $(this).data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data) {
+          data = new Modal(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config](relatedTarget);
+        } else if (_config.show) {
+          data.show(relatedTarget);
+        }
+      });
+    };
+
+    _createClass(Modal, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Modal;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    var _this13 = this;
+
+    var target = void 0;
+    var selector = Util.getSelectorFromElement(this);
+
+    if (selector) {
+      target = $(selector)[0];
+    }
+
+    var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data());
+
+    if (this.tagName === 'A') {
+      event.preventDefault();
+    }
+
+    var $target = $(target).one(Event.SHOW, function (showEvent) {
+      if (showEvent.isDefaultPrevented()) {
+        // only register focus restorer if modal will actually get shown
+        return;
+      }
+
+      $target.one(Event.HIDDEN, function () {
+        if ($(_this13).is(':visible')) {
+          _this13.focus();
+        }
+      });
+    });
+
+    Modal._jQueryInterface.call($(target), config, this);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Modal._jQueryInterface;
+  $.fn[NAME].Constructor = Modal;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Modal._jQueryInterface;
+  };
+
+  return Modal;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): scrollspy.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var ScrollSpy = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'scrollspy';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.scrollspy';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = {
+    offset: 10,
+    method: 'auto',
+    target: ''
+  };
+
+  var DefaultType = {
+    offset: 'number',
+    method: 'string',
+    target: '(string|element)'
+  };
+
+  var Event = {
+    ACTIVATE: 'activate' + EVENT_KEY,
+    SCROLL: 'scroll' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_ITEM: 'dropdown-item',
+    DROPDOWN_MENU: 'dropdown-menu',
+    NAV_LINK: 'nav-link',
+    NAV: 'nav',
+    ACTIVE: 'active'
+  };
+
+  var Selector = {
+    DATA_SPY: '[data-spy="scroll"]',
+    ACTIVE: '.active',
+    LIST_ITEM: '.list-item',
+    LI: 'li',
+    LI_DROPDOWN: 'li.dropdown',
+    NAV_LINKS: '.nav-link',
+    DROPDOWN: '.dropdown',
+    DROPDOWN_ITEMS: '.dropdown-item',
+    DROPDOWN_TOGGLE: '.dropdown-toggle'
+  };
+
+  var OffsetMethod = {
+    OFFSET: 'offset',
+    POSITION: 'position'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var ScrollSpy = function () {
+    function ScrollSpy(element, config) {
+      _classCallCheck(this, ScrollSpy);
+
+      this._element = element;
+      this._scrollElement = element.tagName === 'BODY' ? window : element;
+      this._config = this._getConfig(config);
+      this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
+      this._offsets = [];
+      this._targets = [];
+      this._activeTarget = null;
+      this._scrollHeight = 0;
+
+      $(this._scrollElement).on(Event.SCROLL, $.proxy(this._process, this));
+
+      this.refresh();
+      this._process();
+    }
+
+    // getters
+
+    // public
+
+    ScrollSpy.prototype.refresh = function refresh() {
+      var _this14 = this;
+
+      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
+
+      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
+
+      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
+
+      this._offsets = [];
+      this._targets = [];
+
+      this._scrollHeight = this._getScrollHeight();
+
+      var targets = $.makeArray($(this._selector));
+
+      targets.map(function (element) {
+        var target = void 0;
+        var targetSelector = Util.getSelectorFromElement(element);
+
+        if (targetSelector) {
+          target = $(targetSelector)[0];
+        }
+
+        if (target && (target.offsetWidth || target.offsetHeight)) {
+          // todo (fat): remove sketch reliance on jQuery position/offset
+          return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
+        }
+        return null;
+      }).filter(function (item) {
+        return item;
+      }).sort(function (a, b) {
+        return a[0] - b[0];
+      }).forEach(function (item) {
+        _this14._offsets.push(item[0]);
+        _this14._targets.push(item[1]);
+      });
+    };
+
+    ScrollSpy.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._scrollElement).off(EVENT_KEY);
+
+      this._element = null;
+      this._scrollElement = null;
+      this._config = null;
+      this._selector = null;
+      this._offsets = null;
+      this._targets = null;
+      this._activeTarget = null;
+      this._scrollHeight = null;
+    };
+
+    // private
+
+    ScrollSpy.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+
+      if (typeof config.target !== 'string') {
+        var id = $(config.target).attr('id');
+        if (!id) {
+          id = Util.getUID(NAME);
+          $(config.target).attr('id', id);
+        }
+        config.target = '#' + id;
+      }
+
+      Util.typeCheckConfig(NAME, config, DefaultType);
+
+      return config;
+    };
+
+    ScrollSpy.prototype._getScrollTop = function _getScrollTop() {
+      return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
+    };
+
+    ScrollSpy.prototype._getScrollHeight = function _getScrollHeight() {
+      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
+    };
+
+    ScrollSpy.prototype._process = function _process() {
+      var scrollTop = this._getScrollTop() + this._config.offset;
+      var scrollHeight = this._getScrollHeight();
+      var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight;
+
+      if (this._scrollHeight !== scrollHeight) {
+        this.refresh();
+      }
+
+      if (scrollTop >= maxScroll) {
+        var target = this._targets[this._targets.length - 1];
+
+        if (this._activeTarget !== target) {
+          this._activate(target);
+        }
+      }
+
+      if (this._activeTarget && scrollTop < this._offsets[0]) {
+        this._activeTarget = null;
+        this._clear();
+        return;
+      }
+
+      for (var i = this._offsets.length; i--;) {
+        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (this._offsets[i + 1] === undefined || scrollTop < this._offsets[i + 1]);
+
+        if (isActiveTarget) {
+          this._activate(this._targets[i]);
+        }
+      }
+    };
+
+    ScrollSpy.prototype._activate = function _activate(target) {
+      this._activeTarget = target;
+
+      this._clear();
+
+      var queries = this._selector.split(',');
+      queries = queries.map(function (selector) {
+        return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
+      });
+
+      var $link = $(queries.join(','));
+
+      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
+        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        $link.addClass(ClassName.ACTIVE);
+      } else {
+        // todo (fat) this is kinda sus...
+        // recursively add actives to tested nav-links
+        $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
+      }
+
+      $(this._scrollElement).trigger(Event.ACTIVATE, {
+        relatedTarget: target
+      });
+    };
+
+    ScrollSpy.prototype._clear = function _clear() {
+      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+    };
+
+    // static
+
+    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config || null;
+
+        if (!data) {
+          data = new ScrollSpy(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(ScrollSpy, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return ScrollSpy;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    var scrollSpys = $.makeArray($(Selector.DATA_SPY));
+
+    for (var i = scrollSpys.length; i--;) {
+      var $spy = $(scrollSpys[i]);
+      ScrollSpy._jQueryInterface.call($spy, $spy.data());
+    }
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = ScrollSpy._jQueryInterface;
+  $.fn[NAME].Constructor = ScrollSpy;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return ScrollSpy._jQueryInterface;
+  };
+
+  return ScrollSpy;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tab.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tab = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tab';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tab';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_MENU: 'dropdown-menu',
+    ACTIVE: 'active',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    A: 'a',
+    LI: 'li',
+    DROPDOWN: '.dropdown',
+    UL: 'ul:not(.dropdown-menu)',
+    FADE_CHILD: '> .nav-item .fade, > .fade',
+    ACTIVE: '.active',
+    ACTIVE_CHILD: '> .nav-item > .active, > .active',
+    DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"]',
+    DROPDOWN_TOGGLE: '.dropdown-toggle',
+    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tab = function () {
+    function Tab(element) {
+      _classCallCheck(this, Tab);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Tab.prototype.show = function show() {
+      var _this15 = this;
+
+      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE)) {
+        return;
+      }
+
+      var target = void 0;
+      var previous = void 0;
+      var ulElement = $(this._element).closest(Selector.UL)[0];
+      var selector = Util.getSelectorFromElement(this._element);
+
+      if (ulElement) {
+        previous = $.makeArray($(ulElement).find(Selector.ACTIVE));
+        previous = previous[previous.length - 1];
+      }
+
+      var hideEvent = $.Event(Event.HIDE, {
+        relatedTarget: this._element
+      });
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: previous
+      });
+
+      if (previous) {
+        $(previous).trigger(hideEvent);
+      }
+
+      $(this._element).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (selector) {
+        target = $(selector)[0];
+      }
+
+      this._activate(this._element, ulElement);
+
+      var complete = function complete() {
+        var hiddenEvent = $.Event(Event.HIDDEN, {
+          relatedTarget: _this15._element
+        });
+
+        var shownEvent = $.Event(Event.SHOWN, {
+          relatedTarget: previous
+        });
+
+        $(previous).trigger(hiddenEvent);
+        $(_this15._element).trigger(shownEvent);
+      };
+
+      if (target) {
+        this._activate(target, target.parentNode, complete);
+      } else {
+        complete();
+      }
+    };
+
+    Tab.prototype.dispose = function dispose() {
+      $.removeClass(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Tab.prototype._activate = function _activate(element, container, callback) {
+      var active = $(container).find(Selector.ACTIVE_CHILD)[0];
+      var isTransitioning = callback && Util.supportsTransitionEnd() && (active && $(active).hasClass(ClassName.FADE) || Boolean($(container).find(Selector.FADE_CHILD)[0]));
+
+      var complete = $.proxy(this._transitionComplete, this, element, active, isTransitioning, callback);
+
+      if (active && isTransitioning) {
+        $(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      if (active) {
+        $(active).removeClass(ClassName.IN);
+      }
+    };
+
+    Tab.prototype._transitionComplete = function _transitionComplete(element, active, isTransitioning, callback) {
+      if (active) {
+        $(active).removeClass(ClassName.ACTIVE);
+
+        var dropdownChild = $(active).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
+
+        if (dropdownChild) {
+          $(dropdownChild).removeClass(ClassName.ACTIVE);
+        }
+
+        active.setAttribute('aria-expanded', false);
+      }
+
+      $(element).addClass(ClassName.ACTIVE);
+      element.setAttribute('aria-expanded', true);
+
+      if (isTransitioning) {
+        Util.reflow(element);
+        $(element).addClass(ClassName.IN);
+      } else {
+        $(element).removeClass(ClassName.FADE);
+      }
+
+      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
+
+        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];
+        if (dropdownElement) {
+          $(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        }
+
+        element.setAttribute('aria-expanded', true);
+      }
+
+      if (callback) {
+        callback();
+      }
+    };
+
+    // static
+
+    Tab._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+
+        if (!data) {
+          data = data = new Tab(this);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tab, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Tab;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+    Tab._jQueryInterface.call($(this), 'show');
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tab._jQueryInterface;
+  $.fn[NAME].Constructor = Tab;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tab._jQueryInterface;
+  };
+
+  return Tab;
+}(jQuery);
+
+/* global Tether */
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tooltip.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tooltip = function ($) {
+
+  /**
+   * Check for Tether dependency
+   * Tether - http://tether.io/
+   */
+  if (window.Tether === undefined) {
+    throw new Error('Bootstrap tooltips require Tether (http://tether.io/)');
+  }
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tooltip';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tooltip';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+  var CLASS_PREFIX = 'bs-tether';
+
+  var Default = {
+    animation: true,
+    template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    selector: false,
+    placement: 'top',
+    offset: '0 0',
+    constraints: []
+  };
+
+  var DefaultType = {
+    animation: 'boolean',
+    template: 'string',
+    title: '(string|element|function)',
+    trigger: 'string',
+    delay: '(number|object)',
+    html: 'boolean',
+    selector: '(string|boolean)',
+    placement: '(string|function)',
+    offset: 'string',
+    constraints: 'array'
+  };
+
+  var AttachmentMap = {
+    TOP: 'bottom center',
+    RIGHT: 'middle left',
+    BOTTOM: 'top center',
+    LEFT: 'middle right'
+  };
+
+  var HoverState = {
+    IN: 'in',
+    OUT: 'out'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TOOLTIP: '.tooltip',
+    TOOLTIP_INNER: '.tooltip-inner'
+  };
+
+  var TetherClass = {
+    element: false,
+    enabled: false
+  };
+
+  var Trigger = {
+    HOVER: 'hover',
+    FOCUS: 'focus',
+    CLICK: 'click',
+    MANUAL: 'manual'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tooltip = function () {
+    function Tooltip(element, config) {
+      _classCallCheck(this, Tooltip);
+
+      // private
+      this._isEnabled = true;
+      this._timeout = 0;
+      this._hoverState = '';
+      this._activeTrigger = {};
+      this._tether = null;
+
+      // protected
+      this.element = element;
+      this.config = this._getConfig(config);
+      this.tip = null;
+
+      this._setListeners();
+    }
+
+    // getters
+
+    // public
+
+    Tooltip.prototype.enable = function enable() {
+      this._isEnabled = true;
+    };
+
+    Tooltip.prototype.disable = function disable() {
+      this._isEnabled = false;
+    };
+
+    Tooltip.prototype.toggleEnabled = function toggleEnabled() {
+      this._isEnabled = !this._isEnabled;
+    };
+
+    Tooltip.prototype.toggle = function toggle(event) {
+      if (event) {
+        var dataKey = this.constructor.DATA_KEY;
+        var context = $(event.currentTarget).data(dataKey);
+
+        if (!context) {
+          context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+          $(event.currentTarget).data(dataKey, context);
+        }
+
+        context._activeTrigger.click = !context._activeTrigger.click;
+
+        if (context._isWithActiveTrigger()) {
+          context._enter(null, context);
+        } else {
+          context._leave(null, context);
+        }
+      } else {
+
+        if ($(this.getTipElement()).hasClass(ClassName.IN)) {
+          this._leave(null, this);
+          return;
+        }
+
+        this._enter(null, this);
+      }
+    };
+
+    Tooltip.prototype.dispose = function dispose() {
+      clearTimeout(this._timeout);
+
+      this.cleanupTether();
+
+      $.removeData(this.element, this.constructor.DATA_KEY);
+
+      $(this.element).off(this.constructor.EVENT_KEY);
+
+      if (this.tip) {
+        $(this.tip).remove();
+      }
+
+      this._isEnabled = null;
+      this._timeout = null;
+      this._hoverState = null;
+      this._activeTrigger = null;
+      this._tether = null;
+
+      this.element = null;
+      this.config = null;
+      this.tip = null;
+    };
+
+    Tooltip.prototype.show = function show() {
+      var _this16 = this;
+
+      var showEvent = $.Event(this.constructor.Event.SHOW);
+
+      if (this.isWithContent() && this._isEnabled) {
+        $(this.element).trigger(showEvent);
+
+        var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
+
+        if (showEvent.isDefaultPrevented() || !isInTheDom) {
+          return;
+        }
+
+        var tip = this.getTipElement();
+        var tipId = Util.getUID(this.constructor.NAME);
+
+        tip.setAttribute('id', tipId);
+        this.element.setAttribute('aria-describedby', tipId);
+
+        this.setContent();
+
+        if (this.config.animation) {
+          $(tip).addClass(ClassName.FADE);
+        }
+
+        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
+
+        var attachment = this._getAttachment(placement);
+
+        $(tip).data(this.constructor.DATA_KEY, this).appendTo(document.body);
+
+        $(this.element).trigger(this.constructor.Event.INSERTED);
+
+        this._tether = new Tether({
+          attachment: attachment,
+          element: tip,
+          target: this.element,
+          classes: TetherClass,
+          classPrefix: CLASS_PREFIX,
+          offset: this.config.offset,
+          constraints: this.config.constraints,
+          addTargetClasses: false
+        });
+
+        Util.reflow(tip);
+        this._tether.position();
+
+        $(tip).addClass(ClassName.IN);
+
+        var complete = function complete() {
+          var prevHoverState = _this16._hoverState;
+          _this16._hoverState = null;
+
+          $(_this16.element).trigger(_this16.constructor.Event.SHOWN);
+
+          if (prevHoverState === HoverState.OUT) {
+            _this16._leave(null, _this16);
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
+          return;
+        }
+
+        complete();
+      }
+    };
+
+    Tooltip.prototype.hide = function hide(callback) {
+      var _this17 = this;
+
+      var tip = this.getTipElement();
+      var hideEvent = $.Event(this.constructor.Event.HIDE);
+      var complete = function complete() {
+        if (_this17._hoverState !== HoverState.IN && tip.parentNode) {
+          tip.parentNode.removeChild(tip);
+        }
+
+        _this17.element.removeAttribute('aria-describedby');
+        $(_this17.element).trigger(_this17.constructor.Event.HIDDEN);
+        _this17.cleanupTether();
+
+        if (callback) {
+          callback();
+        }
+      };
+
+      $(this.element).trigger(hideEvent);
+
+      if (hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      $(tip).removeClass(ClassName.IN);
+
+      if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+
+        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      this._hoverState = '';
+    };
+
+    // protected
+
+    Tooltip.prototype.isWithContent = function isWithContent() {
+      return Boolean(this.getTitle());
+    };
+
+    Tooltip.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Tooltip.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    Tooltip.prototype.setElementContent = function setElementContent($element, content) {
+      var html = this.config.html;
+      if ((typeof content === 'undefined' ? 'undefined' : _typeof(content)) === 'object' && (content.nodeType || content.jquery)) {
+        // content is a DOM node or a jQuery
+        if (html) {
+          if (!$(content).parent().is($element)) {
+            $element.empty().append(content);
+          }
+        } else {
+          $element.text($(content).text());
+        }
+      } else {
+        $element[html ? 'html' : 'text'](content);
+      }
+    };
+
+    Tooltip.prototype.getTitle = function getTitle() {
+      var title = this.element.getAttribute('data-original-title');
+
+      if (!title) {
+        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
+      }
+
+      return title;
+    };
+
+    Tooltip.prototype.cleanupTether = function cleanupTether() {
+      if (this._tether) {
+        this._tether.destroy();
+      }
+    };
+
+    // private
+
+    Tooltip.prototype._getAttachment = function _getAttachment(placement) {
+      return AttachmentMap[placement.toUpperCase()];
+    };
+
+    Tooltip.prototype._setListeners = function _setListeners() {
+      var _this18 = this;
+
+      var triggers = this.config.trigger.split(' ');
+
+      triggers.forEach(function (trigger) {
+        if (trigger === 'click') {
+          $(_this18.element).on(_this18.constructor.Event.CLICK, _this18.config.selector, $.proxy(_this18.toggle, _this18));
+        } else if (trigger !== Trigger.MANUAL) {
+          var eventIn = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSEENTER : _this18.constructor.Event.FOCUSIN;
+          var eventOut = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSELEAVE : _this18.constructor.Event.FOCUSOUT;
+
+          $(_this18.element).on(eventIn, _this18.config.selector, $.proxy(_this18._enter, _this18)).on(eventOut, _this18.config.selector, $.proxy(_this18._leave, _this18));
+        }
+      });
+
+      if (this.config.selector) {
+        this.config = $.extend({}, this.config, {
+          trigger: 'manual',
+          selector: ''
+        });
+      } else {
+        this._fixTitle();
+      }
+    };
+
+    Tooltip.prototype._fixTitle = function _fixTitle() {
+      var titleType = _typeof(this.element.getAttribute('data-original-title'));
+      if (this.element.getAttribute('title') || titleType !== 'string') {
+        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
+        this.element.setAttribute('title', '');
+      }
+    };
+
+    Tooltip.prototype._enter = function _enter(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
+      }
+
+      if ($(context.getTipElement()).hasClass(ClassName.IN) || context._hoverState === HoverState.IN) {
+        context._hoverState = HoverState.IN;
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.IN;
+
+      if (!context.config.delay || !context.config.delay.show) {
+        context.show();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.IN) {
+          context.show();
+        }
+      }, context.config.delay.show);
+    };
+
+    Tooltip.prototype._leave = function _leave(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
+      }
+
+      if (context._isWithActiveTrigger()) {
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.OUT;
+
+      if (!context.config.delay || !context.config.delay.hide) {
+        context.hide();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.OUT) {
+          context.hide();
+        }
+      }, context.config.delay.hide);
+    };
+
+    Tooltip.prototype._isWithActiveTrigger = function _isWithActiveTrigger() {
+      for (var trigger in this._activeTrigger) {
+        if (this._activeTrigger[trigger]) {
+          return true;
+        }
+      }
+
+      return false;
+    };
+
+    Tooltip.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, this.constructor.Default, $(this.element).data(), config);
+
+      if (config.delay && typeof config.delay === 'number') {
+        config.delay = {
+          show: config.delay,
+          hide: config.delay
+        };
+      }
+
+      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
+
+      return config;
+    };
+
+    Tooltip.prototype._getDelegateConfig = function _getDelegateConfig() {
+      var config = {};
+
+      if (this.config) {
+        for (var key in this.config) {
+          if (this.constructor.Default[key] !== this.config[key]) {
+            config[key] = this.config[key];
+          }
+        }
+      }
+
+      return config;
+    };
+
+    // static
+
+    Tooltip._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /dispose|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Tooltip(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tooltip, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Tooltip;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tooltip._jQueryInterface;
+  $.fn[NAME].Constructor = Tooltip;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tooltip._jQueryInterface;
+  };
+
+  return Tooltip;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Popover = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'popover';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.popover';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = $.extend({}, Tooltip.Default, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip">' + '<h3 class="popover-title"></h3>' + '<div class="popover-content"></div></div>'
+  });
+
+  var DefaultType = $.extend({}, Tooltip.DefaultType, {
+    content: '(string|element|function)'
+  });
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TITLE: '.popover-title',
+    CONTENT: '.popover-content'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Popover = function (_Tooltip) {
+    _inherits(Popover, _Tooltip);
+
+    function Popover() {
+      _classCallCheck(this, Popover);
+
+      return _possibleConstructorReturn(this, _Tooltip.apply(this, arguments));
+    }
+
+    // overrides
+
+    Popover.prototype.isWithContent = function isWithContent() {
+      return this.getTitle() || this._getContent();
+    };
+
+    Popover.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Popover.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      // we use append for html objects to maintain js events
+      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
+      this.setElementContent($tip.find(Selector.CONTENT), this._getContent());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    // private
+
+    Popover.prototype._getContent = function _getContent() {
+      return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);
+    };
+
+    // static
+
+    Popover._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /destroy|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Popover(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Popover, null, [{
+      key: 'VERSION',
+
+
+      // getters
+
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Popover;
+  }(Tooltip);
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Popover._jQueryInterface;
+  $.fn[NAME].Constructor = Popover;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Popover._jQueryInterface;
+  };
+
+  return Popover;
+}(jQuery);
+
+}();
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
new file mode 100644
index 0000000..f8559b3
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/resources/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(jQuery),+function(){function a(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function b(a,b){ [...]
+DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},o=function(){function b(a){c(this,b),this._element=a}return b.prototype.show=function(){var b=this;if(!this._element.parentNode||this._element.parentNode.nodeType!==Node.ELEMENT_NODE||!a(this._element).hasClass(m.ACTIVE)){var c=void 0,d=void 0,e=a(this._element).closest(n.UL)[0],g=f.getSelectorFromElement(this._element);e&&(d=a.makeArray(a(e).find(n.ACTIVE)),d=d[d.length-1]);var h=a.Event(l.HIDE,{related [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/tobago-config.xml b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/tobago-config.xml
new file mode 100644
index 0000000..e8453ec
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/resources/META-INF/tobago-config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+    version="3.0">
+  <name>tobago-theme-richmond</name>
+  <ordering>
+    <after>
+      <name>tobago-theme-standard</name>
+    </after>
+  </ordering>
+  <theme-definitions>
+    <theme-definition>
+      <name>richmond</name>
+      <display-name>Richmond</display-name>
+      <fallback>standard</fallback>
+      <versioned>true</versioned>
+      <resources production="true">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+        </excludes>
+        <script name="/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+        <style name="/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+      </resources>
+      <resources production="false">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+        </excludes>
+        <script name="/tobago/richmond/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+        <style name="/tobago/richmond/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/scss/_custom.scss b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/scss/_custom.scss
new file mode 100644
index 0000000..d77097f
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/scss/_custom.scss
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Bootstrap overrides
+//
+// Copy variables from `_variables.scss` to this file to override default values
+// without modifying source files.
+
+$brand-primary:             #ffd080 !default;
+$brand-success:             #bcf8ac !default;
+$brand-info:                #00ffff !default;
+$brand-warning:             #f0fd4e !default;
+$brand-danger:              #ffa9a9 !default;
+
+$body-bg:    #eceeef !default;
+$body-color: #5facff !default;
+
+// todo: get this from the JAR
+@import "tobago";
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/scss/_tobago.scss b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/scss/_tobago.scss
new file mode 100644
index 0000000..b342151
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-richmond/src/main/scss/_tobago.scss
@@ -0,0 +1,918 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+
+/*
+ * theme: standard
+ * agent: standard
+ */
+
+/* box -------------------------------------------------------------- */
+
+.tobago-box-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+
+.tobago-flexLayout {
+    display: -webkit-flex; /* needed e.g. for Safari 8.0.2 */
+    display: -ms-flexbox; /* needed for IE 10 */
+    display: flex;
+    min-width: 0; /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+    flex-direction: column;
+    -webkit-flex-direction: column;
+    -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+    margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd{
+  justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween{
+  justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround{
+  justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  -moz-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+
+.tobago-gridLayout {
+    width: 100%;
+    height: 100%;
+/*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+    vertical-align: top;
+    padding: 0;
+    border-left: 5px solid transparent;
+    border-top: 5px solid transparent;
+    height: 100%; /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+    border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+    border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+
+.tobago-header {
+    margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+    margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+
+.tobago-image-markup-disabled {
+  filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  -webkit-border-radius: 6px 6px 6px 6px;
+  -moz-border-radius: 6px 6px 6px 6px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  -webkit-border-radius: 6px 0 6px 6px;
+  -moz-border-radius: 6px 0 6px 6px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+
+.tobago-selectManyShuttle {
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  flex: 1 0 0px;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: flex;
+  flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  flex: 1 0 0px;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: flex;
+  flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important; /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+.tobago-sheet-paging-markup-center {
+}
+
+.tobago-sheet-paging-markup-right {
+  float:right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important; /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+    padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+    background-color: #0097CF;
+    color: #FFFFFF;
+    cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+
+.tobago-tab {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}.form-horizontal .control-label {
+   margin-top: 10px;
+   margin-bottom: 5px;
+ }
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content:"*";
+  color:red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/pom.xml b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/pom.xml
new file mode 100644
index 0000000..0cb10e3
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-theme</artifactId>
+    <version>3.0.3-SNAPSHOT</version>
+  </parent>
+  <artifactId>tobago-theme-scarborough</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Theme Scarborough</name>
+
+  <properties>
+    <theme.name>scarborough</theme.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-standard</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..b1db76e
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,3 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.css b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.css
new file mode 100644
index 0000000..886c302
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.css
@@ -0,0 +1,7681 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+/*
+ * theme: standard
+ * agent: standard
+ */
+/* box -------------------------------------------------------------- */
+.tobago-box-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+.tobago-flexLayout {
+  display: -webkit-flex;
+  /* needed e.g. for Safari 8.0.2 */
+  display: -ms-flexbox;
+  /* needed for IE 10 */
+  display: -webkit-box;
+  display: flex;
+  min-width: 0;
+  /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+          flex-direction: column;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  -webkit-box-align: baseline;
+  -webkit-align-items: baseline;
+      -ms-flex-align: baseline;
+          align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  -webkit-box-align: end;
+  -webkit-align-items: flex-end;
+      -ms-flex-align: end;
+          align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  -webkit-box-align: start;
+  -webkit-align-items: flex-start;
+      -ms-flex-align: start;
+          align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  -webkit-box-align: stretch;
+  -webkit-align-items: stretch;
+      -ms-flex-align: stretch;
+          align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  -webkit-box-pack: start;
+  -webkit-justify-content: flex-start;
+      -ms-flex-pack: start;
+          justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd {
+  -webkit-box-pack: end;
+  -webkit-justify-content: flex-end;
+      -ms-flex-pack: end;
+          justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween {
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround {
+  -webkit-justify-content: space-around;
+      -ms-flex-pack: distribute;
+          justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+  box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+.tobago-gridLayout {
+  width: 100%;
+  height: 100%;
+  /*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+  vertical-align: top;
+  padding: 0;
+  border-left: 5px solid transparent;
+  border-top: 5px solid transparent;
+  height: 100%;
+  /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+  border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+  border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+.tobago-header {
+  margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+  margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+.tobago-image-markup-disabled {
+  -webkit-filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+          filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal;
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+.tobago-selectManyShuttle {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  -webkit-flex-shrink: 0;
+      -ms-flex-negative: 0;
+          flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important;
+  /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+
+.tobago-sheet-paging-markup-right {
+  float: right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 1 auto;
+      -ms-flex: 1 1 auto;
+          flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important;
+  /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+  padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+  background-color: #0097CF;
+  color: #FFFFFF;
+  cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+.tobago-tab {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}
+
+.form-horizontal .control-label {
+  margin-top: 10px;
+  margin-bottom: 5px;
+}
+
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content: "*";
+  color: red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
+
+/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */
+html {
+  font-family: sans-serif;
+  line-height: 1.15;
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+}
+
+body {
+  margin: 0;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+  display: block;
+}
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+}
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+progress {
+  vertical-align: baseline;
+}
+
+template,
+[hidden] {
+  display: none;
+}
+
+a {
+  background-color: transparent;
+  -webkit-text-decoration-skip: objects;
+}
+
+a:active,
+a:hover {
+  outline-width: 0;
+}
+
+abbr[title] {
+  border-bottom: none;
+  text-decoration: underline;
+  text-decoration: underline dotted;
+}
+
+b,
+strong {
+  font-weight: inherit;
+}
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+dfn {
+  font-style: italic;
+}
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+
+small {
+  font-size: 80%;
+}
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+img {
+  border-style: none;
+}
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+figure {
+  margin: 1em 40px;
+}
+
+hr {
+  -webkit-box-sizing: content-box;
+          box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font: inherit;
+  margin: 0;
+}
+
+optgroup {
+  font-weight: bold;
+}
+
+button,
+input {
+  overflow: visible;
+}
+
+button,
+select {
+  text-transform: none;
+}
+
+button,
+html [type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+legend {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  color: inherit;
+  display: table;
+  max-width: 100%;
+  padding: 0;
+  white-space: normal;
+}
+
+textarea {
+  overflow: auto;
+}
+
+[type="checkbox"],
+[type="radio"] {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+[type="search"] {
+  -webkit-appearance: textfield;
+  outline-offset: -2px;
+}
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54;
+}
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  font: inherit;
+}
+
+@media print {
+  *,
+  *::before,
+  *::after,
+  *::first-letter,
+  p::first-line,
+  div::first-line,
+  blockquote::first-line,
+  li::first-line {
+    text-shadow: none !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  abbr[title]::after {
+    content: " (" attr(title) ")";
+  }
+  pre {
+    white-space: pre-wrap !important;
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  .navbar {
+    display: none;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .tag {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+
+html {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+  -webkit-box-sizing: inherit;
+          box-sizing: inherit;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+html {
+  font-size: 16px;
+  -ms-overflow-style: scrollbar;
+  -webkit-tap-highlight-color: transparent;
+}
+
+body {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-size: 1rem;
+  line-height: 1.5;
+  color: #373a3c;
+  background-color: #bbccdd;
+}
+
+[tabindex="-1"]:focus {
+  outline: none !important;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 0;
+  margin-bottom: .5rem;
+}
+
+p {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #818a91;
+}
+
+address {
+  margin-bottom: 1rem;
+  font-style: normal;
+  line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+  margin-bottom: 0;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-bottom: .5rem;
+  margin-left: 0;
+}
+
+blockquote {
+  margin: 0 0 1rem;
+}
+
+a {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+a:focus, a:hover {
+  color: #014c8c;
+  text-decoration: underline;
+}
+
+a:focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+a:not([href]):not([tabindex]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus {
+  outline: none;
+}
+
+pre {
+  margin-top: 0;
+  margin-bottom: 1rem;
+  overflow: auto;
+}
+
+figure {
+  margin: 0 0 1rem;
+}
+
+img {
+  vertical-align: middle;
+}
+
+[role="button"] {
+  cursor: pointer;
+}
+
+a,
+area,
+button,
+[role="button"],
+input,
+label,
+select,
+summary,
+textarea {
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+}
+
+table {
+  border-collapse: collapse;
+  background-color: transparent;
+}
+
+caption {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  color: #818a91;
+  text-align: left;
+  caption-side: bottom;
+}
+
+th {
+  text-align: left;
+}
+
+label {
+  display: inline-block;
+  margin-bottom: .5rem;
+}
+
+button:focus {
+  outline: 1px dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+textarea {
+  line-height: inherit;
+}
+
+input[type="radio"]:disabled,
+input[type="checkbox"]:disabled {
+  cursor: not-allowed;
+}
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  -webkit-appearance: listbox;
+}
+
+textarea {
+  resize: vertical;
+}
+
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: .5rem;
+  font-size: 1.5rem;
+  line-height: inherit;
+}
+
+input[type="search"] {
+  -webkit-appearance: none;
+}
+
+output {
+  display: inline-block;
+}
+
+[hidden] {
+  display: none !important;
+}
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  margin-bottom: 0.5rem;
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+
+h1, .h1 {
+  font-size: 2.5rem;
+}
+
+h2, .h2 {
+  font-size: 2rem;
+}
+
+h3, .h3 {
+  font-size: 1.75rem;
+}
+
+h4, .h4 {
+  font-size: 1.5rem;
+}
+
+h5, .h5 {
+  font-size: 1.25rem;
+}
+
+h6, .h6 {
+  font-size: 1rem;
+}
+
+.lead {
+  font-size: 1.25rem;
+  font-weight: 300;
+}
+
+.display-1 {
+  font-size: 6rem;
+  font-weight: 300;
+}
+
+.display-2 {
+  font-size: 5.5rem;
+  font-weight: 300;
+}
+
+.display-3 {
+  font-size: 4.5rem;
+  font-weight: 300;
+}
+
+.display-4 {
+  font-size: 3.5rem;
+  font-weight: 300;
+}
+
+hr {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+small,
+.small {
+  font-size: 80%;
+  font-weight: normal;
+}
+
+mark,
+.mark {
+  padding: 0.2em;
+  background-color: #fcf8e3;
+}
+
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline-item {
+  display: inline-block;
+}
+
+.list-inline-item:not(:last-child) {
+  margin-right: 5px;
+}
+
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+.blockquote {
+  padding: 0.5rem 1rem;
+  margin-bottom: 1rem;
+  font-size: 1.25rem;
+  border-left: 0.25rem solid #eceeef;
+}
+
+.blockquote-footer {
+  display: block;
+  font-size: 80%;
+  color: #818a91;
+}
+
+.blockquote-footer::before {
+  content: "\2014 \00A0";
+}
+
+.blockquote-reverse {
+  padding-right: 1rem;
+  padding-left: 0;
+  text-align: right;
+  border-right: 0.25rem solid #eceeef;
+  border-left: 0;
+}
+
+.blockquote-reverse .blockquote-footer::before {
+  content: "";
+}
+
+.blockquote-reverse .blockquote-footer::after {
+  content: "\00A0 \2014";
+}
+
+dl.row > dd + dt {
+  clear: left;
+}
+
+.img-fluid, .carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  max-width: 100%;
+  height: auto;
+}
+
+.img-thumbnail {
+  padding: 0.25rem;
+  background-color: #bbccdd;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  -webkit-transition: all .2s ease-in-out;
+  -o-transition: all .2s ease-in-out;
+  transition: all .2s ease-in-out;
+  max-width: 100%;
+  height: auto;
+}
+
+.figure {
+  display: inline-block;
+}
+
+.figure-img {
+  margin-bottom: 0.5rem;
+  line-height: 1;
+}
+
+.figure-caption {
+  font-size: 90%;
+  color: #818a91;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+code {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #bd4147;
+  background-color: #f7f7f9;
+  border-radius: 0.25rem;
+}
+
+kbd {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 0.2rem;
+}
+
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: bold;
+}
+
+pre {
+  display: block;
+  margin-top: 0;
+  margin-bottom: 1rem;
+  font-size: 90%;
+  color: #373a3c;
+}
+
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  background-color: transparent;
+  border-radius: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+.container {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .container {
+    width: 540px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 768px) {
+  .container {
+    width: 720px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 992px) {
+  .container {
+    width: 960px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container {
+    width: 1140px;
+    max-width: 100%;
+  }
+}
+
+.container-fluid {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container-fluid::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.row::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+.col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg [...]
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+@media (min-width: 576px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+.col-xs-1 {
+  float: left;
+  width: 8.333333%;
+}
+
+.col-xs-2 {
+  float: left;
+  width: 16.666667%;
+}
+
+.col-xs-3 {
+  float: left;
+  width: 25%;
+}
+
+.col-xs-4 {
+  float: left;
+  width: 33.333333%;
+}
+
+.col-xs-5 {
+  float: left;
+  width: 41.666667%;
+}
+
+.col-xs-6 {
+  float: left;
+  width: 50%;
+}
+
+.col-xs-7 {
+  float: left;
+  width: 58.333333%;
+}
+
+.col-xs-8 {
+  float: left;
+  width: 66.666667%;
+}
+
+.col-xs-9 {
+  float: left;
+  width: 75%;
+}
+
+.col-xs-10 {
+  float: left;
+  width: 83.333333%;
+}
+
+.col-xs-11 {
+  float: left;
+  width: 91.666667%;
+}
+
+.col-xs-12 {
+  float: left;
+  width: 100%;
+}
+
+.pull-xs-0 {
+  right: auto;
+}
+
+.pull-xs-1 {
+  right: 8.333333%;
+}
+
+.pull-xs-2 {
+  right: 16.666667%;
+}
+
+.pull-xs-3 {
+  right: 25%;
+}
+
+.pull-xs-4 {
+  right: 33.333333%;
+}
+
+.pull-xs-5 {
+  right: 41.666667%;
+}
+
+.pull-xs-6 {
+  right: 50%;
+}
+
+.pull-xs-7 {
+  right: 58.333333%;
+}
+
+.pull-xs-8 {
+  right: 66.666667%;
+}
+
+.pull-xs-9 {
+  right: 75%;
+}
+
+.pull-xs-10 {
+  right: 83.333333%;
+}
+
+.pull-xs-11 {
+  right: 91.666667%;
+}
+
+.pull-xs-12 {
+  right: 100%;
+}
+
+.push-xs-0 {
+  left: auto;
+}
+
+.push-xs-1 {
+  left: 8.333333%;
+}
+
+.push-xs-2 {
+  left: 16.666667%;
+}
+
+.push-xs-3 {
+  left: 25%;
+}
+
+.push-xs-4 {
+  left: 33.333333%;
+}
+
+.push-xs-5 {
+  left: 41.666667%;
+}
+
+.push-xs-6 {
+  left: 50%;
+}
+
+.push-xs-7 {
+  left: 58.333333%;
+}
+
+.push-xs-8 {
+  left: 66.666667%;
+}
+
+.push-xs-9 {
+  left: 75%;
+}
+
+.push-xs-10 {
+  left: 83.333333%;
+}
+
+.push-xs-11 {
+  left: 91.666667%;
+}
+
+.push-xs-12 {
+  left: 100%;
+}
+
+.offset-xs-1 {
+  margin-left: 8.333333%;
+}
+
+.offset-xs-2 {
+  margin-left: 16.666667%;
+}
+
+.offset-xs-3 {
+  margin-left: 25%;
+}
+
+.offset-xs-4 {
+  margin-left: 33.333333%;
+}
+
+.offset-xs-5 {
+  margin-left: 41.666667%;
+}
+
+.offset-xs-6 {
+  margin-left: 50%;
+}
+
+.offset-xs-7 {
+  margin-left: 58.333333%;
+}
+
+.offset-xs-8 {
+  margin-left: 66.666667%;
+}
+
+.offset-xs-9 {
+  margin-left: 75%;
+}
+
+.offset-xs-10 {
+  margin-left: 83.333333%;
+}
+
+.offset-xs-11 {
+  margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+  .col-sm-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-sm-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-sm-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-sm-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-sm-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-sm-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-sm-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-sm-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-sm-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-sm-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-sm-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-sm-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-sm-0 {
+    right: auto;
+  }
+  .pull-sm-1 {
+    right: 8.333333%;
+  }
+  .pull-sm-2 {
+    right: 16.666667%;
+  }
+  .pull-sm-3 {
+    right: 25%;
+  }
+  .pull-sm-4 {
+    right: 33.333333%;
+  }
+  .pull-sm-5 {
+    right: 41.666667%;
+  }
+  .pull-sm-6 {
+    right: 50%;
+  }
+  .pull-sm-7 {
+    right: 58.333333%;
+  }
+  .pull-sm-8 {
+    right: 66.666667%;
+  }
+  .pull-sm-9 {
+    right: 75%;
+  }
+  .pull-sm-10 {
+    right: 83.333333%;
+  }
+  .pull-sm-11 {
+    right: 91.666667%;
+  }
+  .pull-sm-12 {
+    right: 100%;
+  }
+  .push-sm-0 {
+    left: auto;
+  }
+  .push-sm-1 {
+    left: 8.333333%;
+  }
+  .push-sm-2 {
+    left: 16.666667%;
+  }
+  .push-sm-3 {
+    left: 25%;
+  }
+  .push-sm-4 {
+    left: 33.333333%;
+  }
+  .push-sm-5 {
+    left: 41.666667%;
+  }
+  .push-sm-6 {
+    left: 50%;
+  }
+  .push-sm-7 {
+    left: 58.333333%;
+  }
+  .push-sm-8 {
+    left: 66.666667%;
+  }
+  .push-sm-9 {
+    left: 75%;
+  }
+  .push-sm-10 {
+    left: 83.333333%;
+  }
+  .push-sm-11 {
+    left: 91.666667%;
+  }
+  .push-sm-12 {
+    left: 100%;
+  }
+  .offset-sm-0 {
+    margin-left: 0%;
+  }
+  .offset-sm-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-sm-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-sm-3 {
+    margin-left: 25%;
+  }
+  .offset-sm-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-sm-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-sm-6 {
+    margin-left: 50%;
+  }
+  .offset-sm-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-sm-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-sm-9 {
+    margin-left: 75%;
+  }
+  .offset-sm-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-sm-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-md-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-md-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-md-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-md-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-md-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-md-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-md-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-md-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-md-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-md-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-md-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-md-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-md-0 {
+    right: auto;
+  }
+  .pull-md-1 {
+    right: 8.333333%;
+  }
+  .pull-md-2 {
+    right: 16.666667%;
+  }
+  .pull-md-3 {
+    right: 25%;
+  }
+  .pull-md-4 {
+    right: 33.333333%;
+  }
+  .pull-md-5 {
+    right: 41.666667%;
+  }
+  .pull-md-6 {
+    right: 50%;
+  }
+  .pull-md-7 {
+    right: 58.333333%;
+  }
+  .pull-md-8 {
+    right: 66.666667%;
+  }
+  .pull-md-9 {
+    right: 75%;
+  }
+  .pull-md-10 {
+    right: 83.333333%;
+  }
+  .pull-md-11 {
+    right: 91.666667%;
+  }
+  .pull-md-12 {
+    right: 100%;
+  }
+  .push-md-0 {
+    left: auto;
+  }
+  .push-md-1 {
+    left: 8.333333%;
+  }
+  .push-md-2 {
+    left: 16.666667%;
+  }
+  .push-md-3 {
+    left: 25%;
+  }
+  .push-md-4 {
+    left: 33.333333%;
+  }
+  .push-md-5 {
+    left: 41.666667%;
+  }
+  .push-md-6 {
+    left: 50%;
+  }
+  .push-md-7 {
+    left: 58.333333%;
+  }
+  .push-md-8 {
+    left: 66.666667%;
+  }
+  .push-md-9 {
+    left: 75%;
+  }
+  .push-md-10 {
+    left: 83.333333%;
+  }
+  .push-md-11 {
+    left: 91.666667%;
+  }
+  .push-md-12 {
+    left: 100%;
+  }
+  .offset-md-0 {
+    margin-left: 0%;
+  }
+  .offset-md-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-md-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-md-3 {
+    margin-left: 25%;
+  }
+  .offset-md-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-md-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-md-6 {
+    margin-left: 50%;
+  }
+  .offset-md-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-md-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-md-9 {
+    margin-left: 75%;
+  }
+  .offset-md-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-md-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-lg-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-lg-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-lg-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-lg-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-lg-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-lg-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-lg-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-lg-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-lg-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-lg-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-lg-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-lg-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-lg-0 {
+    right: auto;
+  }
+  .pull-lg-1 {
+    right: 8.333333%;
+  }
+  .pull-lg-2 {
+    right: 16.666667%;
+  }
+  .pull-lg-3 {
+    right: 25%;
+  }
+  .pull-lg-4 {
+    right: 33.333333%;
+  }
+  .pull-lg-5 {
+    right: 41.666667%;
+  }
+  .pull-lg-6 {
+    right: 50%;
+  }
+  .pull-lg-7 {
+    right: 58.333333%;
+  }
+  .pull-lg-8 {
+    right: 66.666667%;
+  }
+  .pull-lg-9 {
+    right: 75%;
+  }
+  .pull-lg-10 {
+    right: 83.333333%;
+  }
+  .pull-lg-11 {
+    right: 91.666667%;
+  }
+  .pull-lg-12 {
+    right: 100%;
+  }
+  .push-lg-0 {
+    left: auto;
+  }
+  .push-lg-1 {
+    left: 8.333333%;
+  }
+  .push-lg-2 {
+    left: 16.666667%;
+  }
+  .push-lg-3 {
+    left: 25%;
+  }
+  .push-lg-4 {
+    left: 33.333333%;
+  }
+  .push-lg-5 {
+    left: 41.666667%;
+  }
+  .push-lg-6 {
+    left: 50%;
+  }
+  .push-lg-7 {
+    left: 58.333333%;
+  }
+  .push-lg-8 {
+    left: 66.666667%;
+  }
+  .push-lg-9 {
+    left: 75%;
+  }
+  .push-lg-10 {
+    left: 83.333333%;
+  }
+  .push-lg-11 {
+    left: 91.666667%;
+  }
+  .push-lg-12 {
+    left: 100%;
+  }
+  .offset-lg-0 {
+    margin-left: 0%;
+  }
+  .offset-lg-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-lg-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-lg-3 {
+    margin-left: 25%;
+  }
+  .offset-lg-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-lg-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-lg-6 {
+    margin-left: 50%;
+  }
+  .offset-lg-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-lg-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-lg-9 {
+    margin-left: 75%;
+  }
+  .offset-lg-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-lg-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xl-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-xl-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-xl-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-xl-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-xl-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-xl-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-xl-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-xl-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-xl-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-xl-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-xl-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-xl-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-xl-0 {
+    right: auto;
+  }
+  .pull-xl-1 {
+    right: 8.333333%;
+  }
+  .pull-xl-2 {
+    right: 16.666667%;
+  }
+  .pull-xl-3 {
+    right: 25%;
+  }
+  .pull-xl-4 {
+    right: 33.333333%;
+  }
+  .pull-xl-5 {
+    right: 41.666667%;
+  }
+  .pull-xl-6 {
+    right: 50%;
+  }
+  .pull-xl-7 {
+    right: 58.333333%;
+  }
+  .pull-xl-8 {
+    right: 66.666667%;
+  }
+  .pull-xl-9 {
+    right: 75%;
+  }
+  .pull-xl-10 {
+    right: 83.333333%;
+  }
+  .pull-xl-11 {
+    right: 91.666667%;
+  }
+  .pull-xl-12 {
+    right: 100%;
+  }
+  .push-xl-0 {
+    left: auto;
+  }
+  .push-xl-1 {
+    left: 8.333333%;
+  }
+  .push-xl-2 {
+    left: 16.666667%;
+  }
+  .push-xl-3 {
+    left: 25%;
+  }
+  .push-xl-4 {
+    left: 33.333333%;
+  }
+  .push-xl-5 {
+    left: 41.666667%;
+  }
+  .push-xl-6 {
+    left: 50%;
+  }
+  .push-xl-7 {
+    left: 58.333333%;
+  }
+  .push-xl-8 {
+    left: 66.666667%;
+  }
+  .push-xl-9 {
+    left: 75%;
+  }
+  .push-xl-10 {
+    left: 83.333333%;
+  }
+  .push-xl-11 {
+    left: 91.666667%;
+  }
+  .push-xl-12 {
+    left: 100%;
+  }
+  .offset-xl-0 {
+    margin-left: 0%;
+  }
+  .offset-xl-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-xl-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-xl-3 {
+    margin-left: 25%;
+  }
+  .offset-xl-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-xl-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-xl-6 {
+    margin-left: 50%;
+  }
+  .offset-xl-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-xl-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-xl-9 {
+    margin-left: 75%;
+  }
+  .offset-xl-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-xl-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 1rem;
+}
+
+.table th,
+.table td {
+  padding: 0.75rem;
+  vertical-align: top;
+  border-top: 1px solid #eceeef;
+}
+
+.table thead th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #eceeef;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #eceeef;
+}
+
+.table .table {
+  background-color: #bbccdd;
+}
+
+.table-sm th,
+.table-sm td {
+  padding: 0.3rem;
+}
+
+.table-bordered {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered thead th,
+.table-bordered thead td {
+  border-bottom-width: 2px;
+}
+
+.table-striped tbody tr:nth-of-type(odd) {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+
+.table-hover tbody tr:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-active,
+.table-active > th,
+.table-active > td {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover > td,
+.table-hover .table-active:hover > th {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-success,
+.table-success > th,
+.table-success > td {
+  background-color: #dff0d8;
+}
+
+.table-hover .table-success:hover {
+  background-color: #d0e9c6;
+}
+
+.table-hover .table-success:hover > td,
+.table-hover .table-success:hover > th {
+  background-color: #d0e9c6;
+}
+
+.table-info,
+.table-info > th,
+.table-info > td {
+  background-color: #d9edf7;
+}
+
+.table-hover .table-info:hover {
+  background-color: #c4e3f3;
+}
+
+.table-hover .table-info:hover > td,
+.table-hover .table-info:hover > th {
+  background-color: #c4e3f3;
+}
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+  background-color: #fcf8e3;
+}
+
+.table-hover .table-warning:hover {
+  background-color: #faf2cc;
+}
+
+.table-hover .table-warning:hover > td,
+.table-hover .table-warning:hover > th {
+  background-color: #faf2cc;
+}
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+  background-color: #f2dede;
+}
+
+.table-hover .table-danger:hover {
+  background-color: #ebcccc;
+}
+
+.table-hover .table-danger:hover > td,
+.table-hover .table-danger:hover > th {
+  background-color: #ebcccc;
+}
+
+.thead-inverse th {
+  color: #fff;
+  background-color: #373a3c;
+}
+
+.thead-default th {
+  color: #55595c;
+  background-color: #eceeef;
+}
+
+.table-inverse {
+  color: #eceeef;
+  background-color: #373a3c;
+}
+
+.table-inverse th,
+.table-inverse td,
+.table-inverse thead th {
+  border-color: #55595c;
+}
+
+.table-inverse.table-bordered {
+  border: 0;
+}
+
+.table-responsive {
+  display: block;
+  width: 100%;
+  min-height: 0%;
+  overflow-x: auto;
+}
+
+.table-reflow thead {
+  float: left;
+}
+
+.table-reflow tbody {
+  display: block;
+  white-space: nowrap;
+}
+
+.table-reflow th,
+.table-reflow td {
+  border-top: 1px solid #eceeef;
+  border-left: 1px solid #eceeef;
+}
+
+.table-reflow th:last-child,
+.table-reflow td:last-child {
+  border-right: 1px solid #eceeef;
+}
+
+.table-reflow thead:last-child tr:last-child th,
+.table-reflow thead:last-child tr:last-child td,
+.table-reflow tbody:last-child tr:last-child th,
+.table-reflow tbody:last-child tr:last-child td,
+.table-reflow tfoot:last-child tr:last-child th,
+.table-reflow tfoot:last-child tr:last-child td {
+  border-bottom: 1px solid #eceeef;
+}
+
+.table-reflow tr {
+  float: left;
+}
+
+.table-reflow tr th,
+.table-reflow tr td {
+  display: block !important;
+  border: 1px solid #eceeef;
+}
+
+.form-control {
+  display: block;
+  width: 100%;
+  padding: 0.5rem 0.75rem;
+  font-size: 1rem;
+  line-height: 1.25;
+  color: #55595c;
+  background-color: #fff;
+  background-image: none;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.form-control::-ms-expand {
+  background-color: transparent;
+  border: 0;
+}
+
+.form-control:focus {
+  color: #55595c;
+  background-color: #fff;
+  border-color: #66afe9;
+  outline: none;
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::-moz-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:disabled, .form-control[readonly] {
+  background-color: #eceeef;
+  opacity: 1;
+}
+
+.form-control:disabled {
+  cursor: not-allowed;
+}
+
+select.form-control:not([size]):not([multiple]) {
+  height: calc(2.5rem - 2px);
+}
+
+select.form-control:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.form-control-file,
+.form-control-range {
+  display: block;
+}
+
+.col-form-label {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+}
+
+.col-form-label-lg {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  font-size: 1.25rem;
+}
+
+.col-form-label-sm {
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  font-size: 0.875rem;
+}
+
+.col-form-legend {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+}
+
+.form-control-static {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  line-height: 1.25;
+  border: solid transparent;
+  border-width: 1px 0;
+}
+
+.form-control-static.form-control-sm, .input-group-sm > .form-control-static.form-control,
+.input-group-sm > .form-control-static.input-group-addon,
+.input-group-sm > .input-group-btn > .form-control-static.btn, .form-control-static.form-control-lg, .input-group-lg > .form-control-static.form-control,
+.input-group-lg > .form-control-static.input-group-addon,
+.input-group-lg > .input-group-btn > .form-control-static.btn {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.form-control-sm, .input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),
+.input-group-sm > select.input-group-addon:not([size]):not([multiple]),
+.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 1.8125rem;
+}
+
+.form-control-lg, .input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),
+.input-group-lg > select.input-group-addon:not([size]):not([multiple]),
+.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 3.166667rem;
+}
+
+.form-group {
+  margin-bottom: 1rem;
+}
+
+.form-text {
+  display: block;
+  margin-top: 0.25rem;
+}
+
+.form-check {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+}
+
+.form-check + .form-check {
+  margin-top: -.25rem;
+}
+
+.form-check.disabled .form-check-label {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-check-label {
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  cursor: pointer;
+}
+
+.form-check-input {
+  position: absolute;
+  margin-top: .25rem;
+  margin-left: -1.25rem;
+}
+
+.form-check-input:only-child {
+  position: static;
+}
+
+.form-check-inline {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  vertical-align: middle;
+  cursor: pointer;
+}
+
+.form-check-inline + .form-check-inline {
+  margin-left: .75rem;
+}
+
+.form-check-inline.disabled {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-control-feedback {
+  margin-top: 0.25rem;
+}
+
+.form-control-success,
+.form-control-warning,
+.form-control-danger {
+  padding-right: 2.25rem;
+  background-repeat: no-repeat;
+  background-position: center right 0.625rem;
+  -webkit-background-size: 1.25rem 1.25rem;
+          background-size: 1.25rem 1.25rem;
+}
+
+.has-success .form-control-feedback,
+.has-success .form-control-label,
+.has-success .form-check-label,
+.has-success .form-check-inline,
+.has-success .custom-control {
+  color: #5cb85c;
+}
+
+.has-success .form-control {
+  border-color: #5cb85c;
+}
+
+.has-success .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+}
+
+.has-success .input-group-addon {
+  color: #5cb85c;
+  border-color: #5cb85c;
+  background-color: #eaf6ea;
+}
+
+.has-success .form-control-success {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#5cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");
+}
+
+.has-warning .form-control-feedback,
+.has-warning .form-control-label,
+.has-warning .form-check-label,
+.has-warning .form-check-inline,
+.has-warning .custom-control {
+  color: #f0ad4e;
+}
+
+.has-warning .form-control {
+  border-color: #f0ad4e;
+}
+
+.has-warning .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+}
+
+.has-warning .input-group-addon {
+  color: #f0ad4e;
+  border-color: #f0ad4e;
+  background-color: white;
+}
+
+.has-warning .form-control-warning {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E");
+}
+
+.has-danger .form-control-feedback,
+.has-danger .form-control-label,
+.has-danger .form-check-label,
+.has-danger .form-check-inline,
+.has-danger .custom-control {
+  color: #d9534f;
+}
+
+.has-danger .form-control {
+  border-color: #d9534f;
+}
+
+.has-danger .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+}
+
+.has-danger .input-group-addon {
+  color: #d9534f;
+  border-color: #d9534f;
+  background-color: #fdf7f7;
+}
+
+.has-danger .form-control-danger {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E");
+}
+
+@media (min-width: 576px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-static {
+    display: inline-block;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .form-control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check-label {
+    padding-left: 0;
+  }
+  .form-inline .form-check-input {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+
+.btn {
+  display: inline-block;
+  font-weight: normal;
+  line-height: 1.25;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  border: 1px solid transparent;
+  padding: 0.5rem 1rem;
+  font-size: 1rem;
+  border-radius: 0.25rem;
+}
+
+.btn:focus, .btn.focus, .btn:active:focus, .btn:active.focus, .btn.active:focus, .btn.active.focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn:focus, .btn:hover {
+  text-decoration: none;
+}
+
+.btn.focus {
+  text-decoration: none;
+}
+
+.btn:active, .btn.active {
+  background-image: none;
+  outline: 0;
+}
+
+.btn.disabled, .btn:disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+a.btn.disabled,
+fieldset[disabled] a.btn {
+  pointer-events: none;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary:hover {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:focus, .btn-primary.focus {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:active, .btn-primary.active,
+.open > .btn-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+  background-image: none;
+}
+
+.btn-primary:active:hover, .btn-primary:active:focus, .btn-primary:active.focus, .btn-primary.active:hover, .btn-primary.active:focus, .btn-primary.active.focus,
+.open > .btn-primary.dropdown-toggle:hover,
+.open > .btn-primary.dropdown-toggle:focus,
+.open > .btn-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary:disabled:focus, .btn-primary:disabled.focus {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary.disabled:hover, .btn-primary:disabled:hover {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-secondary {
+  color: #373a3c;
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary:hover {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:focus, .btn-secondary.focus {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:active, .btn-secondary.active,
+.open > .btn-secondary.dropdown-toggle {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+  background-image: none;
+}
+
+.btn-secondary:active:hover, .btn-secondary:active:focus, .btn-secondary:active.focus, .btn-secondary.active:hover, .btn-secondary.active:focus, .btn-secondary.active.focus,
+.open > .btn-secondary.dropdown-toggle:hover,
+.open > .btn-secondary.dropdown-toggle:focus,
+.open > .btn-secondary.dropdown-toggle.focus {
+  color: #373a3c;
+  background-color: #d4d4d4;
+  border-color: #8c8c8c;
+}
+
+.btn-secondary.disabled:focus, .btn-secondary.disabled.focus, .btn-secondary:disabled:focus, .btn-secondary:disabled.focus {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary.disabled:hover, .btn-secondary:disabled:hover {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-info {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info:hover {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:focus, .btn-info.focus {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:active, .btn-info.active,
+.open > .btn-info.dropdown-toggle {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+  background-image: none;
+}
+
+.btn-info:active:hover, .btn-info:active:focus, .btn-info:active.focus, .btn-info.active:hover, .btn-info.active:focus, .btn-info.active.focus,
+.open > .btn-info.dropdown-toggle:hover,
+.open > .btn-info.dropdown-toggle:focus,
+.open > .btn-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info:disabled:focus, .btn-info:disabled.focus {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info.disabled:hover, .btn-info:disabled:hover {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-success {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success:hover {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:focus, .btn-success.focus {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:active, .btn-success.active,
+.open > .btn-success.dropdown-toggle {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+  background-image: none;
+}
+
+.btn-success:active:hover, .btn-success:active:focus, .btn-success:active.focus, .btn-success.active:hover, .btn-success.active:focus, .btn-success.active.focus,
+.open > .btn-success.dropdown-toggle:hover,
+.open > .btn-success.dropdown-toggle:focus,
+.open > .btn-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success:disabled:focus, .btn-success:disabled.focus {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success.disabled:hover, .btn-success:disabled:hover {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-warning {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning:hover {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:focus, .btn-warning.focus {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:active, .btn-warning.active,
+.open > .btn-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+  background-image: none;
+}
+
+.btn-warning:active:hover, .btn-warning:active:focus, .btn-warning:active.focus, .btn-warning.active:hover, .btn-warning.active:focus, .btn-warning.active.focus,
+.open > .btn-warning.dropdown-toggle:hover,
+.open > .btn-warning.dropdown-toggle:focus,
+.open > .btn-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning:disabled:focus, .btn-warning:disabled.focus {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning.disabled:hover, .btn-warning:disabled:hover {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-danger {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger:hover {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:focus, .btn-danger.focus {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:active, .btn-danger.active,
+.open > .btn-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+  background-image: none;
+}
+
+.btn-danger:active:hover, .btn-danger:active:focus, .btn-danger:active.focus, .btn-danger.active:hover, .btn-danger.active:focus, .btn-danger.active.focus,
+.open > .btn-danger.dropdown-toggle:hover,
+.open > .btn-danger.dropdown-toggle:focus,
+.open > .btn-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger:disabled:focus, .btn-danger:disabled.focus {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger.disabled:hover, .btn-danger:disabled:hover {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-primary {
+  color: #0275d8;
+  background-image: none;
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:hover {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:focus, .btn-outline-primary.focus {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active, .btn-outline-primary.active,
+.open > .btn-outline-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active:hover, .btn-outline-primary:active:focus, .btn-outline-primary:active.focus, .btn-outline-primary.active:hover, .btn-outline-primary.active:focus, .btn-outline-primary.active.focus,
+.open > .btn-outline-primary.dropdown-toggle:hover,
+.open > .btn-outline-primary.dropdown-toggle:focus,
+.open > .btn-outline-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-outline-primary.disabled:focus, .btn-outline-primary.disabled.focus, .btn-outline-primary:disabled:focus, .btn-outline-primary:disabled.focus {
+  border-color: #43a7fd;
+}
+
+.btn-outline-primary.disabled:hover, .btn-outline-primary:disabled:hover {
+  border-color: #43a7fd;
+}
+
+.btn-outline-secondary {
+  color: #ccc;
+  background-image: none;
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:hover {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:focus, .btn-outline-secondary.focus {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active, .btn-outline-secondary.active,
+.open > .btn-outline-secondary.dropdown-toggle {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active:hover, .btn-outline-secondary:active:focus, .btn-outline-secondary:active.focus, .btn-outline-secondary.active:hover, .btn-outline-secondary.active:focus, .btn-outline-secondary.active.focus,
+.open > .btn-outline-secondary.dropdown-toggle:hover,
+.open > .btn-outline-secondary.dropdown-toggle:focus,
+.open > .btn-outline-secondary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #a1a1a1;
+  border-color: #8c8c8c;
+}
+
+.btn-outline-secondary.disabled:focus, .btn-outline-secondary.disabled.focus, .btn-outline-secondary:disabled:focus, .btn-outline-secondary:disabled.focus {
+  border-color: white;
+}
+
+.btn-outline-secondary.disabled:hover, .btn-outline-secondary:disabled:hover {
+  border-color: white;
+}
+
+.btn-outline-info {
+  color: #5bc0de;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:hover {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:focus, .btn-outline-info.focus {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active, .btn-outline-info.active,
+.open > .btn-outline-info.dropdown-toggle {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active:hover, .btn-outline-info:active:focus, .btn-outline-info:active.focus, .btn-outline-info.active:hover, .btn-outline-info.active:focus, .btn-outline-info.active.focus,
+.open > .btn-outline-info.dropdown-toggle:hover,
+.open > .btn-outline-info.dropdown-toggle:focus,
+.open > .btn-outline-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-outline-info.disabled:focus, .btn-outline-info.disabled.focus, .btn-outline-info:disabled:focus, .btn-outline-info:disabled.focus {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-info.disabled:hover, .btn-outline-info:disabled:hover {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-success {
+  color: #5cb85c;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:hover {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:focus, .btn-outline-success.focus {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active, .btn-outline-success.active,
+.open > .btn-outline-success.dropdown-toggle {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active:hover, .btn-outline-success:active:focus, .btn-outline-success:active.focus, .btn-outline-success.active:hover, .btn-outline-success.active:focus, .btn-outline-success.active.focus,
+.open > .btn-outline-success.dropdown-toggle:hover,
+.open > .btn-outline-success.dropdown-toggle:focus,
+.open > .btn-outline-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-outline-success.disabled:focus, .btn-outline-success.disabled.focus, .btn-outline-success:disabled:focus, .btn-outline-success:disabled.focus {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-success.disabled:hover, .btn-outline-success:disabled:hover {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-warning {
+  color: #f0ad4e;
+  background-image: none;
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:hover {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:focus, .btn-outline-warning.focus {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active, .btn-outline-warning.active,
+.open > .btn-outline-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active:hover, .btn-outline-warning:active:focus, .btn-outline-warning:active.focus, .btn-outline-warning.active:hover, .btn-outline-warning.active:focus, .btn-outline-warning.active.focus,
+.open > .btn-outline-warning.dropdown-toggle:hover,
+.open > .btn-outline-warning.dropdown-toggle:focus,
+.open > .btn-outline-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-outline-warning.disabled:focus, .btn-outline-warning.disabled.focus, .btn-outline-warning:disabled:focus, .btn-outline-warning:disabled.focus {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-warning.disabled:hover, .btn-outline-warning:disabled:hover {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-danger {
+  color: #d9534f;
+  background-image: none;
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:hover {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:focus, .btn-outline-danger.focus {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active, .btn-outline-danger.active,
+.open > .btn-outline-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active:hover, .btn-outline-danger:active:focus, .btn-outline-danger:active.focus, .btn-outline-danger.active:hover, .btn-outline-danger.active:focus, .btn-outline-danger.active.focus,
+.open > .btn-outline-danger.dropdown-toggle:hover,
+.open > .btn-outline-danger.dropdown-toggle:focus,
+.open > .btn-outline-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-outline-danger.disabled:focus, .btn-outline-danger.disabled.focus, .btn-outline-danger:disabled:focus, .btn-outline-danger:disabled.focus {
+  border-color: #eba5a3;
+}
+
+.btn-outline-danger.disabled:hover, .btn-outline-danger:disabled:hover {
+  border-color: #eba5a3;
+}
+
+.btn-link {
+  font-weight: normal;
+  color: #0275d8;
+  border-radius: 0;
+}
+
+.btn-link, .btn-link:active, .btn-link.active, .btn-link:disabled {
+  background-color: transparent;
+}
+
+.btn-link, .btn-link:focus, .btn-link:active {
+  border-color: transparent;
+}
+
+.btn-link:hover {
+  border-color: transparent;
+}
+
+.btn-link:focus, .btn-link:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link:disabled:focus, .btn-link:disabled:hover {
+  color: #818a91;
+  text-decoration: none;
+}
+
+.btn-lg, .btn-group-lg > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.btn-sm, .btn-group-sm > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+}
+
+.btn-block + .btn-block {
+  margin-top: 0.5rem;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+  -o-transition: opacity .15s linear;
+  transition: opacity .15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  display: none;
+}
+
+.collapse.in {
+  display: block;
+}
+
+tr.collapse.in {
+  display: table-row;
+}
+
+tbody.collapse.in {
+  display: table-row-group;
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition-timing-function: ease;
+       -o-transition-timing-function: ease;
+          transition-timing-function: ease;
+  -webkit-transition-duration: .35s;
+       -o-transition-duration: .35s;
+          transition-duration: .35s;
+  -webkit-transition-property: height;
+  -o-transition-property: height;
+  transition-property: height;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.3em;
+  vertical-align: middle;
+  content: "";
+  border-top: 0.3em solid;
+  border-right: 0.3em solid transparent;
+  border-left: 0.3em solid transparent;
+}
+
+.dropdown-toggle:focus {
+  outline: 0;
+}
+
+.dropup .dropdown-toggle::after {
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 10rem;
+  padding: 0.5rem 0;
+  margin: 0.125rem 0 0;
+  font-size: 1rem;
+  color: #373a3c;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.dropdown-divider {
+  height: 1px;
+  margin: 0.5rem 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+
+.dropdown-item {
+  display: block;
+  width: 100%;
+  padding: 3px 1.5rem;
+  clear: both;
+  font-weight: normal;
+  color: #373a3c;
+  text-align: inherit;
+  white-space: nowrap;
+  background: none;
+  border: 0;
+}
+
+.dropdown-item:focus, .dropdown-item:hover {
+  color: #2b2d2f;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.dropdown-item.active, .dropdown-item.active:focus, .dropdown-item.active:hover {
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  outline: 0;
+}
+
+.dropdown-item.disabled, .dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  color: #818a91;
+}
+
+.dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: "progid:DXImageTransform.Microsoft.gradient(enabled = false)";
+}
+
+.open > .dropdown-menu {
+  display: block;
+}
+
+.open > a {
+  outline: 0;
+}
+
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+
+.dropdown-header {
+  display: block;
+  padding: 0.5rem 1.5rem;
+  margin-bottom: 0;
+  font-size: 0.875rem;
+  color: #818a91;
+  white-space: nowrap;
+}
+
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 0.125rem;
+}
+
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+  margin-bottom: 0;
+}
+
+.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+.btn-group-vertical > .btn:focus,
+.btn-group-vertical > .btn:active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover {
+  z-index: 2;
+}
+
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+
+.btn-toolbar {
+  margin-left: -0.5rem;
+}
+
+.btn-toolbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 0.5rem;
+}
+
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group > .btn-group {
+  float: left;
+}
+
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+.btn + .dropdown-toggle-split {
+  padding-right: 0.75rem;
+  padding-left: 0.75rem;
+}
+
+.btn + .dropdown-toggle-split::after {
+  margin-left: 0;
+}
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+  padding-right: 0.375rem;
+  padding-left: 0.375rem;
+}
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+  padding-right: 1.125rem;
+  padding-left: 1.125rem;
+}
+
+.btn .caret {
+  margin-left: 0;
+}
+
+.btn-lg .caret, .btn-group-lg > .btn .caret {
+  border-width: 0.3em 0.3em 0;
+  border-bottom-width: 0;
+}
+
+.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret {
+  border-width: 0 0.3em 0.3em;
+}
+
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+
+.btn-group-vertical > .btn-group::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+  position: absolute;
+  clip: rect(0, 0, 0, 0);
+  pointer-events: none;
+}
+
+.input-group {
+  position: relative;
+  width: 100%;
+  display: table;
+  border-collapse: separate;
+}
+
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+
+.input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {
+  z-index: 3;
+}
+
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+
+.input-group-addon {
+  padding: 0.5rem 0.75rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+  font-weight: normal;
+  line-height: 1.25;
+  color: #55595c;
+  text-align: center;
+  background-color: #eceeef;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.input-group-addon.form-control-sm,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .input-group-addon.btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.input-group-addon.form-control-lg,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .input-group-addon.btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+
+.input-group .form-control:not(:last-child),
+.input-group-addon:not(:last-child),
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group > .btn,
+.input-group-btn:not(:last-child) > .dropdown-toggle,
+.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.input-group-addon:not(:last-child) {
+  border-right: 0;
+}
+
+.input-group .form-control:not(:first-child),
+.input-group-addon:not(:first-child),
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group > .btn,
+.input-group-btn:not(:first-child) > .dropdown-toggle,
+.input-group-btn:not(:last-child) > .btn:not(:first-child),
+.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.form-control + .input-group-addon:not(:first-child) {
+  border-left: 0;
+}
+
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+
+.input-group-btn > .btn {
+  position: relative;
+}
+
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+
+.input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {
+  z-index: 3;
+}
+
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group {
+  margin-right: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group {
+  z-index: 2;
+  margin-left: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,
+.input-group-btn:not(:first-child) > .btn-group:focus,
+.input-group-btn:not(:first-child) > .btn-group:active,
+.input-group-btn:not(:first-child) > .btn-group:hover {
+  z-index: 3;
+}
+
+.custom-control {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.5rem;
+  cursor: pointer;
+}
+
+.custom-control + .custom-control {
+  margin-left: 1rem;
+}
+
+.custom-control-input {
+  position: absolute;
+  z-index: -1;
+  opacity: 0;
+}
+
+.custom-control-input:checked ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #0074d9;
+}
+
+.custom-control-input:focus ~ .custom-control-indicator {
+  -webkit-box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+          box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+}
+
+.custom-control-input:active ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #84c6ff;
+}
+
+.custom-control-input:disabled ~ .custom-control-indicator {
+  cursor: not-allowed;
+  background-color: #eee;
+}
+
+.custom-control-input:disabled ~ .custom-control-description {
+  color: #767676;
+  cursor: not-allowed;
+}
+
+.custom-control-indicator {
+  position: absolute;
+  top: .25rem;
+  left: 0;
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  pointer-events: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #ddd;
+  background-repeat: no-repeat;
+  background-position: center center;
+  -webkit-background-size: 50% 50%;
+          background-size: 50% 50%;
+}
+
+.custom-checkbox .custom-control-indicator {
+  border-radius: 0.25rem;
+}
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
+}
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {
+  background-color: #0074d9;
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#fff' d='M0 2h4'/%3E%3C/svg%3E");
+}
+
+.custom-radio .custom-control-indicator {
+  border-radius: 50%;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#fff'/%3E%3C/svg%3E");
+}
+
+.custom-controls-stacked .custom-control {
+  float: left;
+  clear: left;
+}
+
+.custom-controls-stacked .custom-control + .custom-control {
+  margin-left: 0;
+}
+
+.custom-select {
+  display: inline-block;
+  max-width: 100%;
+  height: calc(2.5rem - 2px);
+  padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+  padding-right: 0.75rem \9;
+  color: #55595c;
+  vertical-align: middle;
+  background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;
+  background-image: none \9;
+  -webkit-background-size: 8px 10px;
+          background-size: 8px 10px;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+  -moz-appearance: none;
+  -webkit-appearance: none;
+}
+
+.custom-select:focus {
+  border-color: #51a7e8;
+  outline: none;
+}
+
+.custom-select:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.custom-select:disabled {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.custom-select::-ms-expand {
+  opacity: 0;
+}
+
+.custom-select-sm {
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  font-size: 75%;
+}
+
+.custom-file {
+  position: relative;
+  display: inline-block;
+  max-width: 100%;
+  height: 2.5rem;
+  cursor: pointer;
+}
+
+.custom-file-input {
+  min-width: 14rem;
+  max-width: 100%;
+  margin: 0;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+
+.custom-file-control {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 5;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+}
+
+.custom-file-control:lang(en)::after {
+  content: "Choose file...";
+}
+
+.custom-file-control::before {
+  position: absolute;
+  top: -1px;
+  right: -1px;
+  bottom: -1px;
+  z-index: 6;
+  display: block;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  background-color: #eee;
+  border: 1px solid #ddd;
+  border-radius: 0 0.25rem 0.25rem 0;
+}
+
+.custom-file-control:lang(en)::before {
+  content: "Browse";
+}
+
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.nav-link {
+  display: inline-block;
+}
+
+.nav-link:focus, .nav-link:hover {
+  text-decoration: none;
+}
+
+.nav-link.disabled {
+  color: #818a91;
+}
+
+.nav-link.disabled, .nav-link.disabled:focus, .nav-link.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+
+.nav-inline .nav-item {
+  display: inline-block;
+}
+
+.nav-inline .nav-item + .nav-item,
+.nav-inline .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-tabs .nav-item {
+  float: left;
+  margin-bottom: -1px;
+}
+
+.nav-tabs .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-tabs .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border: 1px solid transparent;
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover {
+  border-color: #eceeef #eceeef #ddd;
+}
+
+.nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:focus, .nav-tabs .nav-link.disabled:hover {
+  color: #818a91;
+  background-color: transparent;
+  border-color: transparent;
+}
+
+.nav-tabs .nav-link.active, .nav-tabs .nav-link.active:focus, .nav-tabs .nav-link.active:hover,
+.nav-tabs .nav-item.open .nav-link,
+.nav-tabs .nav-item.open .nav-link:focus,
+.nav-tabs .nav-item.open .nav-link:hover {
+  color: #55595c;
+  background-color: #bbccdd;
+  border-color: #ddd #ddd transparent;
+}
+
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.nav-pills::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-pills .nav-item {
+  float: left;
+}
+
+.nav-pills .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-pills .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border-radius: 0.25rem;
+}
+
+.nav-pills .nav-link.active, .nav-pills .nav-link.active:focus, .nav-pills .nav-link.active:hover,
+.nav-pills .nav-item.open .nav-link,
+.nav-pills .nav-item.open .nav-link:focus,
+.nav-pills .nav-item.open .nav-link:hover {
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+}
+
+.nav-stacked .nav-item {
+  display: block;
+  float: none;
+}
+
+.nav-stacked .nav-item + .nav-item {
+  margin-top: 0.2rem;
+  margin-left: 0;
+}
+
+.tab-content > .tab-pane {
+  display: none;
+}
+
+.tab-content > .active {
+  display: block;
+}
+
+.navbar {
+  position: relative;
+  padding: 0.5rem 1rem;
+}
+
+.navbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .navbar {
+    border-radius: 0.25rem;
+  }
+}
+
+.navbar-full {
+  z-index: 1000;
+}
+
+@media (min-width: 576px) {
+  .navbar-full {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+@media (min-width: 576px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top {
+  top: 0;
+}
+
+.navbar-fixed-bottom {
+  bottom: 0;
+}
+
+.navbar-sticky-top {
+  position: -webkit-sticky;
+  position: sticky;
+  top: 0;
+  z-index: 1030;
+  width: 100%;
+}
+
+@media (min-width: 576px) {
+  .navbar-sticky-top {
+    border-radius: 0;
+  }
+}
+
+.navbar-brand {
+  float: left;
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  margin-right: 1rem;
+  font-size: 1.25rem;
+  line-height: inherit;
+}
+
+.navbar-brand:focus, .navbar-brand:hover {
+  text-decoration: none;
+}
+
+.navbar-divider {
+  float: left;
+  width: 1px;
+  padding-top: 0.425rem;
+  padding-bottom: 0.425rem;
+  margin-right: 1rem;
+  margin-left: 1rem;
+  overflow: hidden;
+}
+
+.navbar-divider::before {
+  content: "\00a0";
+}
+
+.navbar-text {
+  display: inline-block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-toggler {
+  width: 2.5em;
+  height: 2em;
+  padding: 0.5rem 0.75rem;
+  font-size: 1.25rem;
+  line-height: 1;
+  background: transparent no-repeat center center;
+  -webkit-background-size: 24px 24px;
+          background-size: 24px 24px;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.navbar-toggler:focus, .navbar-toggler:hover {
+  text-decoration: none;
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-xs .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-xs .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-sm .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-sm .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-md .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-md .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block;
+  }
+}
+
+.navbar-toggleable-lg::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 1199px) {
+  .navbar-toggleable-lg .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-lg .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-lg .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 1200px) {
+  .navbar-toggleable-lg {
+    display: block;
+  }
+}
+
+.navbar-toggleable-xl {
+  display: block;
+}
+
+.navbar-toggleable-xl::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.navbar-toggleable-xl .navbar-brand {
+  display: block;
+  float: none;
+  margin-top: .5rem;
+  margin-right: 0;
+}
+
+.navbar-toggleable-xl .navbar-nav {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+
+.navbar-toggleable-xl .navbar-nav .dropdown-menu {
+  position: static;
+  float: none;
+}
+
+.navbar-nav .nav-item {
+  float: left;
+}
+
+.navbar-nav .nav-link {
+  display: block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-nav .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.navbar-nav .nav-item + .nav-item {
+  margin-left: 1rem;
+}
+
+.navbar-light .navbar-brand,
+.navbar-light .navbar-toggler {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover,
+.navbar-light .navbar-toggler:focus,
+.navbar-light .navbar-toggler:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-nav .nav-link {
+  color: rgba(0, 0, 0, 0.5);
+}
+
+.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover {
+  color: rgba(0, 0, 0, 0.7);
+}
+
+.navbar-light .navbar-nav .open > .nav-link, .navbar-light .navbar-nav .open > .nav-link:focus, .navbar-light .navbar-nav .open > .nav-link:hover,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link:focus,
+.navbar-light .navbar-nav .active > .nav-link:hover,
+.navbar-light .navbar-nav .nav-link.open,
+.navbar-light .navbar-nav .nav-link.open:focus,
+.navbar-light .navbar-nav .nav-link.open:hover,
+.navbar-light .navbar-nav .nav-link.active,
+.navbar-light .navbar-nav .nav-link.active:focus,
+.navbar-light .navbar-nav .nav-link.active:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.navbar-light .navbar-divider {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.navbar-dark .navbar-brand,
+.navbar-dark .navbar-toggler {
+  color: white;
+}
+
+.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover,
+.navbar-dark .navbar-toggler:focus,
+.navbar-dark .navbar-toggler:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-nav .nav-link {
+  color: rgba(255, 255, 255, 0.5);
+}
+
+.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.navbar-dark .navbar-nav .open > .nav-link, .navbar-dark .navbar-nav .open > .nav-link:focus, .navbar-dark .navbar-nav .open > .nav-link:hover,
+.navbar-dark .navbar-nav .active > .nav-link,
+.navbar-dark .navbar-nav .active > .nav-link:focus,
+.navbar-dark .navbar-nav .active > .nav-link:hover,
+.navbar-dark .navbar-nav .nav-link.open,
+.navbar-dark .navbar-nav .nav-link.open:focus,
+.navbar-dark .navbar-nav .nav-link.open:hover,
+.navbar-dark .navbar-nav .nav-link.active,
+.navbar-dark .navbar-nav .nav-link.active:focus,
+.navbar-dark .navbar-nav .nav-link.active:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(255, 255, 255, 0.1);
+}
+
+.navbar-dark .navbar-divider {
+  background-color: rgba(255, 255, 255, 0.075);
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block !important;
+  }
+}
+
+.card {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+  background-color: #fff;
+  border-radius: 0.25rem;
+  border: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-block {
+  padding: 1.25rem;
+}
+
+.card-block::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-title {
+  margin-bottom: 0.75rem;
+}
+
+.card-subtitle {
+  margin-top: -0.375rem;
+  margin-bottom: 0;
+}
+
+.card-text:last-child {
+  margin-bottom: 0;
+}
+
+.card-link:hover {
+  text-decoration: none;
+}
+
+.card-link + .card-link {
+  margin-left: 1.25rem;
+}
+
+.card > .list-group:first-child .list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.card > .list-group:last-child .list-group-item:last-child {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.card-header {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 0;
+  background-color: #f5f5f5;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-header:first-child {
+  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
+}
+
+.card-footer {
+  padding: 0.75rem 1.25rem;
+  background-color: #f5f5f5;
+  border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-footer:last-child {
+  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);
+}
+
+.card-header-tabs {
+  margin-right: -0.625rem;
+  margin-bottom: -0.75rem;
+  margin-left: -0.625rem;
+  border-bottom: 0;
+}
+
+.card-header-pills {
+  margin-right: -0.625rem;
+  margin-left: -0.625rem;
+}
+
+.card-primary {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.card-primary .card-header,
+.card-primary .card-footer {
+  background-color: transparent;
+}
+
+.card-success {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.card-success .card-header,
+.card-success .card-footer {
+  background-color: transparent;
+}
+
+.card-info {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.card-info .card-header,
+.card-info .card-footer {
+  background-color: transparent;
+}
+
+.card-warning {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.card-warning .card-header,
+.card-warning .card-footer {
+  background-color: transparent;
+}
+
+.card-danger {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.card-danger .card-header,
+.card-danger .card-footer {
+  background-color: transparent;
+}
+
+.card-outline-primary {
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.card-outline-secondary {
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.card-outline-info {
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.card-outline-success {
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.card-outline-warning {
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.card-outline-danger {
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer {
+  border-color: rgba(255, 255, 255, 0.2);
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer,
+.card-inverse .card-title,
+.card-inverse .card-blockquote {
+  color: #fff;
+}
+
+.card-inverse .card-link,
+.card-inverse .card-text,
+.card-inverse .card-subtitle,
+.card-inverse .card-blockquote .blockquote-footer {
+  color: rgba(255, 255, 255, 0.65);
+}
+
+.card-inverse .card-link:focus, .card-inverse .card-link:hover {
+  color: #fff;
+}
+
+.card-blockquote {
+  padding: 0;
+  margin-bottom: 0;
+  border-left: 0;
+}
+
+.card-img {
+  border-radius: calc(0.25rem - 1px);
+}
+
+.card-img-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1.25rem;
+}
+
+.card-img-top {
+  border-top-right-radius: calc(0.25rem - 1px);
+  border-top-left-radius: calc(0.25rem - 1px);
+}
+
+.card-img-bottom {
+  border-bottom-right-radius: calc(0.25rem - 1px);
+  border-bottom-left-radius: calc(0.25rem - 1px);
+}
+
+@media (min-width: 576px) {
+  .card-deck {
+    display: table;
+    width: 100%;
+    margin-bottom: 0.75rem;
+    table-layout: fixed;
+    border-spacing: 1.25rem 0;
+  }
+  .card-deck .card {
+    display: table-cell;
+    margin-bottom: 0;
+    vertical-align: top;
+  }
+  .card-deck-wrapper {
+    margin-right: -1.25rem;
+    margin-left: -1.25rem;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-group {
+    display: table;
+    width: 100%;
+    table-layout: fixed;
+  }
+  .card-group .card {
+    display: table-cell;
+    vertical-align: top;
+  }
+  .card-group .card + .card {
+    margin-left: 0;
+    border-left: 0;
+  }
+  .card-group .card:first-child {
+    border-bottom-right-radius: 0;
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-top {
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-bottom {
+    border-bottom-right-radius: 0;
+  }
+  .card-group .card:last-child {
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-top {
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-bottom {
+    border-bottom-left-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) {
+    border-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) .card-img-top,
+  .card-group .card:not(:first-child):not(:last-child) .card-img-bottom {
+    border-radius: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-columns {
+    -webkit-column-count: 3;
+       -moz-column-count: 3;
+            column-count: 3;
+    -webkit-column-gap: 1.25rem;
+       -moz-column-gap: 1.25rem;
+            column-gap: 1.25rem;
+  }
+  .card-columns .card {
+    display: inline-block;
+    width: 100%;
+  }
+}
+
+.breadcrumb {
+  padding: 0.75rem 1rem;
+  margin-bottom: 1rem;
+  list-style: none;
+  background-color: #eceeef;
+  border-radius: 0.25rem;
+}
+
+.breadcrumb::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.breadcrumb-item {
+  float: left;
+}
+
+.breadcrumb-item + .breadcrumb-item::before {
+  display: inline-block;
+  padding-right: 0.5rem;
+  padding-left: 0.5rem;
+  color: #818a91;
+  content: "/";
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: underline;
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: none;
+}
+
+.breadcrumb-item.active {
+  color: #818a91;
+}
+
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border-radius: 0.25rem;
+}
+
+.page-item {
+  display: inline;
+}
+
+.page-item:first-child .page-link {
+  margin-left: 0;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.page-item:last-child .page-link {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.page-item.active .page-link, .page-item.active .page-link:focus, .page-item.active .page-link:hover {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.page-item.disabled .page-link, .page-item.disabled .page-link:focus, .page-item.disabled .page-link:hover {
+  color: #818a91;
+  pointer-events: none;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+
+.page-link {
+  position: relative;
+  float: left;
+  padding: 0.5rem 0.75rem;
+  margin-left: -1px;
+  color: #0275d8;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.page-link:focus, .page-link:hover {
+  color: #014c8c;
+  background-color: #eceeef;
+  border-color: #ddd;
+}
+
+.pagination-lg .page-link {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+}
+
+.pagination-lg .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.3rem;
+  border-top-left-radius: 0.3rem;
+}
+
+.pagination-lg .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.3rem;
+  border-top-right-radius: 0.3rem;
+}
+
+.pagination-sm .page-link {
+  padding: 0.275rem 0.75rem;
+  font-size: 0.875rem;
+}
+
+.pagination-sm .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.2rem;
+  border-top-left-radius: 0.2rem;
+}
+
+.pagination-sm .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.2rem;
+  border-top-right-radius: 0.2rem;
+}
+
+.tag {
+  display: inline-block;
+  padding: 0.25em 0.4em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: 0.25rem;
+}
+
+.tag:empty {
+  display: none;
+}
+
+.btn .tag {
+  position: relative;
+  top: -1px;
+}
+
+a.tag:focus, a.tag:hover {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.tag-pill {
+  padding-right: 0.6em;
+  padding-left: 0.6em;
+  border-radius: 10rem;
+}
+
+.tag-default {
+  background-color: #818a91;
+}
+
+.tag-default[href]:focus, .tag-default[href]:hover {
+  background-color: #687077;
+}
+
+.tag-primary {
+  background-color: #0275d8;
+}
+
+.tag-primary[href]:focus, .tag-primary[href]:hover {
+  background-color: #025aa5;
+}
+
+.tag-success {
+  background-color: #5cb85c;
+}
+
+.tag-success[href]:focus, .tag-success[href]:hover {
+  background-color: #449d44;
+}
+
+.tag-info {
+  background-color: #5bc0de;
+}
+
+.tag-info[href]:focus, .tag-info[href]:hover {
+  background-color: #31b0d5;
+}
+
+.tag-warning {
+  background-color: #f0ad4e;
+}
+
+.tag-warning[href]:focus, .tag-warning[href]:hover {
+  background-color: #ec971f;
+}
+
+.tag-danger {
+  background-color: #d9534f;
+}
+
+.tag-danger[href]:focus, .tag-danger[href]:hover {
+  background-color: #c9302c;
+}
+
+.jumbotron {
+  padding: 2rem 1rem;
+  margin-bottom: 2rem;
+  background-color: #eceeef;
+  border-radius: 0.3rem;
+}
+
+@media (min-width: 576px) {
+  .jumbotron {
+    padding: 4rem 2rem;
+  }
+}
+
+.jumbotron-hr {
+  border-top-color: #d0d5d8;
+}
+
+.jumbotron-fluid {
+  padding-right: 0;
+  padding-left: 0;
+  border-radius: 0;
+}
+
+.alert {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 1rem;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.alert-heading {
+  color: inherit;
+}
+
+.alert-link {
+  font-weight: bold;
+}
+
+.alert-dismissible {
+  padding-right: 2.5rem;
+}
+
+.alert-dismissible .close {
+  position: relative;
+  top: -.125rem;
+  right: -1.25rem;
+  color: inherit;
+}
+
+.alert-success {
+  background-color: #dff0d8;
+  border-color: #d0e9c6;
+  color: #3c763d;
+}
+
+.alert-success hr {
+  border-top-color: #c1e2b3;
+}
+
+.alert-success .alert-link {
+  color: #2b542c;
+}
+
+.alert-info {
+  background-color: #d9edf7;
+  border-color: #bcdff1;
+  color: #31708f;
+}
+
+.alert-info hr {
+  border-top-color: #a6d5ec;
+}
+
+.alert-info .alert-link {
+  color: #245269;
+}
+
+.alert-warning {
+  background-color: #fcf8e3;
+  border-color: #faf2cc;
+  color: #8a6d3b;
+}
+
+.alert-warning hr {
+  border-top-color: #f7ecb5;
+}
+
+.alert-warning .alert-link {
+  color: #66512c;
+}
+
+.alert-danger {
+  background-color: #f2dede;
+  border-color: #ebcccc;
+  color: #a94442;
+}
+
+.alert-danger hr {
+  border-top-color: #e4b9b9;
+}
+
+.alert-danger .alert-link {
+  color: #843534;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  display: block;
+  width: 100%;
+  height: 1rem;
+  margin-bottom: 1rem;
+}
+
+.progress[value] {
+  background-color: #eee;
+  border: 0;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  border-radius: 0.25rem;
+}
+
+.progress[value]::-ms-fill {
+  background-color: #0074d9;
+  border: 0;
+}
+
+.progress[value]::-moz-progress-bar {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-value {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value="100"]::-moz-progress-bar {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value="100"]::-webkit-progress-value {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-bar {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+base::-moz-progress-bar,
+.progress[value] {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress {
+    background-color: #eee;
+    border-radius: 0.25rem;
+  }
+  .progress-bar {
+    display: inline-block;
+    height: 1rem;
+    text-indent: -999rem;
+    background-color: #0074d9;
+    border-bottom-left-radius: 0.25rem;
+    border-top-left-radius: 0.25rem;
+  }
+  .progress[width="100%"] {
+    border-bottom-right-radius: 0.25rem;
+    border-top-right-radius: 0.25rem;
+  }
+}
+
+.progress-striped[value]::-webkit-progress-value {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 1rem 1rem;
+          background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-moz-progress-bar {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-ms-fill {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-bar-striped {
+    background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    -webkit-background-size: 1rem 1rem;
+            background-size: 1rem 1rem;
+  }
+}
+
+.progress-animated[value]::-webkit-progress-value {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-animated[value]::-moz-progress-bar {
+  animation: progress-bar-stripes 2s linear infinite;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-animated .progress-bar-striped {
+    -webkit-animation: progress-bar-stripes 2s linear infinite;
+         -o-animation: progress-bar-stripes 2s linear infinite;
+            animation: progress-bar-stripes 2s linear infinite;
+  }
+}
+
+.progress-success[value]::-webkit-progress-value {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-moz-progress-bar {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-ms-fill {
+  background-color: #5cb85c;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-success .progress-bar {
+    background-color: #5cb85c;
+  }
+}
+
+.progress-info[value]::-webkit-progress-value {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-moz-progress-bar {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-ms-fill {
+  background-color: #5bc0de;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-info .progress-bar {
+    background-color: #5bc0de;
+  }
+}
+
+.progress-warning[value]::-webkit-progress-value {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-moz-progress-bar {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-ms-fill {
+  background-color: #f0ad4e;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-warning .progress-bar {
+    background-color: #f0ad4e;
+  }
+}
+
+.progress-danger[value]::-webkit-progress-value {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-moz-progress-bar {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-ms-fill {
+  background-color: #d9534f;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-danger .progress-bar {
+    background-color: #d9534f;
+  }
+}
+
+.media,
+.media-body {
+  overflow: hidden;
+}
+
+.media-body {
+  width: 10000px;
+}
+
+.media-left,
+.media-right,
+.media-body {
+  display: table-cell;
+  vertical-align: top;
+}
+
+.media-middle {
+  vertical-align: middle;
+}
+
+.media-bottom {
+  vertical-align: bottom;
+}
+
+.media-object {
+  display: block;
+}
+
+.media-object.img-thumbnail {
+  max-width: none;
+}
+
+.media-right {
+  padding-left: 10px;
+}
+
+.media-left {
+  padding-right: 10px;
+}
+
+.media-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-group {
+  padding-left: 0;
+  margin-bottom: 0;
+}
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 0.75rem 1.25rem;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.list-group-item.disabled, .list-group-item.disabled:focus, .list-group-item.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading {
+  color: inherit;
+}
+
+.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text {
+  color: #818a91;
+}
+
+.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover {
+  z-index: 2;
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > .small {
+  color: inherit;
+}
+
+.list-group-item.active .list-group-item-text, .list-group-item.active:focus .list-group-item-text, .list-group-item.active:hover .list-group-item-text {
+  color: #a8d6fe;
+}
+
+.list-group-flush .list-group-item {
+  border-right: 0;
+  border-left: 0;
+  border-radius: 0;
+}
+
+.list-group-item-action {
+  width: 100%;
+  color: #555;
+  text-align: inherit;
+}
+
+.list-group-item-action .list-group-item-heading {
+  color: #333;
+}
+
+.list-group-item-action:focus, .list-group-item-action:hover {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+
+a.list-group-item-success,
+button.list-group-item-success {
+  color: #3c763d;
+}
+
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-success:focus, a.list-group-item-success:hover,
+button.list-group-item-success:focus,
+button.list-group-item-success:hover {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+
+a.list-group-item-success.active, a.list-group-item-success.active:focus, a.list-group-item-success.active:hover,
+button.list-group-item-success.active,
+button.list-group-item-success.active:focus,
+button.list-group-item-success.active:hover {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+
+a.list-group-item-info,
+button.list-group-item-info {
+  color: #31708f;
+}
+
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-info:focus, a.list-group-item-info:hover,
+button.list-group-item-info:focus,
+button.list-group-item-info:hover {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+
+a.list-group-item-info.active, a.list-group-item-info.active:focus, a.list-group-item-info.active:hover,
+button.list-group-item-info.active,
+button.list-group-item-info.active:focus,
+button.list-group-item-info.active:hover {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+
+a.list-group-item-warning,
+button.list-group-item-warning {
+  color: #8a6d3b;
+}
+
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-warning:focus, a.list-group-item-warning:hover,
+button.list-group-item-warning:focus,
+button.list-group-item-warning:hover {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+
+a.list-group-item-warning.active, a.list-group-item-warning.active:focus, a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active,
+button.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:hover {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+
+a.list-group-item-danger,
+button.list-group-item-danger {
+  color: #a94442;
+}
+
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-danger:focus, a.list-group-item-danger:hover,
+button.list-group-item-danger:focus,
+button.list-group-item-danger:hover {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+
+a.list-group-item-danger.active, a.list-group-item-danger.active:focus, a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active,
+button.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:hover {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+.embed-responsive-21by9 {
+  padding-bottom: 42.857143%;
+}
+
+.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+
+.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+
+.embed-responsive-1by1 {
+  padding-bottom: 100%;
+}
+
+.close {
+  float: right;
+  font-size: 1.5rem;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  opacity: .2;
+}
+
+.close:focus, .close:hover {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  opacity: .5;
+}
+
+button.close {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.modal-open {
+  overflow: hidden;
+}
+
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  outline: 0;
+}
+
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+  transition: -webkit-transform .3s ease-out;
+  -o-transition: -o-transform .3s ease-out;
+  transition: transform .3s ease-out;
+  transition: transform .3s ease-out, -webkit-transform .3s ease-out, -o-transform .3s ease-out;
+  -webkit-transform: translate(0, -25%);
+      -ms-transform: translate(0, -25%);
+       -o-transform: translate(0, -25%);
+          transform: translate(0, -25%);
+}
+
+.modal.in .modal-dialog {
+  -webkit-transform: translate(0, 0);
+      -ms-transform: translate(0, 0);
+       -o-transform: translate(0, 0);
+          transform: translate(0, 0);
+}
+
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+  outline: 0;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop.in {
+  opacity: 0.5;
+}
+
+.modal-header {
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+.modal-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-header .close {
+  margin-top: -2px;
+}
+
+.modal-title {
+  margin: 0;
+  line-height: 1.5;
+}
+
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+
+.modal-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+
+@media (min-width: 576px) {
+  .modal-dialog {
+    max-width: 600px;
+    margin: 30px auto;
+  }
+  .modal-sm {
+    max-width: 300px;
+  }
+}
+
+@media (min-width: 992px) {
+  .modal-lg {
+    max-width: 900px;
+  }
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  opacity: 0;
+}
+
+.tooltip.in {
+  opacity: 0.9;
+}
+
+.tooltip.tooltip-top, .tooltip.bs-tether-element-attached-bottom {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+
+.tooltip.tooltip-top .tooltip-inner::before, .tooltip.bs-tether-element-attached-bottom .tooltip-inner::before {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+
+.tooltip.tooltip-right, .tooltip.bs-tether-element-attached-left {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+
+.tooltip.tooltip-right .tooltip-inner::before, .tooltip.bs-tether-element-attached-left .tooltip-inner::before {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+
+.tooltip.tooltip-bottom, .tooltip.bs-tether-element-attached-top {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+
+.tooltip.tooltip-bottom .tooltip-inner::before, .tooltip.bs-tether-element-attached-top .tooltip-inner::before {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+
+.tooltip.tooltip-left, .tooltip.bs-tether-element-attached-right {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+
+.tooltip.tooltip-left .tooltip-inner::before, .tooltip.bs-tether-element-attached-right .tooltip-inner::before {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  background-color: #000;
+  border-radius: 0.25rem;
+}
+
+.tooltip-inner::before {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: block;
+  max-width: 276px;
+  padding: 1px;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+}
+
+.popover.popover-top, .popover.bs-tether-element-attached-bottom {
+  margin-top: -10px;
+}
+
+.popover.popover-top::before, .popover.popover-top::after, .popover.bs-tether-element-attached-bottom::before, .popover.bs-tether-element-attached-bottom::after {
+  left: 50%;
+  border-bottom-width: 0;
+}
+
+.popover.popover-top::before, .popover.bs-tether-element-attached-bottom::before {
+  bottom: -11px;
+  margin-left: -11px;
+  border-top-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-top::after, .popover.bs-tether-element-attached-bottom::after {
+  bottom: -10px;
+  margin-left: -10px;
+  border-top-color: #fff;
+}
+
+.popover.popover-right, .popover.bs-tether-element-attached-left {
+  margin-left: 10px;
+}
+
+.popover.popover-right::before, .popover.popover-right::after, .popover.bs-tether-element-attached-left::before, .popover.bs-tether-element-attached-left::after {
+  top: 50%;
+  border-left-width: 0;
+}
+
+.popover.popover-right::before, .popover.bs-tether-element-attached-left::before {
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-right::after, .popover.bs-tether-element-attached-left::after {
+  left: -10px;
+  margin-top: -10px;
+  border-right-color: #fff;
+}
+
+.popover.popover-bottom, .popover.bs-tether-element-attached-top {
+  margin-top: 10px;
+}
+
+.popover.popover-bottom::before, .popover.popover-bottom::after, .popover.bs-tether-element-attached-top::before, .popover.bs-tether-element-attached-top::after {
+  left: 50%;
+  border-top-width: 0;
+}
+
+.popover.popover-bottom::before, .popover.bs-tether-element-attached-top::before {
+  top: -11px;
+  margin-left: -11px;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-bottom::after, .popover.bs-tether-element-attached-top::after {
+  top: -10px;
+  margin-left: -10px;
+  border-bottom-color: #f7f7f7;
+}
+
+.popover.popover-bottom .popover-title::before, .popover.bs-tether-element-attached-top .popover-title::before {
+  position: absolute;
+  top: 0;
+  left: 50%;
+  display: block;
+  width: 20px;
+  margin-left: -10px;
+  content: "";
+  border-bottom: 1px solid #f7f7f7;
+}
+
+.popover.popover-left, .popover.bs-tether-element-attached-right {
+  margin-left: -10px;
+}
+
+.popover.popover-left::before, .popover.popover-left::after, .popover.bs-tether-element-attached-right::before, .popover.bs-tether-element-attached-right::after {
+  top: 50%;
+  border-right-width: 0;
+}
+
+.popover.popover-left::before, .popover.bs-tether-element-attached-right::before {
+  right: -11px;
+  margin-top: -11px;
+  border-left-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-left::after, .popover.bs-tether-element-attached-right::after {
+  right: -10px;
+  margin-top: -10px;
+  border-left-color: #fff;
+}
+
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 1rem;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 0.2375rem 0.2375rem 0 0;
+}
+
+.popover-title:empty {
+  display: none;
+}
+
+.popover-content {
+  padding: 9px 14px;
+}
+
+.popover::before,
+.popover::after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover::before {
+  content: "";
+  border-width: 11px;
+}
+
+.popover::after {
+  content: "";
+  border-width: 10px;
+}
+
+.carousel {
+  position: relative;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-inner > .carousel-item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+  -o-transition: .6s ease-in-out left;
+  transition: .6s ease-in-out left;
+}
+
+.carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  line-height: 1;
+}
+
+@media all and (transform-3d), (-webkit-transform-3d) {
+  .carousel-inner > .carousel-item {
+    -webkit-transition: -webkit-transform .6s ease-in-out;
+    transition: -webkit-transform .6s ease-in-out;
+    -o-transition: -o-transform .6s ease-in-out;
+    transition: transform .6s ease-in-out;
+    transition: transform .6s ease-in-out, -webkit-transform .6s ease-in-out, -o-transform .6s ease-in-out;
+    -webkit-backface-visibility: hidden;
+            backface-visibility: hidden;
+    -webkit-perspective: 1000px;
+            perspective: 1000px;
+  }
+  .carousel-inner > .carousel-item.next, .carousel-inner > .carousel-item.active.right {
+    left: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+            transform: translate3d(100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.prev, .carousel-inner > .carousel-item.active.left {
+    left: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+            transform: translate3d(-100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.next.left, .carousel-inner > .carousel-item.prev.right, .carousel-inner > .carousel-item.active {
+    left: 0;
+    -webkit-transform: translate3d(0, 0, 0);
+            transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+
+.carousel-inner > .active {
+  left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.carousel-inner > .next {
+  left: 100%;
+}
+
+.carousel-inner > .prev {
+  left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+
+.carousel-inner > .active.left {
+  left: -100%;
+}
+
+.carousel-inner > .active.right {
+  left: 100%;
+}
+
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+  opacity: 0.5;
+}
+
+.carousel-control.left {
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+
+.carousel-control:focus, .carousel-control:hover {
+  color: #fff;
+  text-decoration: none;
+  outline: 0;
+  opacity: .9;
+}
+
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+  line-height: 1;
+}
+
+.carousel-control .icon-prev {
+  left: 50%;
+  margin-left: -10px;
+}
+
+.carousel-control .icon-next {
+  right: 50%;
+  margin-right: -10px;
+}
+
+.carousel-control .icon-prev::before {
+  content: "\2039";
+}
+
+.carousel-control .icon-next::before {
+  content: "\203a";
+}
+
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: transparent;
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+
+.carousel-caption .btn {
+  text-shadow: none;
+}
+
+@media (min-width: 576px) {
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+
+.align-baseline {
+  vertical-align: baseline !important;
+}
+
+.align-top {
+  vertical-align: top !important;
+}
+
+.align-middle {
+  vertical-align: middle !important;
+}
+
+.align-bottom {
+  vertical-align: bottom !important;
+}
+
+.align-text-bottom {
+  vertical-align: text-bottom !important;
+}
+
+.align-text-top {
+  vertical-align: text-top !important;
+}
+
+.bg-faded {
+  background-color: #f7f7f9;
+}
+
+.bg-primary {
+  background-color: #0275d8 !important;
+}
+
+a.bg-primary:focus, a.bg-primary:hover {
+  background-color: #025aa5 !important;
+}
+
+.bg-success {
+  background-color: #5cb85c !important;
+}
+
+a.bg-success:focus, a.bg-success:hover {
+  background-color: #449d44 !important;
+}
+
+.bg-info {
+  background-color: #5bc0de !important;
+}
+
+a.bg-info:focus, a.bg-info:hover {
+  background-color: #31b0d5 !important;
+}
+
+.bg-warning {
+  background-color: #f0ad4e !important;
+}
+
+a.bg-warning:focus, a.bg-warning:hover {
+  background-color: #ec971f !important;
+}
+
+.bg-danger {
+  background-color: #d9534f !important;
+}
+
+a.bg-danger:focus, a.bg-danger:hover {
+  background-color: #c9302c !important;
+}
+
+.bg-inverse {
+  background-color: #373a3c !important;
+}
+
+a.bg-inverse:focus, a.bg-inverse:hover {
+  background-color: #1f2021 !important;
+}
+
+.rounded {
+  border-radius: 0.25rem;
+}
+
+.rounded-top {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-right {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.rounded-bottom {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.rounded-left {
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-circle {
+  border-radius: 50%;
+}
+
+.clearfix::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.d-block {
+  display: block !important;
+}
+
+.d-inline-block {
+  display: inline-block !important;
+}
+
+.d-inline {
+  display: inline !important;
+}
+
+.float-xs-left {
+  float: left !important;
+}
+
+.float-xs-right {
+  float: right !important;
+}
+
+.float-xs-none {
+  float: none !important;
+}
+
+@media (min-width: 576px) {
+  .float-sm-left {
+    float: left !important;
+  }
+  .float-sm-right {
+    float: right !important;
+  }
+  .float-sm-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .float-md-left {
+    float: left !important;
+  }
+  .float-md-right {
+    float: right !important;
+  }
+  .float-md-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .float-lg-left {
+    float: left !important;
+  }
+  .float-lg-right {
+    float: right !important;
+  }
+  .float-lg-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .float-xl-left {
+    float: left !important;
+  }
+  .float-xl-right {
+    float: right !important;
+  }
+  .float-xl-none {
+    float: none !important;
+  }
+}
+
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+
+.w-100 {
+  width: 100% !important;
+}
+
+.h-100 {
+  height: 100% !important;
+}
+
+.mx-auto {
+  margin-right: auto !important;
+  margin-left: auto !important;
+}
+
+.m-0 {
+  margin: 0 0 !important;
+}
+
+.mt-0 {
+  margin-top: 0 !important;
+}
+
+.mr-0 {
+  margin-right: 0 !important;
+}
+
+.mb-0 {
+  margin-bottom: 0 !important;
+}
+
+.ml-0 {
+  margin-left: 0 !important;
+}
+
+.mx-0 {
+  margin-right: 0 !important;
+  margin-left: 0 !important;
+}
+
+.my-0 {
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+
+.m-1 {
+  margin: 1rem 1rem !important;
+}
+
+.mt-1 {
+  margin-top: 1rem !important;
+}
+
+.mr-1 {
+  margin-right: 1rem !important;
+}
+
+.mb-1 {
+  margin-bottom: 1rem !important;
+}
+
+.ml-1 {
+  margin-left: 1rem !important;
+}
+
+.mx-1 {
+  margin-right: 1rem !important;
+  margin-left: 1rem !important;
+}
+
+.my-1 {
+  margin-top: 1rem !important;
+  margin-bottom: 1rem !important;
+}
+
+.m-2 {
+  margin: 1.5rem 1.5rem !important;
+}
+
+.mt-2 {
+  margin-top: 1.5rem !important;
+}
+
+.mr-2 {
+  margin-right: 1.5rem !important;
+}
+
+.mb-2 {
+  margin-bottom: 1.5rem !important;
+}
+
+.ml-2 {
+  margin-left: 1.5rem !important;
+}
+
+.mx-2 {
+  margin-right: 1.5rem !important;
+  margin-left: 1.5rem !important;
+}
+
+.my-2 {
+  margin-top: 1.5rem !important;
+  margin-bottom: 1.5rem !important;
+}
+
+.m-3 {
+  margin: 3rem 3rem !important;
+}
+
+.mt-3 {
+  margin-top: 3rem !important;
+}
+
+.mr-3 {
+  margin-right: 3rem !important;
+}
+
+.mb-3 {
+  margin-bottom: 3rem !important;
+}
+
+.ml-3 {
+  margin-left: 3rem !important;
+}
+
+.mx-3 {
+  margin-right: 3rem !important;
+  margin-left: 3rem !important;
+}
+
+.my-3 {
+  margin-top: 3rem !important;
+  margin-bottom: 3rem !important;
+}
+
+.p-0 {
+  padding: 0 0 !important;
+}
+
+.pt-0 {
+  padding-top: 0 !important;
+}
+
+.pr-0 {
+  padding-right: 0 !important;
+}
+
+.pb-0 {
+  padding-bottom: 0 !important;
+}
+
+.pl-0 {
+  padding-left: 0 !important;
+}
+
+.px-0 {
+  padding-right: 0 !important;
+  padding-left: 0 !important;
+}
+
+.py-0 {
+  padding-top: 0 !important;
+  padding-bottom: 0 !important;
+}
+
+.p-1 {
+  padding: 1rem 1rem !important;
+}
+
+.pt-1 {
+  padding-top: 1rem !important;
+}
+
+.pr-1 {
+  padding-right: 1rem !important;
+}
+
+.pb-1 {
+  padding-bottom: 1rem !important;
+}
+
+.pl-1 {
+  padding-left: 1rem !important;
+}
+
+.px-1 {
+  padding-right: 1rem !important;
+  padding-left: 1rem !important;
+}
+
+.py-1 {
+  padding-top: 1rem !important;
+  padding-bottom: 1rem !important;
+}
+
+.p-2 {
+  padding: 1.5rem 1.5rem !important;
+}
+
+.pt-2 {
+  padding-top: 1.5rem !important;
+}
+
+.pr-2 {
+  padding-right: 1.5rem !important;
+}
+
+.pb-2 {
+  padding-bottom: 1.5rem !important;
+}
+
+.pl-2 {
+  padding-left: 1.5rem !important;
+}
+
+.px-2 {
+  padding-right: 1.5rem !important;
+  padding-left: 1.5rem !important;
+}
+
+.py-2 {
+  padding-top: 1.5rem !important;
+  padding-bottom: 1.5rem !important;
+}
+
+.p-3 {
+  padding: 3rem 3rem !important;
+}
+
+.pt-3 {
+  padding-top: 3rem !important;
+}
+
+.pr-3 {
+  padding-right: 3rem !important;
+}
+
+.pb-3 {
+  padding-bottom: 3rem !important;
+}
+
+.pl-3 {
+  padding-left: 3rem !important;
+}
+
+.px-3 {
+  padding-right: 3rem !important;
+  padding-left: 3rem !important;
+}
+
+.py-3 {
+  padding-top: 3rem !important;
+  padding-bottom: 3rem !important;
+}
+
+.pos-f-t {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+.text-justify {
+  text-align: justify !important;
+}
+
+.text-nowrap {
+  white-space: nowrap !important;
+}
+
+.text-truncate {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.text-xs-left {
+  text-align: left !important;
+}
+
+.text-xs-right {
+  text-align: right !important;
+}
+
+.text-xs-center {
+  text-align: center !important;
+}
+
+@media (min-width: 576px) {
+  .text-sm-left {
+    text-align: left !important;
+  }
+  .text-sm-right {
+    text-align: right !important;
+  }
+  .text-sm-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .text-md-left {
+    text-align: left !important;
+  }
+  .text-md-right {
+    text-align: right !important;
+  }
+  .text-md-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .text-lg-left {
+    text-align: left !important;
+  }
+  .text-lg-right {
+    text-align: right !important;
+  }
+  .text-lg-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .text-xl-left {
+    text-align: left !important;
+  }
+  .text-xl-right {
+    text-align: right !important;
+  }
+  .text-xl-center {
+    text-align: center !important;
+  }
+}
+
+.text-lowercase {
+  text-transform: lowercase !important;
+}
+
+.text-uppercase {
+  text-transform: uppercase !important;
+}
+
+.text-capitalize {
+  text-transform: capitalize !important;
+}
+
+.font-weight-normal {
+  font-weight: normal;
+}
+
+.font-weight-bold {
+  font-weight: bold;
+}
+
+.font-italic {
+  font-style: italic;
+}
+
+.text-white {
+  color: #fff !important;
+}
+
+.text-muted {
+  color: #818a91 !important;
+}
+
+a.text-muted:focus, a.text-muted:hover {
+  color: #687077 !important;
+}
+
+.text-primary {
+  color: #0275d8 !important;
+}
+
+a.text-primary:focus, a.text-primary:hover {
+  color: #025aa5 !important;
+}
+
+.text-success {
+  color: #5cb85c !important;
+}
+
+a.text-success:focus, a.text-success:hover {
+  color: #449d44 !important;
+}
+
+.text-info {
+  color: #5bc0de !important;
+}
+
+a.text-info:focus, a.text-info:hover {
+  color: #31b0d5 !important;
+}
+
+.text-warning {
+  color: #f0ad4e !important;
+}
+
+a.text-warning:focus, a.text-warning:hover {
+  color: #ec971f !important;
+}
+
+.text-danger {
+  color: #d9534f !important;
+}
+
+a.text-danger:focus, a.text-danger:hover {
+  color: #c9302c !important;
+}
+
+.text-gray-dark {
+  color: #373a3c !important;
+}
+
+a.text-gray-dark:focus, a.text-gray-dark:hover {
+  color: #1f2021 !important;
+}
+
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.invisible {
+  visibility: hidden !important;
+}
+
+.hidden-xs-up {
+  display: none !important;
+}
+
+@media (max-width: 575px) {
+  .hidden-xs-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 576px) {
+  .hidden-sm-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-sm-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .hidden-md-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 991px) {
+  .hidden-md-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .hidden-lg-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 1199px) {
+  .hidden-lg-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .hidden-xl-up {
+    display: none !important;
+  }
+}
+
+.hidden-xl-down {
+  display: none !important;
+}
+
+.visible-print-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+
+.visible-print-inline {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+
+.visible-print-inline-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
new file mode 100644
index 0000000..256be60
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_custom.scss","../../scss/_tobago.scss","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_hover.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
new file mode 100644
index 0000000..16e36a1
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.tobago-box-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center}.tobago-button>img{margin-top:-1px;margin-bottom:-1px}.tobago-collapsed.tobago-box .card-block,.tobago-collapsed.tobago-panel,.tobago-collapsed.tobago-section .tobago-section-content{display:none}.tobago-d [...]
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
new file mode 100644
index 0000000..12af8fc
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/_tobago.scss","dist/css/bootstrap.css","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_cle [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.js b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.js
new file mode 100644
index 0000000..0a37e60
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.js
@@ -0,0 +1,3430 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+if (typeof jQuery === 'undefined') {
+  throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+  var version = $.fn.jquery.split(' ')[0].split('.')
+  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {
+    throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
+  }
+}(jQuery);
+
+
++function () {
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) [...]
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): util.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Util = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Private TransitionEnd Helpers
+   * ------------------------------------------------------------------------
+   */
+
+  var transition = false;
+
+  var MAX_UID = 1000000;
+
+  var TransitionEndEvent = {
+    WebkitTransition: 'webkitTransitionEnd',
+    MozTransition: 'transitionend',
+    OTransition: 'oTransitionEnd otransitionend',
+    transition: 'transitionend'
+  };
+
+  // shoutout AngusCroll (https://goo.gl/pxwQGp)
+  function toType(obj) {
+    return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
+  }
+
+  function isElement(obj) {
+    return (obj[0] || obj).nodeType;
+  }
+
+  function getSpecialTransitionEndEvent() {
+    return {
+      bindType: transition.end,
+      delegateType: transition.end,
+      handle: function handle(event) {
+        if ($(event.target).is(this)) {
+          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
+        }
+        return undefined;
+      }
+    };
+  }
+
+  function transitionEndTest() {
+    if (window.QUnit) {
+      return false;
+    }
+
+    var el = document.createElement('bootstrap');
+
+    for (var name in TransitionEndEvent) {
+      if (el.style[name] !== undefined) {
+        return { end: TransitionEndEvent[name] };
+      }
+    }
+
+    return false;
+  }
+
+  function transitionEndEmulator(duration) {
+    var _this = this;
+
+    var called = false;
+
+    $(this).one(Util.TRANSITION_END, function () {
+      called = true;
+    });
+
+    setTimeout(function () {
+      if (!called) {
+        Util.triggerTransitionEnd(_this);
+      }
+    }, duration);
+
+    return this;
+  }
+
+  function setTransitionEndSupport() {
+    transition = transitionEndTest();
+
+    $.fn.emulateTransitionEnd = transitionEndEmulator;
+
+    if (Util.supportsTransitionEnd()) {
+      $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
+    }
+  }
+
+  /**
+   * --------------------------------------------------------------------------
+   * Public Util Api
+   * --------------------------------------------------------------------------
+   */
+
+  var Util = {
+
+    TRANSITION_END: 'bsTransitionEnd',
+
+    getUID: function getUID(prefix) {
+      do {
+        /* eslint-disable no-bitwise */
+        prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
+        /* eslint-enable no-bitwise */
+      } while (document.getElementById(prefix));
+      return prefix;
+    },
+    getSelectorFromElement: function getSelectorFromElement(element) {
+      var selector = element.getAttribute('data-target');
+
+      if (!selector) {
+        selector = element.getAttribute('href') || '';
+        selector = /^#[a-z]/i.test(selector) ? selector : null;
+      }
+
+      return selector;
+    },
+    reflow: function reflow(element) {
+      new Function('bs', 'return bs')(element.offsetHeight);
+    },
+    triggerTransitionEnd: function triggerTransitionEnd(element) {
+      $(element).trigger(transition.end);
+    },
+    supportsTransitionEnd: function supportsTransitionEnd() {
+      return Boolean(transition);
+    },
+    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
+      for (var property in configTypes) {
+        if (configTypes.hasOwnProperty(property)) {
+          var expectedTypes = configTypes[property];
+          var value = config[property];
+          var valueType = void 0;
+
+          if (value && isElement(value)) {
+            valueType = 'element';
+          } else {
+            valueType = toType(value);
+          }
+
+          if (!new RegExp(expectedTypes).test(valueType)) {
+            throw new Error(componentName.toUpperCase() + ': ' + ('Option "' + property + '" provided type "' + valueType + '" ') + ('but expected type "' + expectedTypes + '".'));
+          }
+        }
+      }
+    }
+  };
+
+  setTransitionEndSupport();
+
+  return Util;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): alert.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Alert = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'alert';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.alert';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Selector = {
+    DISMISS: '[data-dismiss="alert"]'
+  };
+
+  var Event = {
+    CLOSE: 'close' + EVENT_KEY,
+    CLOSED: 'closed' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    ALERT: 'alert',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Alert = function () {
+    function Alert(element) {
+      _classCallCheck(this, Alert);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Alert.prototype.close = function close(element) {
+      element = element || this._element;
+
+      var rootElement = this._getRootElement(element);
+      var customEvent = this._triggerCloseEvent(rootElement);
+
+      if (customEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._removeElement(rootElement);
+    };
+
+    Alert.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Alert.prototype._getRootElement = function _getRootElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      var parent = false;
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      if (!parent) {
+        parent = $(element).closest('.' + ClassName.ALERT)[0];
+      }
+
+      return parent;
+    };
+
+    Alert.prototype._triggerCloseEvent = function _triggerCloseEvent(element) {
+      var closeEvent = $.Event(Event.CLOSE);
+
+      $(element).trigger(closeEvent);
+      return closeEvent;
+    };
+
+    Alert.prototype._removeElement = function _removeElement(element) {
+      $(element).removeClass(ClassName.IN);
+
+      if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {
+        this._destroyElement(element);
+        return;
+      }
+
+      $(element).one(Util.TRANSITION_END, $.proxy(this._destroyElement, this, element)).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Alert.prototype._destroyElement = function _destroyElement(element) {
+      $(element).detach().trigger(Event.CLOSED).remove();
+    };
+
+    // static
+
+    Alert._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $element = $(this);
+        var data = $element.data(DATA_KEY);
+
+        if (!data) {
+          data = new Alert(this);
+          $element.data(DATA_KEY, data);
+        }
+
+        if (config === 'close') {
+          data[config](this);
+        }
+      });
+    };
+
+    Alert._handleDismiss = function _handleDismiss(alertInstance) {
+      return function (event) {
+        if (event) {
+          event.preventDefault();
+        }
+
+        alertInstance.close(this);
+      };
+    };
+
+    _createClass(Alert, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Alert;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Alert._jQueryInterface;
+  $.fn[NAME].Constructor = Alert;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Alert._jQueryInterface;
+  };
+
+  return Alert;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): button.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Button = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'button';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.button';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var ClassName = {
+    ACTIVE: 'active',
+    BUTTON: 'btn',
+    FOCUS: 'focus'
+  };
+
+  var Selector = {
+    DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
+    DATA_TOGGLE: '[data-toggle="buttons"]',
+    INPUT: 'input',
+    ACTIVE: '.active',
+    BUTTON: '.btn'
+  };
+
+  var Event = {
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    FOCUS_BLUR_DATA_API: 'focus' + EVENT_KEY + DATA_API_KEY + ' ' + ('blur' + EVENT_KEY + DATA_API_KEY)
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Button = function () {
+    function Button(element) {
+      _classCallCheck(this, Button);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Button.prototype.toggle = function toggle() {
+      var triggerChangeEvent = true;
+      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];
+
+      if (rootElement) {
+        var input = $(this._element).find(Selector.INPUT)[0];
+
+        if (input) {
+          if (input.type === 'radio') {
+            if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) {
+              triggerChangeEvent = false;
+            } else {
+              var activeElement = $(rootElement).find(Selector.ACTIVE)[0];
+
+              if (activeElement) {
+                $(activeElement).removeClass(ClassName.ACTIVE);
+              }
+            }
+          }
+
+          if (triggerChangeEvent) {
+            input.checked = !$(this._element).hasClass(ClassName.ACTIVE);
+            $(this._element).trigger('change');
+          }
+
+          input.focus();
+        }
+      } else {
+        this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));
+      }
+
+      if (triggerChangeEvent) {
+        $(this._element).toggleClass(ClassName.ACTIVE);
+      }
+    };
+
+    Button.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // static
+
+    Button._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          data = new Button(this);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (config === 'toggle') {
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Button, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Button;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    event.preventDefault();
+
+    var button = event.target;
+
+    if (!$(button).hasClass(ClassName.BUTTON)) {
+      button = $(button).closest(Selector.BUTTON);
+    }
+
+    Button._jQueryInterface.call($(button), 'toggle');
+  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    var button = $(event.target).closest(Selector.BUTTON)[0];
+    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Button._jQueryInterface;
+  $.fn[NAME].Constructor = Button;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Button._jQueryInterface;
+  };
+
+  return Button;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): carousel.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Carousel = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'carousel';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.carousel';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
+  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
+
+  var Default = {
+    interval: 5000,
+    keyboard: true,
+    slide: false,
+    pause: 'hover',
+    wrap: true
+  };
+
+  var DefaultType = {
+    interval: '(number|boolean)',
+    keyboard: 'boolean',
+    slide: '(boolean|string)',
+    pause: '(string|boolean)',
+    wrap: 'boolean'
+  };
+
+  var Direction = {
+    NEXT: 'next',
+    PREVIOUS: 'prev'
+  };
+
+  var Event = {
+    SLIDE: 'slide' + EVENT_KEY,
+    SLID: 'slid' + EVENT_KEY,
+    KEYDOWN: 'keydown' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    CAROUSEL: 'carousel',
+    ACTIVE: 'active',
+    SLIDE: 'slide',
+    RIGHT: 'right',
+    LEFT: 'left',
+    ITEM: 'carousel-item'
+  };
+
+  var Selector = {
+    ACTIVE: '.active',
+    ACTIVE_ITEM: '.active.carousel-item',
+    ITEM: '.carousel-item',
+    NEXT_PREV: '.next, .prev',
+    INDICATORS: '.carousel-indicators',
+    DATA_SLIDE: '[data-slide], [data-slide-to]',
+    DATA_RIDE: '[data-ride="carousel"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Carousel = function () {
+    function Carousel(element, config) {
+      _classCallCheck(this, Carousel);
+
+      this._items = null;
+      this._interval = null;
+      this._activeElement = null;
+
+      this._isPaused = false;
+      this._isSliding = false;
+
+      this._config = this._getConfig(config);
+      this._element = $(element)[0];
+      this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Carousel.prototype.next = function next() {
+      if (!this._isSliding) {
+        this._slide(Direction.NEXT);
+      }
+    };
+
+    Carousel.prototype.nextWhenVisible = function nextWhenVisible() {
+      // Don't call next when the page isn't visible
+      if (!document.hidden) {
+        this.next();
+      }
+    };
+
+    Carousel.prototype.prev = function prev() {
+      if (!this._isSliding) {
+        this._slide(Direction.PREVIOUS);
+      }
+    };
+
+    Carousel.prototype.pause = function pause(event) {
+      if (!event) {
+        this._isPaused = true;
+      }
+
+      if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {
+        Util.triggerTransitionEnd(this._element);
+        this.cycle(true);
+      }
+
+      clearInterval(this._interval);
+      this._interval = null;
+    };
+
+    Carousel.prototype.cycle = function cycle(event) {
+      if (!event) {
+        this._isPaused = false;
+      }
+
+      if (this._interval) {
+        clearInterval(this._interval);
+        this._interval = null;
+      }
+
+      if (this._config.interval && !this._isPaused) {
+        this._interval = setInterval($.proxy(document.visibilityState ? this.nextWhenVisible : this.next, this), this._config.interval);
+      }
+    };
+
+    Carousel.prototype.to = function to(index) {
+      var _this2 = this;
+
+      this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+
+      var activeIndex = this._getItemIndex(this._activeElement);
+
+      if (index > this._items.length - 1 || index < 0) {
+        return;
+      }
+
+      if (this._isSliding) {
+        $(this._element).one(Event.SLID, function () {
+          return _this2.to(index);
+        });
+        return;
+      }
+
+      if (activeIndex === index) {
+        this.pause();
+        this.cycle();
+        return;
+      }
+
+      var direction = index > activeIndex ? Direction.NEXT : Direction.PREVIOUS;
+
+      this._slide(direction, this._items[index]);
+    };
+
+    Carousel.prototype.dispose = function dispose() {
+      $(this._element).off(EVENT_KEY);
+      $.removeData(this._element, DATA_KEY);
+
+      this._items = null;
+      this._config = null;
+      this._element = null;
+      this._interval = null;
+      this._isPaused = null;
+      this._isSliding = null;
+      this._activeElement = null;
+      this._indicatorsElement = null;
+    };
+
+    // private
+
+    Carousel.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Carousel.prototype._addEventListeners = function _addEventListeners() {
+      if (this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN, $.proxy(this._keydown, this));
+      }
+
+      if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
+        $(this._element).on(Event.MOUSEENTER, $.proxy(this.pause, this)).on(Event.MOUSELEAVE, $.proxy(this.cycle, this));
+      }
+    };
+
+    Carousel.prototype._keydown = function _keydown(event) {
+      event.preventDefault();
+
+      if (/input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      switch (event.which) {
+        case ARROW_LEFT_KEYCODE:
+          this.prev();
+          break;
+        case ARROW_RIGHT_KEYCODE:
+          this.next();
+          break;
+        default:
+          return;
+      }
+    };
+
+    Carousel.prototype._getItemIndex = function _getItemIndex(element) {
+      this._items = $.makeArray($(element).parent().find(Selector.ITEM));
+      return this._items.indexOf(element);
+    };
+
+    Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) {
+      var isNextDirection = direction === Direction.NEXT;
+      var isPrevDirection = direction === Direction.PREVIOUS;
+      var activeIndex = this._getItemIndex(activeElement);
+      var lastItemIndex = this._items.length - 1;
+      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
+
+      if (isGoingToWrap && !this._config.wrap) {
+        return activeElement;
+      }
+
+      var delta = direction === Direction.PREVIOUS ? -1 : 1;
+      var itemIndex = (activeIndex + delta) % this._items.length;
+
+      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
+    };
+
+    Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, directionalClassname) {
+      var slideEvent = $.Event(Event.SLIDE, {
+        relatedTarget: relatedTarget,
+        direction: directionalClassname
+      });
+
+      $(this._element).trigger(slideEvent);
+
+      return slideEvent;
+    };
+
+    Carousel.prototype._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
+      if (this._indicatorsElement) {
+        $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+
+        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
+
+        if (nextIndicator) {
+          $(nextIndicator).addClass(ClassName.ACTIVE);
+        }
+      }
+    };
+
+    Carousel.prototype._slide = function _slide(direction, element) {
+      var _this3 = this;
+
+      var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
+
+      var isCycling = Boolean(this._interval);
+
+      var directionalClassName = direction === Direction.NEXT ? ClassName.LEFT : ClassName.RIGHT;
+
+      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {
+        this._isSliding = false;
+        return;
+      }
+
+      var slideEvent = this._triggerSlideEvent(nextElement, directionalClassName);
+      if (slideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (!activeElement || !nextElement) {
+        // some weirdness is happening, so we bail
+        return;
+      }
+
+      this._isSliding = true;
+
+      if (isCycling) {
+        this.pause();
+      }
+
+      this._setActiveIndicatorElement(nextElement);
+
+      var slidEvent = $.Event(Event.SLID, {
+        relatedTarget: nextElement,
+        direction: directionalClassName
+      });
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {
+
+        $(nextElement).addClass(direction);
+
+        Util.reflow(nextElement);
+
+        $(activeElement).addClass(directionalClassName);
+        $(nextElement).addClass(directionalClassName);
+
+        $(activeElement).one(Util.TRANSITION_END, function () {
+          $(nextElement).removeClass(directionalClassName).removeClass(direction);
+
+          $(nextElement).addClass(ClassName.ACTIVE);
+
+          $(activeElement).removeClass(ClassName.ACTIVE).removeClass(direction).removeClass(directionalClassName);
+
+          _this3._isSliding = false;
+
+          setTimeout(function () {
+            return $(_this3._element).trigger(slidEvent);
+          }, 0);
+        }).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        $(activeElement).removeClass(ClassName.ACTIVE);
+        $(nextElement).addClass(ClassName.ACTIVE);
+
+        this._isSliding = false;
+        $(this._element).trigger(slidEvent);
+      }
+
+      if (isCycling) {
+        this.cycle();
+      }
+    };
+
+    // static
+
+    Carousel._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Default, $(this).data());
+
+        if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
+          $.extend(_config, config);
+        }
+
+        var action = typeof config === 'string' ? config : _config.slide;
+
+        if (!data) {
+          data = new Carousel(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'number') {
+          data.to(config);
+        } else if (typeof action === 'string') {
+          if (data[action] === undefined) {
+            throw new Error('No method named "' + action + '"');
+          }
+          data[action]();
+        } else if (_config.interval) {
+          data.pause();
+          data.cycle();
+        }
+      });
+    };
+
+    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
+      var selector = Util.getSelectorFromElement(this);
+
+      if (!selector) {
+        return;
+      }
+
+      var target = $(selector)[0];
+
+      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {
+        return;
+      }
+
+      var config = $.extend({}, $(target).data(), $(this).data());
+      var slideIndex = this.getAttribute('data-slide-to');
+
+      if (slideIndex) {
+        config.interval = false;
+      }
+
+      Carousel._jQueryInterface.call($(target), config);
+
+      if (slideIndex) {
+        $(target).data(DATA_KEY).to(slideIndex);
+      }
+
+      event.preventDefault();
+    };
+
+    _createClass(Carousel, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Carousel;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    $(Selector.DATA_RIDE).each(function () {
+      var $carousel = $(this);
+      Carousel._jQueryInterface.call($carousel, $carousel.data());
+    });
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Carousel._jQueryInterface;
+  $.fn[NAME].Constructor = Carousel;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Carousel._jQueryInterface;
+  };
+
+  return Carousel;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): collapse.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Collapse = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'collapse';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.collapse';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+
+  var Default = {
+    toggle: true,
+    parent: ''
+  };
+
+  var DefaultType = {
+    toggle: 'boolean',
+    parent: 'string'
+  };
+
+  var Event = {
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    IN: 'in',
+    COLLAPSE: 'collapse',
+    COLLAPSING: 'collapsing',
+    COLLAPSED: 'collapsed'
+  };
+
+  var Dimension = {
+    WIDTH: 'width',
+    HEIGHT: 'height'
+  };
+
+  var Selector = {
+    ACTIVES: '.card > .in, .card > .collapsing',
+    DATA_TOGGLE: '[data-toggle="collapse"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Collapse = function () {
+    function Collapse(element, config) {
+      _classCallCheck(this, Collapse);
+
+      this._isTransitioning = false;
+      this._element = element;
+      this._config = this._getConfig(config);
+      this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
+
+      this._parent = this._config.parent ? this._getParent() : null;
+
+      if (!this._config.parent) {
+        this._addAriaAndCollapsedClass(this._element, this._triggerArray);
+      }
+
+      if (this._config.toggle) {
+        this.toggle();
+      }
+    }
+
+    // getters
+
+    // public
+
+    Collapse.prototype.toggle = function toggle() {
+      if ($(this._element).hasClass(ClassName.IN)) {
+        this.hide();
+      } else {
+        this.show();
+      }
+    };
+
+    Collapse.prototype.show = function show() {
+      var _this4 = this;
+
+      if (this._isTransitioning || $(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var actives = void 0;
+      var activesData = void 0;
+
+      if (this._parent) {
+        actives = $.makeArray($(Selector.ACTIVES));
+        if (!actives.length) {
+          actives = null;
+        }
+      }
+
+      if (actives) {
+        activesData = $(actives).data(DATA_KEY);
+        if (activesData && activesData._isTransitioning) {
+          return;
+        }
+      }
+
+      var startEvent = $.Event(Event.SHOW);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (actives) {
+        Collapse._jQueryInterface.call($(actives), 'hide');
+        if (!activesData) {
+          $(actives).data(DATA_KEY, null);
+        }
+      }
+
+      var dimension = this._getDimension();
+
+      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
+
+      this._element.style[dimension] = 0;
+      this._element.setAttribute('aria-expanded', true);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        $(_this4._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.IN);
+
+        _this4._element.style[dimension] = '';
+
+        _this4.setTransitioning(false);
+
+        $(_this4._element).trigger(Event.SHOWN);
+      };
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
+      var scrollSize = 'scroll' + capitalizedDimension;
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+
+      this._element.style[dimension] = this._element[scrollSize] + 'px';
+    };
+
+    Collapse.prototype.hide = function hide() {
+      var _this5 = this;
+
+      if (this._isTransitioning || !$(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var startEvent = $.Event(Event.HIDE);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      var dimension = this._getDimension();
+      var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight';
+
+      this._element.style[dimension] = this._element[offsetDimension] + 'px';
+
+      Util.reflow(this._element);
+
+      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.IN);
+
+      this._element.setAttribute('aria-expanded', false);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        _this5.setTransitioning(false);
+        $(_this5._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
+      };
+
+      this._element.style[dimension] = '';
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Collapse.prototype.setTransitioning = function setTransitioning(isTransitioning) {
+      this._isTransitioning = isTransitioning;
+    };
+
+    Collapse.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      this._config = null;
+      this._parent = null;
+      this._element = null;
+      this._triggerArray = null;
+      this._isTransitioning = null;
+    };
+
+    // private
+
+    Collapse.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      config.toggle = Boolean(config.toggle); // coerce string values
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Collapse.prototype._getDimension = function _getDimension() {
+      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);
+      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
+    };
+
+    Collapse.prototype._getParent = function _getParent() {
+      var _this6 = this;
+
+      var parent = $(this._config.parent)[0];
+      var selector = '[data-toggle="collapse"][data-parent="' + this._config.parent + '"]';
+
+      $(parent).find(selector).each(function (i, element) {
+        _this6._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
+      });
+
+      return parent;
+    };
+
+    Collapse.prototype._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
+      if (element) {
+        var isOpen = $(element).hasClass(ClassName.IN);
+        element.setAttribute('aria-expanded', isOpen);
+
+        if (triggerArray.length) {
+          $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
+        }
+      }
+    };
+
+    // static
+
+    Collapse._getTargetFromElement = function _getTargetFromElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      return selector ? $(selector)[0] : null;
+    };
+
+    Collapse._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+        var _config = $.extend({}, Default, $this.data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data && _config.toggle && /show|hide/.test(config)) {
+          _config.toggle = false;
+        }
+
+        if (!data) {
+          data = new Collapse(this, _config);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Collapse, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Collapse;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+
+    var target = Collapse._getTargetFromElement(this);
+    var data = $(target).data(DATA_KEY);
+    var config = data ? 'toggle' : $(this).data();
+
+    Collapse._jQueryInterface.call($(target), config);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Collapse._jQueryInterface;
+  $.fn[NAME].Constructor = Collapse;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Collapse._jQueryInterface;
+  };
+
+  return Collapse;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): dropdown.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Dropdown = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'dropdown';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.dropdown';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
+  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
+  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    BACKDROP: 'dropdown-backdrop',
+    DISABLED: 'disabled',
+    OPEN: 'open'
+  };
+
+  var Selector = {
+    BACKDROP: '.dropdown-backdrop',
+    DATA_TOGGLE: '[data-toggle="dropdown"]',
+    FORM_CHILD: '.dropdown form',
+    ROLE_MENU: '[role="menu"]',
+    ROLE_LISTBOX: '[role="listbox"]',
+    NAVBAR_NAV: '.navbar-nav',
+    VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Dropdown = function () {
+    function Dropdown(element) {
+      _classCallCheck(this, Dropdown);
+
+      this._element = element;
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Dropdown.prototype.toggle = function toggle() {
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return false;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      Dropdown._clearMenus();
+
+      if (isActive) {
+        return false;
+      }
+
+      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
+
+        // if mobile we use a backdrop because click events don't delegate
+        var dropdown = document.createElement('div');
+        dropdown.className = ClassName.BACKDROP;
+        $(dropdown).insertBefore(this);
+        $(dropdown).on('click', Dropdown._clearMenus);
+      }
+
+      var relatedTarget = { relatedTarget: this };
+      var showEvent = $.Event(Event.SHOW, relatedTarget);
+
+      $(parent).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented()) {
+        return false;
+      }
+
+      this.focus();
+      this.setAttribute('aria-expanded', 'true');
+
+      $(parent).toggleClass(ClassName.OPEN);
+      $(parent).trigger($.Event(Event.SHOWN, relatedTarget));
+
+      return false;
+    };
+
+    Dropdown.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._element).off(EVENT_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Dropdown.prototype._addEventListeners = function _addEventListeners() {
+      $(this._element).on(Event.CLICK, this.toggle);
+    };
+
+    // static
+
+    Dropdown._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          $(this).data(DATA_KEY, data = new Dropdown(this));
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config].call(this);
+        }
+      });
+    };
+
+    Dropdown._clearMenus = function _clearMenus(event) {
+      if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
+        return;
+      }
+
+      var backdrop = $(Selector.BACKDROP)[0];
+      if (backdrop) {
+        backdrop.parentNode.removeChild(backdrop);
+      }
+
+      var toggles = $.makeArray($(Selector.DATA_TOGGLE));
+
+      for (var i = 0; i < toggles.length; i++) {
+        var parent = Dropdown._getParentFromElement(toggles[i]);
+        var relatedTarget = { relatedTarget: toggles[i] };
+
+        if (!$(parent).hasClass(ClassName.OPEN)) {
+          continue;
+        }
+
+        if (event && event.type === 'click' && /input|textarea/i.test(event.target.tagName) && $.contains(parent, event.target)) {
+          continue;
+        }
+
+        var hideEvent = $.Event(Event.HIDE, relatedTarget);
+        $(parent).trigger(hideEvent);
+        if (hideEvent.isDefaultPrevented()) {
+          continue;
+        }
+
+        toggles[i].setAttribute('aria-expanded', 'false');
+
+        $(parent).removeClass(ClassName.OPEN).trigger($.Event(Event.HIDDEN, relatedTarget));
+      }
+    };
+
+    Dropdown._getParentFromElement = function _getParentFromElement(element) {
+      var parent = void 0;
+      var selector = Util.getSelectorFromElement(element);
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      return parent || element.parentNode;
+    };
+
+    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
+      if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      event.preventDefault();
+      event.stopPropagation();
+
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {
+
+        if (event.which === ESCAPE_KEYCODE) {
+          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
+          $(toggle).trigger('focus');
+        }
+
+        $(this).trigger('click');
+        return;
+      }
+
+      var items = $.makeArray($(Selector.VISIBLE_ITEMS));
+
+      items = items.filter(function (item) {
+        return item.offsetWidth || item.offsetHeight;
+      });
+
+      if (!items.length) {
+        return;
+      }
+
+      var index = items.indexOf(event.target);
+
+      if (event.which === ARROW_UP_KEYCODE && index > 0) {
+        // up
+        index--;
+      }
+
+      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
+        // down
+        index++;
+      }
+
+      if (index < 0) {
+        index = 0;
+      }
+
+      items[index].focus();
+    };
+
+    _createClass(Dropdown, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Dropdown;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
+    e.stopPropagation();
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Dropdown._jQueryInterface;
+  $.fn[NAME].Constructor = Dropdown;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Dropdown._jQueryInterface;
+  };
+
+  return Dropdown;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): modal.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Modal = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'modal';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.modal';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 300;
+  var BACKDROP_TRANSITION_DURATION = 150;
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+
+  var Default = {
+    backdrop: true,
+    keyboard: true,
+    focus: true,
+    show: true
+  };
+
+  var DefaultType = {
+    backdrop: '(boolean|string)',
+    keyboard: 'boolean',
+    focus: 'boolean',
+    show: 'boolean'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    RESIZE: 'resize' + EVENT_KEY,
+    CLICK_DISMISS: 'click.dismiss' + EVENT_KEY,
+    KEYDOWN_DISMISS: 'keydown.dismiss' + EVENT_KEY,
+    MOUSEUP_DISMISS: 'mouseup.dismiss' + EVENT_KEY,
+    MOUSEDOWN_DISMISS: 'mousedown.dismiss' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
+    BACKDROP: 'modal-backdrop',
+    OPEN: 'modal-open',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    DIALOG: '.modal-dialog',
+    DATA_TOGGLE: '[data-toggle="modal"]',
+    DATA_DISMISS: '[data-dismiss="modal"]',
+    FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Modal = function () {
+    function Modal(element, config) {
+      _classCallCheck(this, Modal);
+
+      this._config = this._getConfig(config);
+      this._element = element;
+      this._dialog = $(element).find(Selector.DIALOG)[0];
+      this._backdrop = null;
+      this._isShown = false;
+      this._isBodyOverflowing = false;
+      this._ignoreBackdropClick = false;
+      this._originalBodyPadding = 0;
+      this._scrollbarWidth = 0;
+    }
+
+    // getters
+
+    // public
+
+    Modal.prototype.toggle = function toggle(relatedTarget) {
+      return this._isShown ? this.hide() : this.show(relatedTarget);
+    };
+
+    Modal.prototype.show = function show(relatedTarget) {
+      var _this7 = this;
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: relatedTarget
+      });
+
+      $(this._element).trigger(showEvent);
+
+      if (this._isShown || showEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = true;
+
+      this._checkScrollbar();
+      this._setScrollbar();
+
+      $(document.body).addClass(ClassName.OPEN);
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, $.proxy(this.hide, this));
+
+      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
+        $(_this7._element).one(Event.MOUSEUP_DISMISS, function (event) {
+          if ($(event.target).is(_this7._element)) {
+            _this7._ignoreBackdropClick = true;
+          }
+        });
+      });
+
+      this._showBackdrop($.proxy(this._showElement, this, relatedTarget));
+    };
+
+    Modal.prototype.hide = function hide(event) {
+      if (event) {
+        event.preventDefault();
+      }
+
+      var hideEvent = $.Event(Event.HIDE);
+
+      $(this._element).trigger(hideEvent);
+
+      if (!this._isShown || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = false;
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(document).off(Event.FOCUSIN);
+
+      $(this._element).removeClass(ClassName.IN);
+
+      $(this._element).off(Event.CLICK_DISMISS);
+      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+
+        $(this._element).one(Util.TRANSITION_END, $.proxy(this._hideModal, this)).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        this._hideModal();
+      }
+    };
+
+    Modal.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      $(window).off(EVENT_KEY);
+      $(document).off(EVENT_KEY);
+      $(this._element).off(EVENT_KEY);
+      $(this._backdrop).off(EVENT_KEY);
+
+      this._config = null;
+      this._element = null;
+      this._dialog = null;
+      this._backdrop = null;
+      this._isShown = null;
+      this._isBodyOverflowing = null;
+      this._ignoreBackdropClick = null;
+      this._originalBodyPadding = null;
+      this._scrollbarWidth = null;
+    };
+
+    // private
+
+    Modal.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Modal.prototype._showElement = function _showElement(relatedTarget) {
+      var _this8 = this;
+
+      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);
+
+      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
+        // don't move modals dom position
+        document.body.appendChild(this._element);
+      }
+
+      this._element.style.display = 'block';
+      this._element.removeAttribute('aria-hidden');
+      this._element.scrollTop = 0;
+
+      if (transition) {
+        Util.reflow(this._element);
+      }
+
+      $(this._element).addClass(ClassName.IN);
+
+      if (this._config.focus) {
+        this._enforceFocus();
+      }
+
+      var shownEvent = $.Event(Event.SHOWN, {
+        relatedTarget: relatedTarget
+      });
+
+      var transitionComplete = function transitionComplete() {
+        if (_this8._config.focus) {
+          _this8._element.focus();
+        }
+        $(_this8._element).trigger(shownEvent);
+      };
+
+      if (transition) {
+        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        transitionComplete();
+      }
+    };
+
+    Modal.prototype._enforceFocus = function _enforceFocus() {
+      var _this9 = this;
+
+      $(document).off(Event.FOCUSIN) // guard against infinite focus loop
+      .on(Event.FOCUSIN, function (event) {
+        if (document !== event.target && _this9._element !== event.target && !$(_this9._element).has(event.target).length) {
+          _this9._element.focus();
+        }
+      });
+    };
+
+    Modal.prototype._setEscapeEvent = function _setEscapeEvent() {
+      var _this10 = this;
+
+      if (this._isShown && this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
+          if (event.which === ESCAPE_KEYCODE) {
+            _this10.hide();
+          }
+        });
+      } else if (!this._isShown) {
+        $(this._element).off(Event.KEYDOWN_DISMISS);
+      }
+    };
+
+    Modal.prototype._setResizeEvent = function _setResizeEvent() {
+      if (this._isShown) {
+        $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this));
+      } else {
+        $(window).off(Event.RESIZE);
+      }
+    };
+
+    Modal.prototype._hideModal = function _hideModal() {
+      var _this11 = this;
+
+      this._element.style.display = 'none';
+      this._element.setAttribute('aria-hidden', 'true');
+      this._showBackdrop(function () {
+        $(document.body).removeClass(ClassName.OPEN);
+        _this11._resetAdjustments();
+        _this11._resetScrollbar();
+        $(_this11._element).trigger(Event.HIDDEN);
+      });
+    };
+
+    Modal.prototype._removeBackdrop = function _removeBackdrop() {
+      if (this._backdrop) {
+        $(this._backdrop).remove();
+        this._backdrop = null;
+      }
+    };
+
+    Modal.prototype._showBackdrop = function _showBackdrop(callback) {
+      var _this12 = this;
+
+      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
+
+      if (this._isShown && this._config.backdrop) {
+        var doAnimate = Util.supportsTransitionEnd() && animate;
+
+        this._backdrop = document.createElement('div');
+        this._backdrop.className = ClassName.BACKDROP;
+
+        if (animate) {
+          $(this._backdrop).addClass(animate);
+        }
+
+        $(this._backdrop).appendTo(document.body);
+
+        $(this._element).on(Event.CLICK_DISMISS, function (event) {
+          if (_this12._ignoreBackdropClick) {
+            _this12._ignoreBackdropClick = false;
+            return;
+          }
+          if (event.target !== event.currentTarget) {
+            return;
+          }
+          if (_this12._config.backdrop === 'static') {
+            _this12._element.focus();
+          } else {
+            _this12.hide();
+          }
+        });
+
+        if (doAnimate) {
+          Util.reflow(this._backdrop);
+        }
+
+        $(this._backdrop).addClass(ClassName.IN);
+
+        if (!callback) {
+          return;
+        }
+
+        if (!doAnimate) {
+          callback();
+          return;
+        }
+
+        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+      } else if (!this._isShown && this._backdrop) {
+        $(this._backdrop).removeClass(ClassName.IN);
+
+        var callbackRemove = function callbackRemove() {
+          _this12._removeBackdrop();
+          if (callback) {
+            callback();
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+        } else {
+          callbackRemove();
+        }
+      } else if (callback) {
+        callback();
+      }
+    };
+
+    // ----------------------------------------------------------------------
+    // the following methods are used to handle overflowing modals
+    // todo (fat): these should probably be refactored out of modal.js
+    // ----------------------------------------------------------------------
+
+    Modal.prototype._handleUpdate = function _handleUpdate() {
+      this._adjustDialog();
+    };
+
+    Modal.prototype._adjustDialog = function _adjustDialog() {
+      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+      if (!this._isBodyOverflowing && isModalOverflowing) {
+        this._element.style.paddingLeft = this._scrollbarWidth + 'px';
+      }
+
+      if (this._isBodyOverflowing && !isModalOverflowing) {
+        this._element.style.paddingRight = this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetAdjustments = function _resetAdjustments() {
+      this._element.style.paddingLeft = '';
+      this._element.style.paddingRight = '';
+    };
+
+    Modal.prototype._checkScrollbar = function _checkScrollbar() {
+      this._isBodyOverflowing = document.body.clientWidth < window.innerWidth;
+      this._scrollbarWidth = this._getScrollbarWidth();
+    };
+
+    Modal.prototype._setScrollbar = function _setScrollbar() {
+      var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10);
+
+      this._originalBodyPadding = document.body.style.paddingRight || '';
+
+      if (this._isBodyOverflowing) {
+        document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetScrollbar = function _resetScrollbar() {
+      document.body.style.paddingRight = this._originalBodyPadding;
+    };
+
+    Modal.prototype._getScrollbarWidth = function _getScrollbarWidth() {
+      // thx d.walsh
+      var scrollDiv = document.createElement('div');
+      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
+      document.body.appendChild(scrollDiv);
+      var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+      document.body.removeChild(scrollDiv);
+      return scrollbarWidth;
+    };
+
+    // static
+
+    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Modal.Default, $(this).data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data) {
+          data = new Modal(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config](relatedTarget);
+        } else if (_config.show) {
+          data.show(relatedTarget);
+        }
+      });
+    };
+
+    _createClass(Modal, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Modal;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    var _this13 = this;
+
+    var target = void 0;
+    var selector = Util.getSelectorFromElement(this);
+
+    if (selector) {
+      target = $(selector)[0];
+    }
+
+    var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data());
+
+    if (this.tagName === 'A') {
+      event.preventDefault();
+    }
+
+    var $target = $(target).one(Event.SHOW, function (showEvent) {
+      if (showEvent.isDefaultPrevented()) {
+        // only register focus restorer if modal will actually get shown
+        return;
+      }
+
+      $target.one(Event.HIDDEN, function () {
+        if ($(_this13).is(':visible')) {
+          _this13.focus();
+        }
+      });
+    });
+
+    Modal._jQueryInterface.call($(target), config, this);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Modal._jQueryInterface;
+  $.fn[NAME].Constructor = Modal;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Modal._jQueryInterface;
+  };
+
+  return Modal;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): scrollspy.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var ScrollSpy = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'scrollspy';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.scrollspy';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = {
+    offset: 10,
+    method: 'auto',
+    target: ''
+  };
+
+  var DefaultType = {
+    offset: 'number',
+    method: 'string',
+    target: '(string|element)'
+  };
+
+  var Event = {
+    ACTIVATE: 'activate' + EVENT_KEY,
+    SCROLL: 'scroll' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_ITEM: 'dropdown-item',
+    DROPDOWN_MENU: 'dropdown-menu',
+    NAV_LINK: 'nav-link',
+    NAV: 'nav',
+    ACTIVE: 'active'
+  };
+
+  var Selector = {
+    DATA_SPY: '[data-spy="scroll"]',
+    ACTIVE: '.active',
+    LIST_ITEM: '.list-item',
+    LI: 'li',
+    LI_DROPDOWN: 'li.dropdown',
+    NAV_LINKS: '.nav-link',
+    DROPDOWN: '.dropdown',
+    DROPDOWN_ITEMS: '.dropdown-item',
+    DROPDOWN_TOGGLE: '.dropdown-toggle'
+  };
+
+  var OffsetMethod = {
+    OFFSET: 'offset',
+    POSITION: 'position'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var ScrollSpy = function () {
+    function ScrollSpy(element, config) {
+      _classCallCheck(this, ScrollSpy);
+
+      this._element = element;
+      this._scrollElement = element.tagName === 'BODY' ? window : element;
+      this._config = this._getConfig(config);
+      this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
+      this._offsets = [];
+      this._targets = [];
+      this._activeTarget = null;
+      this._scrollHeight = 0;
+
+      $(this._scrollElement).on(Event.SCROLL, $.proxy(this._process, this));
+
+      this.refresh();
+      this._process();
+    }
+
+    // getters
+
+    // public
+
+    ScrollSpy.prototype.refresh = function refresh() {
+      var _this14 = this;
+
+      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
+
+      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
+
+      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
+
+      this._offsets = [];
+      this._targets = [];
+
+      this._scrollHeight = this._getScrollHeight();
+
+      var targets = $.makeArray($(this._selector));
+
+      targets.map(function (element) {
+        var target = void 0;
+        var targetSelector = Util.getSelectorFromElement(element);
+
+        if (targetSelector) {
+          target = $(targetSelector)[0];
+        }
+
+        if (target && (target.offsetWidth || target.offsetHeight)) {
+          // todo (fat): remove sketch reliance on jQuery position/offset
+          return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
+        }
+        return null;
+      }).filter(function (item) {
+        return item;
+      }).sort(function (a, b) {
+        return a[0] - b[0];
+      }).forEach(function (item) {
+        _this14._offsets.push(item[0]);
+        _this14._targets.push(item[1]);
+      });
+    };
+
+    ScrollSpy.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._scrollElement).off(EVENT_KEY);
+
+      this._element = null;
+      this._scrollElement = null;
+      this._config = null;
+      this._selector = null;
+      this._offsets = null;
+      this._targets = null;
+      this._activeTarget = null;
+      this._scrollHeight = null;
+    };
+
+    // private
+
+    ScrollSpy.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+
+      if (typeof config.target !== 'string') {
+        var id = $(config.target).attr('id');
+        if (!id) {
+          id = Util.getUID(NAME);
+          $(config.target).attr('id', id);
+        }
+        config.target = '#' + id;
+      }
+
+      Util.typeCheckConfig(NAME, config, DefaultType);
+
+      return config;
+    };
+
+    ScrollSpy.prototype._getScrollTop = function _getScrollTop() {
+      return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
+    };
+
+    ScrollSpy.prototype._getScrollHeight = function _getScrollHeight() {
+      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
+    };
+
+    ScrollSpy.prototype._process = function _process() {
+      var scrollTop = this._getScrollTop() + this._config.offset;
+      var scrollHeight = this._getScrollHeight();
+      var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight;
+
+      if (this._scrollHeight !== scrollHeight) {
+        this.refresh();
+      }
+
+      if (scrollTop >= maxScroll) {
+        var target = this._targets[this._targets.length - 1];
+
+        if (this._activeTarget !== target) {
+          this._activate(target);
+        }
+      }
+
+      if (this._activeTarget && scrollTop < this._offsets[0]) {
+        this._activeTarget = null;
+        this._clear();
+        return;
+      }
+
+      for (var i = this._offsets.length; i--;) {
+        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (this._offsets[i + 1] === undefined || scrollTop < this._offsets[i + 1]);
+
+        if (isActiveTarget) {
+          this._activate(this._targets[i]);
+        }
+      }
+    };
+
+    ScrollSpy.prototype._activate = function _activate(target) {
+      this._activeTarget = target;
+
+      this._clear();
+
+      var queries = this._selector.split(',');
+      queries = queries.map(function (selector) {
+        return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
+      });
+
+      var $link = $(queries.join(','));
+
+      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
+        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        $link.addClass(ClassName.ACTIVE);
+      } else {
+        // todo (fat) this is kinda sus...
+        // recursively add actives to tested nav-links
+        $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
+      }
+
+      $(this._scrollElement).trigger(Event.ACTIVATE, {
+        relatedTarget: target
+      });
+    };
+
+    ScrollSpy.prototype._clear = function _clear() {
+      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+    };
+
+    // static
+
+    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config || null;
+
+        if (!data) {
+          data = new ScrollSpy(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(ScrollSpy, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return ScrollSpy;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    var scrollSpys = $.makeArray($(Selector.DATA_SPY));
+
+    for (var i = scrollSpys.length; i--;) {
+      var $spy = $(scrollSpys[i]);
+      ScrollSpy._jQueryInterface.call($spy, $spy.data());
+    }
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = ScrollSpy._jQueryInterface;
+  $.fn[NAME].Constructor = ScrollSpy;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return ScrollSpy._jQueryInterface;
+  };
+
+  return ScrollSpy;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tab.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tab = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tab';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tab';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_MENU: 'dropdown-menu',
+    ACTIVE: 'active',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    A: 'a',
+    LI: 'li',
+    DROPDOWN: '.dropdown',
+    UL: 'ul:not(.dropdown-menu)',
+    FADE_CHILD: '> .nav-item .fade, > .fade',
+    ACTIVE: '.active',
+    ACTIVE_CHILD: '> .nav-item > .active, > .active',
+    DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"]',
+    DROPDOWN_TOGGLE: '.dropdown-toggle',
+    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tab = function () {
+    function Tab(element) {
+      _classCallCheck(this, Tab);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Tab.prototype.show = function show() {
+      var _this15 = this;
+
+      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE)) {
+        return;
+      }
+
+      var target = void 0;
+      var previous = void 0;
+      var ulElement = $(this._element).closest(Selector.UL)[0];
+      var selector = Util.getSelectorFromElement(this._element);
+
+      if (ulElement) {
+        previous = $.makeArray($(ulElement).find(Selector.ACTIVE));
+        previous = previous[previous.length - 1];
+      }
+
+      var hideEvent = $.Event(Event.HIDE, {
+        relatedTarget: this._element
+      });
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: previous
+      });
+
+      if (previous) {
+        $(previous).trigger(hideEvent);
+      }
+
+      $(this._element).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (selector) {
+        target = $(selector)[0];
+      }
+
+      this._activate(this._element, ulElement);
+
+      var complete = function complete() {
+        var hiddenEvent = $.Event(Event.HIDDEN, {
+          relatedTarget: _this15._element
+        });
+
+        var shownEvent = $.Event(Event.SHOWN, {
+          relatedTarget: previous
+        });
+
+        $(previous).trigger(hiddenEvent);
+        $(_this15._element).trigger(shownEvent);
+      };
+
+      if (target) {
+        this._activate(target, target.parentNode, complete);
+      } else {
+        complete();
+      }
+    };
+
+    Tab.prototype.dispose = function dispose() {
+      $.removeClass(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Tab.prototype._activate = function _activate(element, container, callback) {
+      var active = $(container).find(Selector.ACTIVE_CHILD)[0];
+      var isTransitioning = callback && Util.supportsTransitionEnd() && (active && $(active).hasClass(ClassName.FADE) || Boolean($(container).find(Selector.FADE_CHILD)[0]));
+
+      var complete = $.proxy(this._transitionComplete, this, element, active, isTransitioning, callback);
+
+      if (active && isTransitioning) {
+        $(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      if (active) {
+        $(active).removeClass(ClassName.IN);
+      }
+    };
+
+    Tab.prototype._transitionComplete = function _transitionComplete(element, active, isTransitioning, callback) {
+      if (active) {
+        $(active).removeClass(ClassName.ACTIVE);
+
+        var dropdownChild = $(active).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
+
+        if (dropdownChild) {
+          $(dropdownChild).removeClass(ClassName.ACTIVE);
+        }
+
+        active.setAttribute('aria-expanded', false);
+      }
+
+      $(element).addClass(ClassName.ACTIVE);
+      element.setAttribute('aria-expanded', true);
+
+      if (isTransitioning) {
+        Util.reflow(element);
+        $(element).addClass(ClassName.IN);
+      } else {
+        $(element).removeClass(ClassName.FADE);
+      }
+
+      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
+
+        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];
+        if (dropdownElement) {
+          $(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        }
+
+        element.setAttribute('aria-expanded', true);
+      }
+
+      if (callback) {
+        callback();
+      }
+    };
+
+    // static
+
+    Tab._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+
+        if (!data) {
+          data = data = new Tab(this);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tab, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Tab;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+    Tab._jQueryInterface.call($(this), 'show');
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tab._jQueryInterface;
+  $.fn[NAME].Constructor = Tab;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tab._jQueryInterface;
+  };
+
+  return Tab;
+}(jQuery);
+
+/* global Tether */
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tooltip.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tooltip = function ($) {
+
+  /**
+   * Check for Tether dependency
+   * Tether - http://tether.io/
+   */
+  if (window.Tether === undefined) {
+    throw new Error('Bootstrap tooltips require Tether (http://tether.io/)');
+  }
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tooltip';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tooltip';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+  var CLASS_PREFIX = 'bs-tether';
+
+  var Default = {
+    animation: true,
+    template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    selector: false,
+    placement: 'top',
+    offset: '0 0',
+    constraints: []
+  };
+
+  var DefaultType = {
+    animation: 'boolean',
+    template: 'string',
+    title: '(string|element|function)',
+    trigger: 'string',
+    delay: '(number|object)',
+    html: 'boolean',
+    selector: '(string|boolean)',
+    placement: '(string|function)',
+    offset: 'string',
+    constraints: 'array'
+  };
+
+  var AttachmentMap = {
+    TOP: 'bottom center',
+    RIGHT: 'middle left',
+    BOTTOM: 'top center',
+    LEFT: 'middle right'
+  };
+
+  var HoverState = {
+    IN: 'in',
+    OUT: 'out'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TOOLTIP: '.tooltip',
+    TOOLTIP_INNER: '.tooltip-inner'
+  };
+
+  var TetherClass = {
+    element: false,
+    enabled: false
+  };
+
+  var Trigger = {
+    HOVER: 'hover',
+    FOCUS: 'focus',
+    CLICK: 'click',
+    MANUAL: 'manual'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tooltip = function () {
+    function Tooltip(element, config) {
+      _classCallCheck(this, Tooltip);
+
+      // private
+      this._isEnabled = true;
+      this._timeout = 0;
+      this._hoverState = '';
+      this._activeTrigger = {};
+      this._tether = null;
+
+      // protected
+      this.element = element;
+      this.config = this._getConfig(config);
+      this.tip = null;
+
+      this._setListeners();
+    }
+
+    // getters
+
+    // public
+
+    Tooltip.prototype.enable = function enable() {
+      this._isEnabled = true;
+    };
+
+    Tooltip.prototype.disable = function disable() {
+      this._isEnabled = false;
+    };
+
+    Tooltip.prototype.toggleEnabled = function toggleEnabled() {
+      this._isEnabled = !this._isEnabled;
+    };
+
+    Tooltip.prototype.toggle = function toggle(event) {
+      if (event) {
+        var dataKey = this.constructor.DATA_KEY;
+        var context = $(event.currentTarget).data(dataKey);
+
+        if (!context) {
+          context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+          $(event.currentTarget).data(dataKey, context);
+        }
+
+        context._activeTrigger.click = !context._activeTrigger.click;
+
+        if (context._isWithActiveTrigger()) {
+          context._enter(null, context);
+        } else {
+          context._leave(null, context);
+        }
+      } else {
+
+        if ($(this.getTipElement()).hasClass(ClassName.IN)) {
+          this._leave(null, this);
+          return;
+        }
+
+        this._enter(null, this);
+      }
+    };
+
+    Tooltip.prototype.dispose = function dispose() {
+      clearTimeout(this._timeout);
+
+      this.cleanupTether();
+
+      $.removeData(this.element, this.constructor.DATA_KEY);
+
+      $(this.element).off(this.constructor.EVENT_KEY);
+
+      if (this.tip) {
+        $(this.tip).remove();
+      }
+
+      this._isEnabled = null;
+      this._timeout = null;
+      this._hoverState = null;
+      this._activeTrigger = null;
+      this._tether = null;
+
+      this.element = null;
+      this.config = null;
+      this.tip = null;
+    };
+
+    Tooltip.prototype.show = function show() {
+      var _this16 = this;
+
+      var showEvent = $.Event(this.constructor.Event.SHOW);
+
+      if (this.isWithContent() && this._isEnabled) {
+        $(this.element).trigger(showEvent);
+
+        var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
+
+        if (showEvent.isDefaultPrevented() || !isInTheDom) {
+          return;
+        }
+
+        var tip = this.getTipElement();
+        var tipId = Util.getUID(this.constructor.NAME);
+
+        tip.setAttribute('id', tipId);
+        this.element.setAttribute('aria-describedby', tipId);
+
+        this.setContent();
+
+        if (this.config.animation) {
+          $(tip).addClass(ClassName.FADE);
+        }
+
+        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
+
+        var attachment = this._getAttachment(placement);
+
+        $(tip).data(this.constructor.DATA_KEY, this).appendTo(document.body);
+
+        $(this.element).trigger(this.constructor.Event.INSERTED);
+
+        this._tether = new Tether({
+          attachment: attachment,
+          element: tip,
+          target: this.element,
+          classes: TetherClass,
+          classPrefix: CLASS_PREFIX,
+          offset: this.config.offset,
+          constraints: this.config.constraints,
+          addTargetClasses: false
+        });
+
+        Util.reflow(tip);
+        this._tether.position();
+
+        $(tip).addClass(ClassName.IN);
+
+        var complete = function complete() {
+          var prevHoverState = _this16._hoverState;
+          _this16._hoverState = null;
+
+          $(_this16.element).trigger(_this16.constructor.Event.SHOWN);
+
+          if (prevHoverState === HoverState.OUT) {
+            _this16._leave(null, _this16);
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
+          return;
+        }
+
+        complete();
+      }
+    };
+
+    Tooltip.prototype.hide = function hide(callback) {
+      var _this17 = this;
+
+      var tip = this.getTipElement();
+      var hideEvent = $.Event(this.constructor.Event.HIDE);
+      var complete = function complete() {
+        if (_this17._hoverState !== HoverState.IN && tip.parentNode) {
+          tip.parentNode.removeChild(tip);
+        }
+
+        _this17.element.removeAttribute('aria-describedby');
+        $(_this17.element).trigger(_this17.constructor.Event.HIDDEN);
+        _this17.cleanupTether();
+
+        if (callback) {
+          callback();
+        }
+      };
+
+      $(this.element).trigger(hideEvent);
+
+      if (hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      $(tip).removeClass(ClassName.IN);
+
+      if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+
+        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      this._hoverState = '';
+    };
+
+    // protected
+
+    Tooltip.prototype.isWithContent = function isWithContent() {
+      return Boolean(this.getTitle());
+    };
+
+    Tooltip.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Tooltip.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    Tooltip.prototype.setElementContent = function setElementContent($element, content) {
+      var html = this.config.html;
+      if ((typeof content === 'undefined' ? 'undefined' : _typeof(content)) === 'object' && (content.nodeType || content.jquery)) {
+        // content is a DOM node or a jQuery
+        if (html) {
+          if (!$(content).parent().is($element)) {
+            $element.empty().append(content);
+          }
+        } else {
+          $element.text($(content).text());
+        }
+      } else {
+        $element[html ? 'html' : 'text'](content);
+      }
+    };
+
+    Tooltip.prototype.getTitle = function getTitle() {
+      var title = this.element.getAttribute('data-original-title');
+
+      if (!title) {
+        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
+      }
+
+      return title;
+    };
+
+    Tooltip.prototype.cleanupTether = function cleanupTether() {
+      if (this._tether) {
+        this._tether.destroy();
+      }
+    };
+
+    // private
+
+    Tooltip.prototype._getAttachment = function _getAttachment(placement) {
+      return AttachmentMap[placement.toUpperCase()];
+    };
+
+    Tooltip.prototype._setListeners = function _setListeners() {
+      var _this18 = this;
+
+      var triggers = this.config.trigger.split(' ');
+
+      triggers.forEach(function (trigger) {
+        if (trigger === 'click') {
+          $(_this18.element).on(_this18.constructor.Event.CLICK, _this18.config.selector, $.proxy(_this18.toggle, _this18));
+        } else if (trigger !== Trigger.MANUAL) {
+          var eventIn = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSEENTER : _this18.constructor.Event.FOCUSIN;
+          var eventOut = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSELEAVE : _this18.constructor.Event.FOCUSOUT;
+
+          $(_this18.element).on(eventIn, _this18.config.selector, $.proxy(_this18._enter, _this18)).on(eventOut, _this18.config.selector, $.proxy(_this18._leave, _this18));
+        }
+      });
+
+      if (this.config.selector) {
+        this.config = $.extend({}, this.config, {
+          trigger: 'manual',
+          selector: ''
+        });
+      } else {
+        this._fixTitle();
+      }
+    };
+
+    Tooltip.prototype._fixTitle = function _fixTitle() {
+      var titleType = _typeof(this.element.getAttribute('data-original-title'));
+      if (this.element.getAttribute('title') || titleType !== 'string') {
+        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
+        this.element.setAttribute('title', '');
+      }
+    };
+
+    Tooltip.prototype._enter = function _enter(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
+      }
+
+      if ($(context.getTipElement()).hasClass(ClassName.IN) || context._hoverState === HoverState.IN) {
+        context._hoverState = HoverState.IN;
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.IN;
+
+      if (!context.config.delay || !context.config.delay.show) {
+        context.show();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.IN) {
+          context.show();
+        }
+      }, context.config.delay.show);
+    };
+
+    Tooltip.prototype._leave = function _leave(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
+      }
+
+      if (context._isWithActiveTrigger()) {
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.OUT;
+
+      if (!context.config.delay || !context.config.delay.hide) {
+        context.hide();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.OUT) {
+          context.hide();
+        }
+      }, context.config.delay.hide);
+    };
+
+    Tooltip.prototype._isWithActiveTrigger = function _isWithActiveTrigger() {
+      for (var trigger in this._activeTrigger) {
+        if (this._activeTrigger[trigger]) {
+          return true;
+        }
+      }
+
+      return false;
+    };
+
+    Tooltip.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, this.constructor.Default, $(this.element).data(), config);
+
+      if (config.delay && typeof config.delay === 'number') {
+        config.delay = {
+          show: config.delay,
+          hide: config.delay
+        };
+      }
+
+      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
+
+      return config;
+    };
+
+    Tooltip.prototype._getDelegateConfig = function _getDelegateConfig() {
+      var config = {};
+
+      if (this.config) {
+        for (var key in this.config) {
+          if (this.constructor.Default[key] !== this.config[key]) {
+            config[key] = this.config[key];
+          }
+        }
+      }
+
+      return config;
+    };
+
+    // static
+
+    Tooltip._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /dispose|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Tooltip(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tooltip, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Tooltip;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tooltip._jQueryInterface;
+  $.fn[NAME].Constructor = Tooltip;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tooltip._jQueryInterface;
+  };
+
+  return Tooltip;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Popover = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'popover';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.popover';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = $.extend({}, Tooltip.Default, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip">' + '<h3 class="popover-title"></h3>' + '<div class="popover-content"></div></div>'
+  });
+
+  var DefaultType = $.extend({}, Tooltip.DefaultType, {
+    content: '(string|element|function)'
+  });
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TITLE: '.popover-title',
+    CONTENT: '.popover-content'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Popover = function (_Tooltip) {
+    _inherits(Popover, _Tooltip);
+
+    function Popover() {
+      _classCallCheck(this, Popover);
+
+      return _possibleConstructorReturn(this, _Tooltip.apply(this, arguments));
+    }
+
+    // overrides
+
+    Popover.prototype.isWithContent = function isWithContent() {
+      return this.getTitle() || this._getContent();
+    };
+
+    Popover.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Popover.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      // we use append for html objects to maintain js events
+      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
+      this.setElementContent($tip.find(Selector.CONTENT), this._getContent());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    // private
+
+    Popover.prototype._getContent = function _getContent() {
+      return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);
+    };
+
+    // static
+
+    Popover._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /destroy|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Popover(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Popover, null, [{
+      key: 'VERSION',
+
+
+      // getters
+
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Popover;
+  }(Tooltip);
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Popover._jQueryInterface;
+  $.fn[NAME].Constructor = Popover;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Popover._jQueryInterface;
+  };
+
+  return Popover;
+}(jQuery);
+
+}();
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
new file mode 100644
index 0000000..f8559b3
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/resources/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(jQuery),+function(){function a(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function b(a,b){ [...]
+DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},o=function(){function b(a){c(this,b),this._element=a}return b.prototype.show=function(){var b=this;if(!this._element.parentNode||this._element.parentNode.nodeType!==Node.ELEMENT_NODE||!a(this._element).hasClass(m.ACTIVE)){var c=void 0,d=void 0,e=a(this._element).closest(n.UL)[0],g=f.getSelectorFromElement(this._element);e&&(d=a.makeArray(a(e).find(n.ACTIVE)),d=d[d.length-1]);var h=a.Event(l.HIDE,{related [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/tobago-config.xml b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/tobago-config.xml
new file mode 100644
index 0000000..6e75251
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/resources/META-INF/tobago-config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+    version="3.0">
+  <name>tobago-theme-scarborough</name>
+  <ordering>
+    <after>
+      <name>tobago-theme-standard</name>
+    </after>
+  </ordering>
+  <theme-definitions>
+    <theme-definition>
+      <name>scarborough</name>
+      <display-name>Scarborough</display-name>
+      <fallback>standard</fallback>
+      <versioned>true</versioned>
+      <resources production="true">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+        </excludes>
+        <script name="/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+        <style name="/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+      </resources>
+      <resources production="false">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+        </excludes>
+        <script name="/tobago/scarborough/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+        <style name="/tobago/scarborough/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/scss/_custom.scss b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/scss/_custom.scss
new file mode 100644
index 0000000..d6807be
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/scss/_custom.scss
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Bootstrap overrides
+//
+// Copy variables from `_variables.scss` to this file to override default values
+// without modifying source files.
+
+$body-bg:    #bbccdd !default;
+
+// todo: get this from the JAR
+@import "tobago";
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/scss/_tobago.scss b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/scss/_tobago.scss
new file mode 100644
index 0000000..b342151
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-scarborough/src/main/scss/_tobago.scss
@@ -0,0 +1,918 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+
+/*
+ * theme: standard
+ * agent: standard
+ */
+
+/* box -------------------------------------------------------------- */
+
+.tobago-box-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+
+.tobago-flexLayout {
+    display: -webkit-flex; /* needed e.g. for Safari 8.0.2 */
+    display: -ms-flexbox; /* needed for IE 10 */
+    display: flex;
+    min-width: 0; /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+    flex-direction: column;
+    -webkit-flex-direction: column;
+    -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+    margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd{
+  justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween{
+  justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround{
+  justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  -moz-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+
+.tobago-gridLayout {
+    width: 100%;
+    height: 100%;
+/*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+    vertical-align: top;
+    padding: 0;
+    border-left: 5px solid transparent;
+    border-top: 5px solid transparent;
+    height: 100%; /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+    border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+    border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+
+.tobago-header {
+    margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+    margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+
+.tobago-image-markup-disabled {
+  filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  -webkit-border-radius: 6px 6px 6px 6px;
+  -moz-border-radius: 6px 6px 6px 6px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  -webkit-border-radius: 6px 0 6px 6px;
+  -moz-border-radius: 6px 0 6px 6px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+
+.tobago-selectManyShuttle {
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  flex: 1 0 0px;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: flex;
+  flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  flex: 1 0 0px;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: flex;
+  flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important; /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+.tobago-sheet-paging-markup-center {
+}
+
+.tobago-sheet-paging-markup-right {
+  float:right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important; /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+    padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+    background-color: #0097CF;
+    color: #FFFFFF;
+    cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+
+.tobago-tab {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}.form-horizontal .control-label {
+   margin-top: 10px;
+   margin-bottom: 5px;
+ }
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content:"*";
+  color:red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/pom.xml b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/pom.xml
new file mode 100644
index 0000000..d8ded54
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/pom.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-theme</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-theme-speyside</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Theme Speyside</name>
+
+  <properties>
+    <theme.name>speyside</theme.name>
+  </properties>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-theme-standard</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+  </dependencies>
+
+</project>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..b1db76e
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,3 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.css b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.css
new file mode 100644
index 0000000..118bfd9
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.css
@@ -0,0 +1,7681 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+/*
+ * theme: standard
+ * agent: standard
+ */
+/* box -------------------------------------------------------------- */
+.tobago-box-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+.tobago-flexLayout {
+  display: -webkit-flex;
+  /* needed e.g. for Safari 8.0.2 */
+  display: -ms-flexbox;
+  /* needed for IE 10 */
+  display: -webkit-box;
+  display: flex;
+  min-width: 0;
+  /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+          flex-direction: column;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  -webkit-box-align: baseline;
+  -webkit-align-items: baseline;
+      -ms-flex-align: baseline;
+          align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  -webkit-box-align: end;
+  -webkit-align-items: flex-end;
+      -ms-flex-align: end;
+          align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  -webkit-box-align: start;
+  -webkit-align-items: flex-start;
+      -ms-flex-align: start;
+          align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  -webkit-box-align: stretch;
+  -webkit-align-items: stretch;
+      -ms-flex-align: stretch;
+          align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  -webkit-box-pack: start;
+  -webkit-justify-content: flex-start;
+      -ms-flex-pack: start;
+          justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd {
+  -webkit-box-pack: end;
+  -webkit-justify-content: flex-end;
+      -ms-flex-pack: end;
+          justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween {
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround {
+  -webkit-justify-content: space-around;
+      -ms-flex-pack: distribute;
+          justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+  box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+.tobago-gridLayout {
+  width: 100%;
+  height: 100%;
+  /*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+  vertical-align: top;
+  padding: 0;
+  border-left: 5px solid transparent;
+  border-top: 5px solid transparent;
+  height: 100%;
+  /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+  border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+  border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+.tobago-header {
+  margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+  margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+.tobago-image-markup-disabled {
+  -webkit-filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+          filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal;
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+.tobago-selectManyShuttle {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  -webkit-flex-shrink: 0;
+      -ms-flex-negative: 0;
+          flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important;
+  /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+
+.tobago-sheet-paging-markup-right {
+  float: right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 1 auto;
+      -ms-flex: 1 1 auto;
+          flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important;
+  /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+  padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+  background-color: #0097CF;
+  color: #FFFFFF;
+  cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+.tobago-tab {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}
+
+.form-horizontal .control-label {
+  margin-top: 10px;
+  margin-bottom: 5px;
+}
+
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content: "*";
+  color: red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
+
+/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */
+html {
+  font-family: sans-serif;
+  line-height: 1.15;
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+}
+
+body {
+  margin: 0;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+  display: block;
+}
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+}
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+progress {
+  vertical-align: baseline;
+}
+
+template,
+[hidden] {
+  display: none;
+}
+
+a {
+  background-color: transparent;
+  -webkit-text-decoration-skip: objects;
+}
+
+a:active,
+a:hover {
+  outline-width: 0;
+}
+
+abbr[title] {
+  border-bottom: none;
+  text-decoration: underline;
+  text-decoration: underline dotted;
+}
+
+b,
+strong {
+  font-weight: inherit;
+}
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+dfn {
+  font-style: italic;
+}
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+
+small {
+  font-size: 80%;
+}
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+img {
+  border-style: none;
+}
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+figure {
+  margin: 1em 40px;
+}
+
+hr {
+  -webkit-box-sizing: content-box;
+          box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font: inherit;
+  margin: 0;
+}
+
+optgroup {
+  font-weight: bold;
+}
+
+button,
+input {
+  overflow: visible;
+}
+
+button,
+select {
+  text-transform: none;
+}
+
+button,
+html [type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+legend {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  color: inherit;
+  display: table;
+  max-width: 100%;
+  padding: 0;
+  white-space: normal;
+}
+
+textarea {
+  overflow: auto;
+}
+
+[type="checkbox"],
+[type="radio"] {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+[type="search"] {
+  -webkit-appearance: textfield;
+  outline-offset: -2px;
+}
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54;
+}
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  font: inherit;
+}
+
+@media print {
+  *,
+  *::before,
+  *::after,
+  *::first-letter,
+  p::first-line,
+  div::first-line,
+  blockquote::first-line,
+  li::first-line {
+    text-shadow: none !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  abbr[title]::after {
+    content: " (" attr(title) ")";
+  }
+  pre {
+    white-space: pre-wrap !important;
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  .navbar {
+    display: none;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .tag {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+
+html {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+  -webkit-box-sizing: inherit;
+          box-sizing: inherit;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+html {
+  font-size: 16px;
+  -ms-overflow-style: scrollbar;
+  -webkit-tap-highlight-color: transparent;
+}
+
+body {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-size: 1rem;
+  line-height: 1.5;
+  color: #373a3c;
+  background-color: #e2e2e2;
+}
+
+[tabindex="-1"]:focus {
+  outline: none !important;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 0;
+  margin-bottom: .5rem;
+}
+
+p {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #818a91;
+}
+
+address {
+  margin-bottom: 1rem;
+  font-style: normal;
+  line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+  margin-bottom: 0;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-bottom: .5rem;
+  margin-left: 0;
+}
+
+blockquote {
+  margin: 0 0 1rem;
+}
+
+a {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+a:focus, a:hover {
+  color: #014c8c;
+  text-decoration: underline;
+}
+
+a:focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+a:not([href]):not([tabindex]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus {
+  outline: none;
+}
+
+pre {
+  margin-top: 0;
+  margin-bottom: 1rem;
+  overflow: auto;
+}
+
+figure {
+  margin: 0 0 1rem;
+}
+
+img {
+  vertical-align: middle;
+}
+
+[role="button"] {
+  cursor: pointer;
+}
+
+a,
+area,
+button,
+[role="button"],
+input,
+label,
+select,
+summary,
+textarea {
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+}
+
+table {
+  border-collapse: collapse;
+  background-color: transparent;
+}
+
+caption {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  color: #818a91;
+  text-align: left;
+  caption-side: bottom;
+}
+
+th {
+  text-align: left;
+}
+
+label {
+  display: inline-block;
+  margin-bottom: .5rem;
+}
+
+button:focus {
+  outline: 1px dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+textarea {
+  line-height: inherit;
+}
+
+input[type="radio"]:disabled,
+input[type="checkbox"]:disabled {
+  cursor: not-allowed;
+}
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  -webkit-appearance: listbox;
+}
+
+textarea {
+  resize: vertical;
+}
+
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: .5rem;
+  font-size: 1.5rem;
+  line-height: inherit;
+}
+
+input[type="search"] {
+  -webkit-appearance: none;
+}
+
+output {
+  display: inline-block;
+}
+
+[hidden] {
+  display: none !important;
+}
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  margin-bottom: 0.5rem;
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+
+h1, .h1 {
+  font-size: 2.5rem;
+}
+
+h2, .h2 {
+  font-size: 2rem;
+}
+
+h3, .h3 {
+  font-size: 1.75rem;
+}
+
+h4, .h4 {
+  font-size: 1.5rem;
+}
+
+h5, .h5 {
+  font-size: 1.25rem;
+}
+
+h6, .h6 {
+  font-size: 1rem;
+}
+
+.lead {
+  font-size: 1.25rem;
+  font-weight: 300;
+}
+
+.display-1 {
+  font-size: 6rem;
+  font-weight: 300;
+}
+
+.display-2 {
+  font-size: 5.5rem;
+  font-weight: 300;
+}
+
+.display-3 {
+  font-size: 4.5rem;
+  font-weight: 300;
+}
+
+.display-4 {
+  font-size: 3.5rem;
+  font-weight: 300;
+}
+
+hr {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+small,
+.small {
+  font-size: 80%;
+  font-weight: normal;
+}
+
+mark,
+.mark {
+  padding: 0.2em;
+  background-color: #fcf8e3;
+}
+
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline-item {
+  display: inline-block;
+}
+
+.list-inline-item:not(:last-child) {
+  margin-right: 5px;
+}
+
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+.blockquote {
+  padding: 0.5rem 1rem;
+  margin-bottom: 1rem;
+  font-size: 1.25rem;
+  border-left: 0.25rem solid #eceeef;
+}
+
+.blockquote-footer {
+  display: block;
+  font-size: 80%;
+  color: #818a91;
+}
+
+.blockquote-footer::before {
+  content: "\2014 \00A0";
+}
+
+.blockquote-reverse {
+  padding-right: 1rem;
+  padding-left: 0;
+  text-align: right;
+  border-right: 0.25rem solid #eceeef;
+  border-left: 0;
+}
+
+.blockquote-reverse .blockquote-footer::before {
+  content: "";
+}
+
+.blockquote-reverse .blockquote-footer::after {
+  content: "\00A0 \2014";
+}
+
+dl.row > dd + dt {
+  clear: left;
+}
+
+.img-fluid, .carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  max-width: 100%;
+  height: auto;
+}
+
+.img-thumbnail {
+  padding: 0.25rem;
+  background-color: #e2e2e2;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  -webkit-transition: all .2s ease-in-out;
+  -o-transition: all .2s ease-in-out;
+  transition: all .2s ease-in-out;
+  max-width: 100%;
+  height: auto;
+}
+
+.figure {
+  display: inline-block;
+}
+
+.figure-img {
+  margin-bottom: 0.5rem;
+  line-height: 1;
+}
+
+.figure-caption {
+  font-size: 90%;
+  color: #818a91;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+code {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #bd4147;
+  background-color: #f7f7f9;
+  border-radius: 0.25rem;
+}
+
+kbd {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 0.2rem;
+}
+
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: bold;
+}
+
+pre {
+  display: block;
+  margin-top: 0;
+  margin-bottom: 1rem;
+  font-size: 90%;
+  color: #373a3c;
+}
+
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  background-color: transparent;
+  border-radius: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+.container {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .container {
+    width: 540px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 768px) {
+  .container {
+    width: 720px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 992px) {
+  .container {
+    width: 960px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container {
+    width: 1140px;
+    max-width: 100%;
+  }
+}
+
+.container-fluid {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container-fluid::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.row::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+.col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg [...]
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+@media (min-width: 576px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+.col-xs-1 {
+  float: left;
+  width: 8.333333%;
+}
+
+.col-xs-2 {
+  float: left;
+  width: 16.666667%;
+}
+
+.col-xs-3 {
+  float: left;
+  width: 25%;
+}
+
+.col-xs-4 {
+  float: left;
+  width: 33.333333%;
+}
+
+.col-xs-5 {
+  float: left;
+  width: 41.666667%;
+}
+
+.col-xs-6 {
+  float: left;
+  width: 50%;
+}
+
+.col-xs-7 {
+  float: left;
+  width: 58.333333%;
+}
+
+.col-xs-8 {
+  float: left;
+  width: 66.666667%;
+}
+
+.col-xs-9 {
+  float: left;
+  width: 75%;
+}
+
+.col-xs-10 {
+  float: left;
+  width: 83.333333%;
+}
+
+.col-xs-11 {
+  float: left;
+  width: 91.666667%;
+}
+
+.col-xs-12 {
+  float: left;
+  width: 100%;
+}
+
+.pull-xs-0 {
+  right: auto;
+}
+
+.pull-xs-1 {
+  right: 8.333333%;
+}
+
+.pull-xs-2 {
+  right: 16.666667%;
+}
+
+.pull-xs-3 {
+  right: 25%;
+}
+
+.pull-xs-4 {
+  right: 33.333333%;
+}
+
+.pull-xs-5 {
+  right: 41.666667%;
+}
+
+.pull-xs-6 {
+  right: 50%;
+}
+
+.pull-xs-7 {
+  right: 58.333333%;
+}
+
+.pull-xs-8 {
+  right: 66.666667%;
+}
+
+.pull-xs-9 {
+  right: 75%;
+}
+
+.pull-xs-10 {
+  right: 83.333333%;
+}
+
+.pull-xs-11 {
+  right: 91.666667%;
+}
+
+.pull-xs-12 {
+  right: 100%;
+}
+
+.push-xs-0 {
+  left: auto;
+}
+
+.push-xs-1 {
+  left: 8.333333%;
+}
+
+.push-xs-2 {
+  left: 16.666667%;
+}
+
+.push-xs-3 {
+  left: 25%;
+}
+
+.push-xs-4 {
+  left: 33.333333%;
+}
+
+.push-xs-5 {
+  left: 41.666667%;
+}
+
+.push-xs-6 {
+  left: 50%;
+}
+
+.push-xs-7 {
+  left: 58.333333%;
+}
+
+.push-xs-8 {
+  left: 66.666667%;
+}
+
+.push-xs-9 {
+  left: 75%;
+}
+
+.push-xs-10 {
+  left: 83.333333%;
+}
+
+.push-xs-11 {
+  left: 91.666667%;
+}
+
+.push-xs-12 {
+  left: 100%;
+}
+
+.offset-xs-1 {
+  margin-left: 8.333333%;
+}
+
+.offset-xs-2 {
+  margin-left: 16.666667%;
+}
+
+.offset-xs-3 {
+  margin-left: 25%;
+}
+
+.offset-xs-4 {
+  margin-left: 33.333333%;
+}
+
+.offset-xs-5 {
+  margin-left: 41.666667%;
+}
+
+.offset-xs-6 {
+  margin-left: 50%;
+}
+
+.offset-xs-7 {
+  margin-left: 58.333333%;
+}
+
+.offset-xs-8 {
+  margin-left: 66.666667%;
+}
+
+.offset-xs-9 {
+  margin-left: 75%;
+}
+
+.offset-xs-10 {
+  margin-left: 83.333333%;
+}
+
+.offset-xs-11 {
+  margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+  .col-sm-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-sm-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-sm-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-sm-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-sm-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-sm-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-sm-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-sm-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-sm-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-sm-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-sm-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-sm-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-sm-0 {
+    right: auto;
+  }
+  .pull-sm-1 {
+    right: 8.333333%;
+  }
+  .pull-sm-2 {
+    right: 16.666667%;
+  }
+  .pull-sm-3 {
+    right: 25%;
+  }
+  .pull-sm-4 {
+    right: 33.333333%;
+  }
+  .pull-sm-5 {
+    right: 41.666667%;
+  }
+  .pull-sm-6 {
+    right: 50%;
+  }
+  .pull-sm-7 {
+    right: 58.333333%;
+  }
+  .pull-sm-8 {
+    right: 66.666667%;
+  }
+  .pull-sm-9 {
+    right: 75%;
+  }
+  .pull-sm-10 {
+    right: 83.333333%;
+  }
+  .pull-sm-11 {
+    right: 91.666667%;
+  }
+  .pull-sm-12 {
+    right: 100%;
+  }
+  .push-sm-0 {
+    left: auto;
+  }
+  .push-sm-1 {
+    left: 8.333333%;
+  }
+  .push-sm-2 {
+    left: 16.666667%;
+  }
+  .push-sm-3 {
+    left: 25%;
+  }
+  .push-sm-4 {
+    left: 33.333333%;
+  }
+  .push-sm-5 {
+    left: 41.666667%;
+  }
+  .push-sm-6 {
+    left: 50%;
+  }
+  .push-sm-7 {
+    left: 58.333333%;
+  }
+  .push-sm-8 {
+    left: 66.666667%;
+  }
+  .push-sm-9 {
+    left: 75%;
+  }
+  .push-sm-10 {
+    left: 83.333333%;
+  }
+  .push-sm-11 {
+    left: 91.666667%;
+  }
+  .push-sm-12 {
+    left: 100%;
+  }
+  .offset-sm-0 {
+    margin-left: 0%;
+  }
+  .offset-sm-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-sm-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-sm-3 {
+    margin-left: 25%;
+  }
+  .offset-sm-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-sm-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-sm-6 {
+    margin-left: 50%;
+  }
+  .offset-sm-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-sm-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-sm-9 {
+    margin-left: 75%;
+  }
+  .offset-sm-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-sm-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-md-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-md-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-md-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-md-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-md-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-md-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-md-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-md-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-md-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-md-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-md-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-md-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-md-0 {
+    right: auto;
+  }
+  .pull-md-1 {
+    right: 8.333333%;
+  }
+  .pull-md-2 {
+    right: 16.666667%;
+  }
+  .pull-md-3 {
+    right: 25%;
+  }
+  .pull-md-4 {
+    right: 33.333333%;
+  }
+  .pull-md-5 {
+    right: 41.666667%;
+  }
+  .pull-md-6 {
+    right: 50%;
+  }
+  .pull-md-7 {
+    right: 58.333333%;
+  }
+  .pull-md-8 {
+    right: 66.666667%;
+  }
+  .pull-md-9 {
+    right: 75%;
+  }
+  .pull-md-10 {
+    right: 83.333333%;
+  }
+  .pull-md-11 {
+    right: 91.666667%;
+  }
+  .pull-md-12 {
+    right: 100%;
+  }
+  .push-md-0 {
+    left: auto;
+  }
+  .push-md-1 {
+    left: 8.333333%;
+  }
+  .push-md-2 {
+    left: 16.666667%;
+  }
+  .push-md-3 {
+    left: 25%;
+  }
+  .push-md-4 {
+    left: 33.333333%;
+  }
+  .push-md-5 {
+    left: 41.666667%;
+  }
+  .push-md-6 {
+    left: 50%;
+  }
+  .push-md-7 {
+    left: 58.333333%;
+  }
+  .push-md-8 {
+    left: 66.666667%;
+  }
+  .push-md-9 {
+    left: 75%;
+  }
+  .push-md-10 {
+    left: 83.333333%;
+  }
+  .push-md-11 {
+    left: 91.666667%;
+  }
+  .push-md-12 {
+    left: 100%;
+  }
+  .offset-md-0 {
+    margin-left: 0%;
+  }
+  .offset-md-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-md-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-md-3 {
+    margin-left: 25%;
+  }
+  .offset-md-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-md-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-md-6 {
+    margin-left: 50%;
+  }
+  .offset-md-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-md-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-md-9 {
+    margin-left: 75%;
+  }
+  .offset-md-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-md-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-lg-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-lg-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-lg-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-lg-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-lg-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-lg-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-lg-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-lg-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-lg-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-lg-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-lg-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-lg-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-lg-0 {
+    right: auto;
+  }
+  .pull-lg-1 {
+    right: 8.333333%;
+  }
+  .pull-lg-2 {
+    right: 16.666667%;
+  }
+  .pull-lg-3 {
+    right: 25%;
+  }
+  .pull-lg-4 {
+    right: 33.333333%;
+  }
+  .pull-lg-5 {
+    right: 41.666667%;
+  }
+  .pull-lg-6 {
+    right: 50%;
+  }
+  .pull-lg-7 {
+    right: 58.333333%;
+  }
+  .pull-lg-8 {
+    right: 66.666667%;
+  }
+  .pull-lg-9 {
+    right: 75%;
+  }
+  .pull-lg-10 {
+    right: 83.333333%;
+  }
+  .pull-lg-11 {
+    right: 91.666667%;
+  }
+  .pull-lg-12 {
+    right: 100%;
+  }
+  .push-lg-0 {
+    left: auto;
+  }
+  .push-lg-1 {
+    left: 8.333333%;
+  }
+  .push-lg-2 {
+    left: 16.666667%;
+  }
+  .push-lg-3 {
+    left: 25%;
+  }
+  .push-lg-4 {
+    left: 33.333333%;
+  }
+  .push-lg-5 {
+    left: 41.666667%;
+  }
+  .push-lg-6 {
+    left: 50%;
+  }
+  .push-lg-7 {
+    left: 58.333333%;
+  }
+  .push-lg-8 {
+    left: 66.666667%;
+  }
+  .push-lg-9 {
+    left: 75%;
+  }
+  .push-lg-10 {
+    left: 83.333333%;
+  }
+  .push-lg-11 {
+    left: 91.666667%;
+  }
+  .push-lg-12 {
+    left: 100%;
+  }
+  .offset-lg-0 {
+    margin-left: 0%;
+  }
+  .offset-lg-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-lg-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-lg-3 {
+    margin-left: 25%;
+  }
+  .offset-lg-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-lg-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-lg-6 {
+    margin-left: 50%;
+  }
+  .offset-lg-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-lg-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-lg-9 {
+    margin-left: 75%;
+  }
+  .offset-lg-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-lg-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xl-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-xl-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-xl-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-xl-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-xl-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-xl-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-xl-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-xl-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-xl-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-xl-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-xl-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-xl-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-xl-0 {
+    right: auto;
+  }
+  .pull-xl-1 {
+    right: 8.333333%;
+  }
+  .pull-xl-2 {
+    right: 16.666667%;
+  }
+  .pull-xl-3 {
+    right: 25%;
+  }
+  .pull-xl-4 {
+    right: 33.333333%;
+  }
+  .pull-xl-5 {
+    right: 41.666667%;
+  }
+  .pull-xl-6 {
+    right: 50%;
+  }
+  .pull-xl-7 {
+    right: 58.333333%;
+  }
+  .pull-xl-8 {
+    right: 66.666667%;
+  }
+  .pull-xl-9 {
+    right: 75%;
+  }
+  .pull-xl-10 {
+    right: 83.333333%;
+  }
+  .pull-xl-11 {
+    right: 91.666667%;
+  }
+  .pull-xl-12 {
+    right: 100%;
+  }
+  .push-xl-0 {
+    left: auto;
+  }
+  .push-xl-1 {
+    left: 8.333333%;
+  }
+  .push-xl-2 {
+    left: 16.666667%;
+  }
+  .push-xl-3 {
+    left: 25%;
+  }
+  .push-xl-4 {
+    left: 33.333333%;
+  }
+  .push-xl-5 {
+    left: 41.666667%;
+  }
+  .push-xl-6 {
+    left: 50%;
+  }
+  .push-xl-7 {
+    left: 58.333333%;
+  }
+  .push-xl-8 {
+    left: 66.666667%;
+  }
+  .push-xl-9 {
+    left: 75%;
+  }
+  .push-xl-10 {
+    left: 83.333333%;
+  }
+  .push-xl-11 {
+    left: 91.666667%;
+  }
+  .push-xl-12 {
+    left: 100%;
+  }
+  .offset-xl-0 {
+    margin-left: 0%;
+  }
+  .offset-xl-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-xl-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-xl-3 {
+    margin-left: 25%;
+  }
+  .offset-xl-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-xl-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-xl-6 {
+    margin-left: 50%;
+  }
+  .offset-xl-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-xl-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-xl-9 {
+    margin-left: 75%;
+  }
+  .offset-xl-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-xl-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 1rem;
+}
+
+.table th,
+.table td {
+  padding: 0.75rem;
+  vertical-align: top;
+  border-top: 1px solid #eceeef;
+}
+
+.table thead th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #eceeef;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #eceeef;
+}
+
+.table .table {
+  background-color: #e2e2e2;
+}
+
+.table-sm th,
+.table-sm td {
+  padding: 0.3rem;
+}
+
+.table-bordered {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered thead th,
+.table-bordered thead td {
+  border-bottom-width: 2px;
+}
+
+.table-striped tbody tr:nth-of-type(odd) {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+
+.table-hover tbody tr:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-active,
+.table-active > th,
+.table-active > td {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover > td,
+.table-hover .table-active:hover > th {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-success,
+.table-success > th,
+.table-success > td {
+  background-color: #dff0d8;
+}
+
+.table-hover .table-success:hover {
+  background-color: #d0e9c6;
+}
+
+.table-hover .table-success:hover > td,
+.table-hover .table-success:hover > th {
+  background-color: #d0e9c6;
+}
+
+.table-info,
+.table-info > th,
+.table-info > td {
+  background-color: #d9edf7;
+}
+
+.table-hover .table-info:hover {
+  background-color: #c4e3f3;
+}
+
+.table-hover .table-info:hover > td,
+.table-hover .table-info:hover > th {
+  background-color: #c4e3f3;
+}
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+  background-color: #fcf8e3;
+}
+
+.table-hover .table-warning:hover {
+  background-color: #faf2cc;
+}
+
+.table-hover .table-warning:hover > td,
+.table-hover .table-warning:hover > th {
+  background-color: #faf2cc;
+}
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+  background-color: #f2dede;
+}
+
+.table-hover .table-danger:hover {
+  background-color: #ebcccc;
+}
+
+.table-hover .table-danger:hover > td,
+.table-hover .table-danger:hover > th {
+  background-color: #ebcccc;
+}
+
+.thead-inverse th {
+  color: #fff;
+  background-color: #373a3c;
+}
+
+.thead-default th {
+  color: #55595c;
+  background-color: #eceeef;
+}
+
+.table-inverse {
+  color: #eceeef;
+  background-color: #373a3c;
+}
+
+.table-inverse th,
+.table-inverse td,
+.table-inverse thead th {
+  border-color: #55595c;
+}
+
+.table-inverse.table-bordered {
+  border: 0;
+}
+
+.table-responsive {
+  display: block;
+  width: 100%;
+  min-height: 0%;
+  overflow-x: auto;
+}
+
+.table-reflow thead {
+  float: left;
+}
+
+.table-reflow tbody {
+  display: block;
+  white-space: nowrap;
+}
+
+.table-reflow th,
+.table-reflow td {
+  border-top: 1px solid #eceeef;
+  border-left: 1px solid #eceeef;
+}
+
+.table-reflow th:last-child,
+.table-reflow td:last-child {
+  border-right: 1px solid #eceeef;
+}
+
+.table-reflow thead:last-child tr:last-child th,
+.table-reflow thead:last-child tr:last-child td,
+.table-reflow tbody:last-child tr:last-child th,
+.table-reflow tbody:last-child tr:last-child td,
+.table-reflow tfoot:last-child tr:last-child th,
+.table-reflow tfoot:last-child tr:last-child td {
+  border-bottom: 1px solid #eceeef;
+}
+
+.table-reflow tr {
+  float: left;
+}
+
+.table-reflow tr th,
+.table-reflow tr td {
+  display: block !important;
+  border: 1px solid #eceeef;
+}
+
+.form-control {
+  display: block;
+  width: 100%;
+  padding: 0.5rem 0.75rem;
+  font-size: 1rem;
+  line-height: 1.25;
+  color: #55595c;
+  background-color: #fff;
+  background-image: none;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.form-control::-ms-expand {
+  background-color: transparent;
+  border: 0;
+}
+
+.form-control:focus {
+  color: #55595c;
+  background-color: #fff;
+  border-color: #66afe9;
+  outline: none;
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::-moz-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:disabled, .form-control[readonly] {
+  background-color: #eceeef;
+  opacity: 1;
+}
+
+.form-control:disabled {
+  cursor: not-allowed;
+}
+
+select.form-control:not([size]):not([multiple]) {
+  height: calc(2.5rem - 2px);
+}
+
+select.form-control:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.form-control-file,
+.form-control-range {
+  display: block;
+}
+
+.col-form-label {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+}
+
+.col-form-label-lg {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  font-size: 1.25rem;
+}
+
+.col-form-label-sm {
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  font-size: 0.875rem;
+}
+
+.col-form-legend {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+}
+
+.form-control-static {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  line-height: 1.25;
+  border: solid transparent;
+  border-width: 1px 0;
+}
+
+.form-control-static.form-control-sm, .input-group-sm > .form-control-static.form-control,
+.input-group-sm > .form-control-static.input-group-addon,
+.input-group-sm > .input-group-btn > .form-control-static.btn, .form-control-static.form-control-lg, .input-group-lg > .form-control-static.form-control,
+.input-group-lg > .form-control-static.input-group-addon,
+.input-group-lg > .input-group-btn > .form-control-static.btn {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.form-control-sm, .input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),
+.input-group-sm > select.input-group-addon:not([size]):not([multiple]),
+.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 1.8125rem;
+}
+
+.form-control-lg, .input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),
+.input-group-lg > select.input-group-addon:not([size]):not([multiple]),
+.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 3.166667rem;
+}
+
+.form-group {
+  margin-bottom: 1rem;
+}
+
+.form-text {
+  display: block;
+  margin-top: 0.25rem;
+}
+
+.form-check {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+}
+
+.form-check + .form-check {
+  margin-top: -.25rem;
+}
+
+.form-check.disabled .form-check-label {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-check-label {
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  cursor: pointer;
+}
+
+.form-check-input {
+  position: absolute;
+  margin-top: .25rem;
+  margin-left: -1.25rem;
+}
+
+.form-check-input:only-child {
+  position: static;
+}
+
+.form-check-inline {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  vertical-align: middle;
+  cursor: pointer;
+}
+
+.form-check-inline + .form-check-inline {
+  margin-left: .75rem;
+}
+
+.form-check-inline.disabled {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-control-feedback {
+  margin-top: 0.25rem;
+}
+
+.form-control-success,
+.form-control-warning,
+.form-control-danger {
+  padding-right: 2.25rem;
+  background-repeat: no-repeat;
+  background-position: center right 0.625rem;
+  -webkit-background-size: 1.25rem 1.25rem;
+          background-size: 1.25rem 1.25rem;
+}
+
+.has-success .form-control-feedback,
+.has-success .form-control-label,
+.has-success .form-check-label,
+.has-success .form-check-inline,
+.has-success .custom-control {
+  color: #5cb85c;
+}
+
+.has-success .form-control {
+  border-color: #5cb85c;
+}
+
+.has-success .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+}
+
+.has-success .input-group-addon {
+  color: #5cb85c;
+  border-color: #5cb85c;
+  background-color: #eaf6ea;
+}
+
+.has-success .form-control-success {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#5cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");
+}
+
+.has-warning .form-control-feedback,
+.has-warning .form-control-label,
+.has-warning .form-check-label,
+.has-warning .form-check-inline,
+.has-warning .custom-control {
+  color: #f0ad4e;
+}
+
+.has-warning .form-control {
+  border-color: #f0ad4e;
+}
+
+.has-warning .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+}
+
+.has-warning .input-group-addon {
+  color: #f0ad4e;
+  border-color: #f0ad4e;
+  background-color: white;
+}
+
+.has-warning .form-control-warning {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E");
+}
+
+.has-danger .form-control-feedback,
+.has-danger .form-control-label,
+.has-danger .form-check-label,
+.has-danger .form-check-inline,
+.has-danger .custom-control {
+  color: #d9534f;
+}
+
+.has-danger .form-control {
+  border-color: #d9534f;
+}
+
+.has-danger .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+}
+
+.has-danger .input-group-addon {
+  color: #d9534f;
+  border-color: #d9534f;
+  background-color: #fdf7f7;
+}
+
+.has-danger .form-control-danger {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E");
+}
+
+@media (min-width: 576px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-static {
+    display: inline-block;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .form-control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check-label {
+    padding-left: 0;
+  }
+  .form-inline .form-check-input {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+
+.btn {
+  display: inline-block;
+  font-weight: normal;
+  line-height: 1.25;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  border: 1px solid transparent;
+  padding: 0.5rem 1rem;
+  font-size: 1rem;
+  border-radius: 0.25rem;
+}
+
+.btn:focus, .btn.focus, .btn:active:focus, .btn:active.focus, .btn.active:focus, .btn.active.focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn:focus, .btn:hover {
+  text-decoration: none;
+}
+
+.btn.focus {
+  text-decoration: none;
+}
+
+.btn:active, .btn.active {
+  background-image: none;
+  outline: 0;
+}
+
+.btn.disabled, .btn:disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+a.btn.disabled,
+fieldset[disabled] a.btn {
+  pointer-events: none;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary:hover {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:focus, .btn-primary.focus {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:active, .btn-primary.active,
+.open > .btn-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+  background-image: none;
+}
+
+.btn-primary:active:hover, .btn-primary:active:focus, .btn-primary:active.focus, .btn-primary.active:hover, .btn-primary.active:focus, .btn-primary.active.focus,
+.open > .btn-primary.dropdown-toggle:hover,
+.open > .btn-primary.dropdown-toggle:focus,
+.open > .btn-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary:disabled:focus, .btn-primary:disabled.focus {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary.disabled:hover, .btn-primary:disabled:hover {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-secondary {
+  color: #373a3c;
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary:hover {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:focus, .btn-secondary.focus {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:active, .btn-secondary.active,
+.open > .btn-secondary.dropdown-toggle {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+  background-image: none;
+}
+
+.btn-secondary:active:hover, .btn-secondary:active:focus, .btn-secondary:active.focus, .btn-secondary.active:hover, .btn-secondary.active:focus, .btn-secondary.active.focus,
+.open > .btn-secondary.dropdown-toggle:hover,
+.open > .btn-secondary.dropdown-toggle:focus,
+.open > .btn-secondary.dropdown-toggle.focus {
+  color: #373a3c;
+  background-color: #d4d4d4;
+  border-color: #8c8c8c;
+}
+
+.btn-secondary.disabled:focus, .btn-secondary.disabled.focus, .btn-secondary:disabled:focus, .btn-secondary:disabled.focus {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary.disabled:hover, .btn-secondary:disabled:hover {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-info {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info:hover {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:focus, .btn-info.focus {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:active, .btn-info.active,
+.open > .btn-info.dropdown-toggle {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+  background-image: none;
+}
+
+.btn-info:active:hover, .btn-info:active:focus, .btn-info:active.focus, .btn-info.active:hover, .btn-info.active:focus, .btn-info.active.focus,
+.open > .btn-info.dropdown-toggle:hover,
+.open > .btn-info.dropdown-toggle:focus,
+.open > .btn-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info:disabled:focus, .btn-info:disabled.focus {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info.disabled:hover, .btn-info:disabled:hover {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-success {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success:hover {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:focus, .btn-success.focus {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:active, .btn-success.active,
+.open > .btn-success.dropdown-toggle {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+  background-image: none;
+}
+
+.btn-success:active:hover, .btn-success:active:focus, .btn-success:active.focus, .btn-success.active:hover, .btn-success.active:focus, .btn-success.active.focus,
+.open > .btn-success.dropdown-toggle:hover,
+.open > .btn-success.dropdown-toggle:focus,
+.open > .btn-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success:disabled:focus, .btn-success:disabled.focus {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success.disabled:hover, .btn-success:disabled:hover {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-warning {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning:hover {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:focus, .btn-warning.focus {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:active, .btn-warning.active,
+.open > .btn-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+  background-image: none;
+}
+
+.btn-warning:active:hover, .btn-warning:active:focus, .btn-warning:active.focus, .btn-warning.active:hover, .btn-warning.active:focus, .btn-warning.active.focus,
+.open > .btn-warning.dropdown-toggle:hover,
+.open > .btn-warning.dropdown-toggle:focus,
+.open > .btn-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning:disabled:focus, .btn-warning:disabled.focus {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning.disabled:hover, .btn-warning:disabled:hover {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-danger {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger:hover {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:focus, .btn-danger.focus {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:active, .btn-danger.active,
+.open > .btn-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+  background-image: none;
+}
+
+.btn-danger:active:hover, .btn-danger:active:focus, .btn-danger:active.focus, .btn-danger.active:hover, .btn-danger.active:focus, .btn-danger.active.focus,
+.open > .btn-danger.dropdown-toggle:hover,
+.open > .btn-danger.dropdown-toggle:focus,
+.open > .btn-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger:disabled:focus, .btn-danger:disabled.focus {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger.disabled:hover, .btn-danger:disabled:hover {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-primary {
+  color: #0275d8;
+  background-image: none;
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:hover {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:focus, .btn-outline-primary.focus {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active, .btn-outline-primary.active,
+.open > .btn-outline-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active:hover, .btn-outline-primary:active:focus, .btn-outline-primary:active.focus, .btn-outline-primary.active:hover, .btn-outline-primary.active:focus, .btn-outline-primary.active.focus,
+.open > .btn-outline-primary.dropdown-toggle:hover,
+.open > .btn-outline-primary.dropdown-toggle:focus,
+.open > .btn-outline-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-outline-primary.disabled:focus, .btn-outline-primary.disabled.focus, .btn-outline-primary:disabled:focus, .btn-outline-primary:disabled.focus {
+  border-color: #43a7fd;
+}
+
+.btn-outline-primary.disabled:hover, .btn-outline-primary:disabled:hover {
+  border-color: #43a7fd;
+}
+
+.btn-outline-secondary {
+  color: #ccc;
+  background-image: none;
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:hover {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:focus, .btn-outline-secondary.focus {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active, .btn-outline-secondary.active,
+.open > .btn-outline-secondary.dropdown-toggle {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active:hover, .btn-outline-secondary:active:focus, .btn-outline-secondary:active.focus, .btn-outline-secondary.active:hover, .btn-outline-secondary.active:focus, .btn-outline-secondary.active.focus,
+.open > .btn-outline-secondary.dropdown-toggle:hover,
+.open > .btn-outline-secondary.dropdown-toggle:focus,
+.open > .btn-outline-secondary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #a1a1a1;
+  border-color: #8c8c8c;
+}
+
+.btn-outline-secondary.disabled:focus, .btn-outline-secondary.disabled.focus, .btn-outline-secondary:disabled:focus, .btn-outline-secondary:disabled.focus {
+  border-color: white;
+}
+
+.btn-outline-secondary.disabled:hover, .btn-outline-secondary:disabled:hover {
+  border-color: white;
+}
+
+.btn-outline-info {
+  color: #5bc0de;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:hover {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:focus, .btn-outline-info.focus {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active, .btn-outline-info.active,
+.open > .btn-outline-info.dropdown-toggle {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active:hover, .btn-outline-info:active:focus, .btn-outline-info:active.focus, .btn-outline-info.active:hover, .btn-outline-info.active:focus, .btn-outline-info.active.focus,
+.open > .btn-outline-info.dropdown-toggle:hover,
+.open > .btn-outline-info.dropdown-toggle:focus,
+.open > .btn-outline-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-outline-info.disabled:focus, .btn-outline-info.disabled.focus, .btn-outline-info:disabled:focus, .btn-outline-info:disabled.focus {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-info.disabled:hover, .btn-outline-info:disabled:hover {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-success {
+  color: #5cb85c;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:hover {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:focus, .btn-outline-success.focus {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active, .btn-outline-success.active,
+.open > .btn-outline-success.dropdown-toggle {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active:hover, .btn-outline-success:active:focus, .btn-outline-success:active.focus, .btn-outline-success.active:hover, .btn-outline-success.active:focus, .btn-outline-success.active.focus,
+.open > .btn-outline-success.dropdown-toggle:hover,
+.open > .btn-outline-success.dropdown-toggle:focus,
+.open > .btn-outline-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-outline-success.disabled:focus, .btn-outline-success.disabled.focus, .btn-outline-success:disabled:focus, .btn-outline-success:disabled.focus {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-success.disabled:hover, .btn-outline-success:disabled:hover {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-warning {
+  color: #f0ad4e;
+  background-image: none;
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:hover {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:focus, .btn-outline-warning.focus {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active, .btn-outline-warning.active,
+.open > .btn-outline-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active:hover, .btn-outline-warning:active:focus, .btn-outline-warning:active.focus, .btn-outline-warning.active:hover, .btn-outline-warning.active:focus, .btn-outline-warning.active.focus,
+.open > .btn-outline-warning.dropdown-toggle:hover,
+.open > .btn-outline-warning.dropdown-toggle:focus,
+.open > .btn-outline-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-outline-warning.disabled:focus, .btn-outline-warning.disabled.focus, .btn-outline-warning:disabled:focus, .btn-outline-warning:disabled.focus {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-warning.disabled:hover, .btn-outline-warning:disabled:hover {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-danger {
+  color: #d9534f;
+  background-image: none;
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:hover {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:focus, .btn-outline-danger.focus {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active, .btn-outline-danger.active,
+.open > .btn-outline-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active:hover, .btn-outline-danger:active:focus, .btn-outline-danger:active.focus, .btn-outline-danger.active:hover, .btn-outline-danger.active:focus, .btn-outline-danger.active.focus,
+.open > .btn-outline-danger.dropdown-toggle:hover,
+.open > .btn-outline-danger.dropdown-toggle:focus,
+.open > .btn-outline-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-outline-danger.disabled:focus, .btn-outline-danger.disabled.focus, .btn-outline-danger:disabled:focus, .btn-outline-danger:disabled.focus {
+  border-color: #eba5a3;
+}
+
+.btn-outline-danger.disabled:hover, .btn-outline-danger:disabled:hover {
+  border-color: #eba5a3;
+}
+
+.btn-link {
+  font-weight: normal;
+  color: #0275d8;
+  border-radius: 0;
+}
+
+.btn-link, .btn-link:active, .btn-link.active, .btn-link:disabled {
+  background-color: transparent;
+}
+
+.btn-link, .btn-link:focus, .btn-link:active {
+  border-color: transparent;
+}
+
+.btn-link:hover {
+  border-color: transparent;
+}
+
+.btn-link:focus, .btn-link:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link:disabled:focus, .btn-link:disabled:hover {
+  color: #818a91;
+  text-decoration: none;
+}
+
+.btn-lg, .btn-group-lg > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.btn-sm, .btn-group-sm > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+}
+
+.btn-block + .btn-block {
+  margin-top: 0.5rem;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+  -o-transition: opacity .15s linear;
+  transition: opacity .15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  display: none;
+}
+
+.collapse.in {
+  display: block;
+}
+
+tr.collapse.in {
+  display: table-row;
+}
+
+tbody.collapse.in {
+  display: table-row-group;
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition-timing-function: ease;
+       -o-transition-timing-function: ease;
+          transition-timing-function: ease;
+  -webkit-transition-duration: .35s;
+       -o-transition-duration: .35s;
+          transition-duration: .35s;
+  -webkit-transition-property: height;
+  -o-transition-property: height;
+  transition-property: height;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.3em;
+  vertical-align: middle;
+  content: "";
+  border-top: 0.3em solid;
+  border-right: 0.3em solid transparent;
+  border-left: 0.3em solid transparent;
+}
+
+.dropdown-toggle:focus {
+  outline: 0;
+}
+
+.dropup .dropdown-toggle::after {
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 10rem;
+  padding: 0.5rem 0;
+  margin: 0.125rem 0 0;
+  font-size: 1rem;
+  color: #373a3c;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.dropdown-divider {
+  height: 1px;
+  margin: 0.5rem 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+
+.dropdown-item {
+  display: block;
+  width: 100%;
+  padding: 3px 1.5rem;
+  clear: both;
+  font-weight: normal;
+  color: #373a3c;
+  text-align: inherit;
+  white-space: nowrap;
+  background: none;
+  border: 0;
+}
+
+.dropdown-item:focus, .dropdown-item:hover {
+  color: #2b2d2f;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.dropdown-item.active, .dropdown-item.active:focus, .dropdown-item.active:hover {
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  outline: 0;
+}
+
+.dropdown-item.disabled, .dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  color: #818a91;
+}
+
+.dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: "progid:DXImageTransform.Microsoft.gradient(enabled = false)";
+}
+
+.open > .dropdown-menu {
+  display: block;
+}
+
+.open > a {
+  outline: 0;
+}
+
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+
+.dropdown-header {
+  display: block;
+  padding: 0.5rem 1.5rem;
+  margin-bottom: 0;
+  font-size: 0.875rem;
+  color: #818a91;
+  white-space: nowrap;
+}
+
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 0.125rem;
+}
+
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+  margin-bottom: 0;
+}
+
+.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+.btn-group-vertical > .btn:focus,
+.btn-group-vertical > .btn:active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover {
+  z-index: 2;
+}
+
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+
+.btn-toolbar {
+  margin-left: -0.5rem;
+}
+
+.btn-toolbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 0.5rem;
+}
+
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group > .btn-group {
+  float: left;
+}
+
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+.btn + .dropdown-toggle-split {
+  padding-right: 0.75rem;
+  padding-left: 0.75rem;
+}
+
+.btn + .dropdown-toggle-split::after {
+  margin-left: 0;
+}
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+  padding-right: 0.375rem;
+  padding-left: 0.375rem;
+}
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+  padding-right: 1.125rem;
+  padding-left: 1.125rem;
+}
+
+.btn .caret {
+  margin-left: 0;
+}
+
+.btn-lg .caret, .btn-group-lg > .btn .caret {
+  border-width: 0.3em 0.3em 0;
+  border-bottom-width: 0;
+}
+
+.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret {
+  border-width: 0 0.3em 0.3em;
+}
+
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+
+.btn-group-vertical > .btn-group::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+  position: absolute;
+  clip: rect(0, 0, 0, 0);
+  pointer-events: none;
+}
+
+.input-group {
+  position: relative;
+  width: 100%;
+  display: table;
+  border-collapse: separate;
+}
+
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+
+.input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {
+  z-index: 3;
+}
+
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+
+.input-group-addon {
+  padding: 0.5rem 0.75rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+  font-weight: normal;
+  line-height: 1.25;
+  color: #55595c;
+  text-align: center;
+  background-color: #eceeef;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.input-group-addon.form-control-sm,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .input-group-addon.btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.input-group-addon.form-control-lg,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .input-group-addon.btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+
+.input-group .form-control:not(:last-child),
+.input-group-addon:not(:last-child),
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group > .btn,
+.input-group-btn:not(:last-child) > .dropdown-toggle,
+.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.input-group-addon:not(:last-child) {
+  border-right: 0;
+}
+
+.input-group .form-control:not(:first-child),
+.input-group-addon:not(:first-child),
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group > .btn,
+.input-group-btn:not(:first-child) > .dropdown-toggle,
+.input-group-btn:not(:last-child) > .btn:not(:first-child),
+.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.form-control + .input-group-addon:not(:first-child) {
+  border-left: 0;
+}
+
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+
+.input-group-btn > .btn {
+  position: relative;
+}
+
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+
+.input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {
+  z-index: 3;
+}
+
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group {
+  margin-right: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group {
+  z-index: 2;
+  margin-left: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,
+.input-group-btn:not(:first-child) > .btn-group:focus,
+.input-group-btn:not(:first-child) > .btn-group:active,
+.input-group-btn:not(:first-child) > .btn-group:hover {
+  z-index: 3;
+}
+
+.custom-control {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.5rem;
+  cursor: pointer;
+}
+
+.custom-control + .custom-control {
+  margin-left: 1rem;
+}
+
+.custom-control-input {
+  position: absolute;
+  z-index: -1;
+  opacity: 0;
+}
+
+.custom-control-input:checked ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #0074d9;
+}
+
+.custom-control-input:focus ~ .custom-control-indicator {
+  -webkit-box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+          box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+}
+
+.custom-control-input:active ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #84c6ff;
+}
+
+.custom-control-input:disabled ~ .custom-control-indicator {
+  cursor: not-allowed;
+  background-color: #eee;
+}
+
+.custom-control-input:disabled ~ .custom-control-description {
+  color: #767676;
+  cursor: not-allowed;
+}
+
+.custom-control-indicator {
+  position: absolute;
+  top: .25rem;
+  left: 0;
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  pointer-events: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #ddd;
+  background-repeat: no-repeat;
+  background-position: center center;
+  -webkit-background-size: 50% 50%;
+          background-size: 50% 50%;
+}
+
+.custom-checkbox .custom-control-indicator {
+  border-radius: 0.25rem;
+}
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
+}
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {
+  background-color: #0074d9;
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#fff' d='M0 2h4'/%3E%3C/svg%3E");
+}
+
+.custom-radio .custom-control-indicator {
+  border-radius: 50%;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#fff'/%3E%3C/svg%3E");
+}
+
+.custom-controls-stacked .custom-control {
+  float: left;
+  clear: left;
+}
+
+.custom-controls-stacked .custom-control + .custom-control {
+  margin-left: 0;
+}
+
+.custom-select {
+  display: inline-block;
+  max-width: 100%;
+  height: calc(2.5rem - 2px);
+  padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+  padding-right: 0.75rem \9;
+  color: #55595c;
+  vertical-align: middle;
+  background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;
+  background-image: none \9;
+  -webkit-background-size: 8px 10px;
+          background-size: 8px 10px;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+  -moz-appearance: none;
+  -webkit-appearance: none;
+}
+
+.custom-select:focus {
+  border-color: #51a7e8;
+  outline: none;
+}
+
+.custom-select:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.custom-select:disabled {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.custom-select::-ms-expand {
+  opacity: 0;
+}
+
+.custom-select-sm {
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  font-size: 75%;
+}
+
+.custom-file {
+  position: relative;
+  display: inline-block;
+  max-width: 100%;
+  height: 2.5rem;
+  cursor: pointer;
+}
+
+.custom-file-input {
+  min-width: 14rem;
+  max-width: 100%;
+  margin: 0;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+
+.custom-file-control {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 5;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+}
+
+.custom-file-control:lang(en)::after {
+  content: "Choose file...";
+}
+
+.custom-file-control::before {
+  position: absolute;
+  top: -1px;
+  right: -1px;
+  bottom: -1px;
+  z-index: 6;
+  display: block;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  background-color: #eee;
+  border: 1px solid #ddd;
+  border-radius: 0 0.25rem 0.25rem 0;
+}
+
+.custom-file-control:lang(en)::before {
+  content: "Browse";
+}
+
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.nav-link {
+  display: inline-block;
+}
+
+.nav-link:focus, .nav-link:hover {
+  text-decoration: none;
+}
+
+.nav-link.disabled {
+  color: #818a91;
+}
+
+.nav-link.disabled, .nav-link.disabled:focus, .nav-link.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+
+.nav-inline .nav-item {
+  display: inline-block;
+}
+
+.nav-inline .nav-item + .nav-item,
+.nav-inline .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-tabs .nav-item {
+  float: left;
+  margin-bottom: -1px;
+}
+
+.nav-tabs .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-tabs .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border: 1px solid transparent;
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover {
+  border-color: #eceeef #eceeef #ddd;
+}
+
+.nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:focus, .nav-tabs .nav-link.disabled:hover {
+  color: #818a91;
+  background-color: transparent;
+  border-color: transparent;
+}
+
+.nav-tabs .nav-link.active, .nav-tabs .nav-link.active:focus, .nav-tabs .nav-link.active:hover,
+.nav-tabs .nav-item.open .nav-link,
+.nav-tabs .nav-item.open .nav-link:focus,
+.nav-tabs .nav-item.open .nav-link:hover {
+  color: #55595c;
+  background-color: #e2e2e2;
+  border-color: #ddd #ddd transparent;
+}
+
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.nav-pills::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-pills .nav-item {
+  float: left;
+}
+
+.nav-pills .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-pills .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border-radius: 0.25rem;
+}
+
+.nav-pills .nav-link.active, .nav-pills .nav-link.active:focus, .nav-pills .nav-link.active:hover,
+.nav-pills .nav-item.open .nav-link,
+.nav-pills .nav-item.open .nav-link:focus,
+.nav-pills .nav-item.open .nav-link:hover {
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+}
+
+.nav-stacked .nav-item {
+  display: block;
+  float: none;
+}
+
+.nav-stacked .nav-item + .nav-item {
+  margin-top: 0.2rem;
+  margin-left: 0;
+}
+
+.tab-content > .tab-pane {
+  display: none;
+}
+
+.tab-content > .active {
+  display: block;
+}
+
+.navbar {
+  position: relative;
+  padding: 0.5rem 1rem;
+}
+
+.navbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .navbar {
+    border-radius: 0.25rem;
+  }
+}
+
+.navbar-full {
+  z-index: 1000;
+}
+
+@media (min-width: 576px) {
+  .navbar-full {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+@media (min-width: 576px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top {
+  top: 0;
+}
+
+.navbar-fixed-bottom {
+  bottom: 0;
+}
+
+.navbar-sticky-top {
+  position: -webkit-sticky;
+  position: sticky;
+  top: 0;
+  z-index: 1030;
+  width: 100%;
+}
+
+@media (min-width: 576px) {
+  .navbar-sticky-top {
+    border-radius: 0;
+  }
+}
+
+.navbar-brand {
+  float: left;
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  margin-right: 1rem;
+  font-size: 1.25rem;
+  line-height: inherit;
+}
+
+.navbar-brand:focus, .navbar-brand:hover {
+  text-decoration: none;
+}
+
+.navbar-divider {
+  float: left;
+  width: 1px;
+  padding-top: 0.425rem;
+  padding-bottom: 0.425rem;
+  margin-right: 1rem;
+  margin-left: 1rem;
+  overflow: hidden;
+}
+
+.navbar-divider::before {
+  content: "\00a0";
+}
+
+.navbar-text {
+  display: inline-block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-toggler {
+  width: 2.5em;
+  height: 2em;
+  padding: 0.5rem 0.75rem;
+  font-size: 1.25rem;
+  line-height: 1;
+  background: transparent no-repeat center center;
+  -webkit-background-size: 24px 24px;
+          background-size: 24px 24px;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.navbar-toggler:focus, .navbar-toggler:hover {
+  text-decoration: none;
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-xs .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-xs .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-sm .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-sm .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-md .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-md .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block;
+  }
+}
+
+.navbar-toggleable-lg::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 1199px) {
+  .navbar-toggleable-lg .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-lg .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-lg .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 1200px) {
+  .navbar-toggleable-lg {
+    display: block;
+  }
+}
+
+.navbar-toggleable-xl {
+  display: block;
+}
+
+.navbar-toggleable-xl::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.navbar-toggleable-xl .navbar-brand {
+  display: block;
+  float: none;
+  margin-top: .5rem;
+  margin-right: 0;
+}
+
+.navbar-toggleable-xl .navbar-nav {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+
+.navbar-toggleable-xl .navbar-nav .dropdown-menu {
+  position: static;
+  float: none;
+}
+
+.navbar-nav .nav-item {
+  float: left;
+}
+
+.navbar-nav .nav-link {
+  display: block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-nav .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.navbar-nav .nav-item + .nav-item {
+  margin-left: 1rem;
+}
+
+.navbar-light .navbar-brand,
+.navbar-light .navbar-toggler {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover,
+.navbar-light .navbar-toggler:focus,
+.navbar-light .navbar-toggler:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-nav .nav-link {
+  color: rgba(0, 0, 0, 0.5);
+}
+
+.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover {
+  color: rgba(0, 0, 0, 0.7);
+}
+
+.navbar-light .navbar-nav .open > .nav-link, .navbar-light .navbar-nav .open > .nav-link:focus, .navbar-light .navbar-nav .open > .nav-link:hover,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link:focus,
+.navbar-light .navbar-nav .active > .nav-link:hover,
+.navbar-light .navbar-nav .nav-link.open,
+.navbar-light .navbar-nav .nav-link.open:focus,
+.navbar-light .navbar-nav .nav-link.open:hover,
+.navbar-light .navbar-nav .nav-link.active,
+.navbar-light .navbar-nav .nav-link.active:focus,
+.navbar-light .navbar-nav .nav-link.active:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.navbar-light .navbar-divider {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.navbar-dark .navbar-brand,
+.navbar-dark .navbar-toggler {
+  color: white;
+}
+
+.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover,
+.navbar-dark .navbar-toggler:focus,
+.navbar-dark .navbar-toggler:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-nav .nav-link {
+  color: rgba(255, 255, 255, 0.5);
+}
+
+.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.navbar-dark .navbar-nav .open > .nav-link, .navbar-dark .navbar-nav .open > .nav-link:focus, .navbar-dark .navbar-nav .open > .nav-link:hover,
+.navbar-dark .navbar-nav .active > .nav-link,
+.navbar-dark .navbar-nav .active > .nav-link:focus,
+.navbar-dark .navbar-nav .active > .nav-link:hover,
+.navbar-dark .navbar-nav .nav-link.open,
+.navbar-dark .navbar-nav .nav-link.open:focus,
+.navbar-dark .navbar-nav .nav-link.open:hover,
+.navbar-dark .navbar-nav .nav-link.active,
+.navbar-dark .navbar-nav .nav-link.active:focus,
+.navbar-dark .navbar-nav .nav-link.active:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(255, 255, 255, 0.1);
+}
+
+.navbar-dark .navbar-divider {
+  background-color: rgba(255, 255, 255, 0.075);
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block !important;
+  }
+}
+
+.card {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+  background-color: #fff;
+  border-radius: 0.25rem;
+  border: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-block {
+  padding: 1.25rem;
+}
+
+.card-block::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-title {
+  margin-bottom: 0.75rem;
+}
+
+.card-subtitle {
+  margin-top: -0.375rem;
+  margin-bottom: 0;
+}
+
+.card-text:last-child {
+  margin-bottom: 0;
+}
+
+.card-link:hover {
+  text-decoration: none;
+}
+
+.card-link + .card-link {
+  margin-left: 1.25rem;
+}
+
+.card > .list-group:first-child .list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.card > .list-group:last-child .list-group-item:last-child {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.card-header {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 0;
+  background-color: #f5f5f5;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-header:first-child {
+  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
+}
+
+.card-footer {
+  padding: 0.75rem 1.25rem;
+  background-color: #f5f5f5;
+  border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-footer:last-child {
+  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);
+}
+
+.card-header-tabs {
+  margin-right: -0.625rem;
+  margin-bottom: -0.75rem;
+  margin-left: -0.625rem;
+  border-bottom: 0;
+}
+
+.card-header-pills {
+  margin-right: -0.625rem;
+  margin-left: -0.625rem;
+}
+
+.card-primary {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.card-primary .card-header,
+.card-primary .card-footer {
+  background-color: transparent;
+}
+
+.card-success {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.card-success .card-header,
+.card-success .card-footer {
+  background-color: transparent;
+}
+
+.card-info {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.card-info .card-header,
+.card-info .card-footer {
+  background-color: transparent;
+}
+
+.card-warning {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.card-warning .card-header,
+.card-warning .card-footer {
+  background-color: transparent;
+}
+
+.card-danger {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.card-danger .card-header,
+.card-danger .card-footer {
+  background-color: transparent;
+}
+
+.card-outline-primary {
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.card-outline-secondary {
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.card-outline-info {
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.card-outline-success {
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.card-outline-warning {
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.card-outline-danger {
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer {
+  border-color: rgba(255, 255, 255, 0.2);
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer,
+.card-inverse .card-title,
+.card-inverse .card-blockquote {
+  color: #fff;
+}
+
+.card-inverse .card-link,
+.card-inverse .card-text,
+.card-inverse .card-subtitle,
+.card-inverse .card-blockquote .blockquote-footer {
+  color: rgba(255, 255, 255, 0.65);
+}
+
+.card-inverse .card-link:focus, .card-inverse .card-link:hover {
+  color: #fff;
+}
+
+.card-blockquote {
+  padding: 0;
+  margin-bottom: 0;
+  border-left: 0;
+}
+
+.card-img {
+  border-radius: calc(0.25rem - 1px);
+}
+
+.card-img-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1.25rem;
+}
+
+.card-img-top {
+  border-top-right-radius: calc(0.25rem - 1px);
+  border-top-left-radius: calc(0.25rem - 1px);
+}
+
+.card-img-bottom {
+  border-bottom-right-radius: calc(0.25rem - 1px);
+  border-bottom-left-radius: calc(0.25rem - 1px);
+}
+
+@media (min-width: 576px) {
+  .card-deck {
+    display: table;
+    width: 100%;
+    margin-bottom: 0.75rem;
+    table-layout: fixed;
+    border-spacing: 1.25rem 0;
+  }
+  .card-deck .card {
+    display: table-cell;
+    margin-bottom: 0;
+    vertical-align: top;
+  }
+  .card-deck-wrapper {
+    margin-right: -1.25rem;
+    margin-left: -1.25rem;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-group {
+    display: table;
+    width: 100%;
+    table-layout: fixed;
+  }
+  .card-group .card {
+    display: table-cell;
+    vertical-align: top;
+  }
+  .card-group .card + .card {
+    margin-left: 0;
+    border-left: 0;
+  }
+  .card-group .card:first-child {
+    border-bottom-right-radius: 0;
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-top {
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-bottom {
+    border-bottom-right-radius: 0;
+  }
+  .card-group .card:last-child {
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-top {
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-bottom {
+    border-bottom-left-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) {
+    border-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) .card-img-top,
+  .card-group .card:not(:first-child):not(:last-child) .card-img-bottom {
+    border-radius: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-columns {
+    -webkit-column-count: 3;
+       -moz-column-count: 3;
+            column-count: 3;
+    -webkit-column-gap: 1.25rem;
+       -moz-column-gap: 1.25rem;
+            column-gap: 1.25rem;
+  }
+  .card-columns .card {
+    display: inline-block;
+    width: 100%;
+  }
+}
+
+.breadcrumb {
+  padding: 0.75rem 1rem;
+  margin-bottom: 1rem;
+  list-style: none;
+  background-color: #eceeef;
+  border-radius: 0.25rem;
+}
+
+.breadcrumb::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.breadcrumb-item {
+  float: left;
+}
+
+.breadcrumb-item + .breadcrumb-item::before {
+  display: inline-block;
+  padding-right: 0.5rem;
+  padding-left: 0.5rem;
+  color: #818a91;
+  content: "/";
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: underline;
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: none;
+}
+
+.breadcrumb-item.active {
+  color: #818a91;
+}
+
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border-radius: 0.25rem;
+}
+
+.page-item {
+  display: inline;
+}
+
+.page-item:first-child .page-link {
+  margin-left: 0;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.page-item:last-child .page-link {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.page-item.active .page-link, .page-item.active .page-link:focus, .page-item.active .page-link:hover {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.page-item.disabled .page-link, .page-item.disabled .page-link:focus, .page-item.disabled .page-link:hover {
+  color: #818a91;
+  pointer-events: none;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+
+.page-link {
+  position: relative;
+  float: left;
+  padding: 0.5rem 0.75rem;
+  margin-left: -1px;
+  color: #0275d8;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.page-link:focus, .page-link:hover {
+  color: #014c8c;
+  background-color: #eceeef;
+  border-color: #ddd;
+}
+
+.pagination-lg .page-link {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+}
+
+.pagination-lg .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.3rem;
+  border-top-left-radius: 0.3rem;
+}
+
+.pagination-lg .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.3rem;
+  border-top-right-radius: 0.3rem;
+}
+
+.pagination-sm .page-link {
+  padding: 0.275rem 0.75rem;
+  font-size: 0.875rem;
+}
+
+.pagination-sm .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.2rem;
+  border-top-left-radius: 0.2rem;
+}
+
+.pagination-sm .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.2rem;
+  border-top-right-radius: 0.2rem;
+}
+
+.tag {
+  display: inline-block;
+  padding: 0.25em 0.4em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: 0.25rem;
+}
+
+.tag:empty {
+  display: none;
+}
+
+.btn .tag {
+  position: relative;
+  top: -1px;
+}
+
+a.tag:focus, a.tag:hover {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.tag-pill {
+  padding-right: 0.6em;
+  padding-left: 0.6em;
+  border-radius: 10rem;
+}
+
+.tag-default {
+  background-color: #818a91;
+}
+
+.tag-default[href]:focus, .tag-default[href]:hover {
+  background-color: #687077;
+}
+
+.tag-primary {
+  background-color: #0275d8;
+}
+
+.tag-primary[href]:focus, .tag-primary[href]:hover {
+  background-color: #025aa5;
+}
+
+.tag-success {
+  background-color: #5cb85c;
+}
+
+.tag-success[href]:focus, .tag-success[href]:hover {
+  background-color: #449d44;
+}
+
+.tag-info {
+  background-color: #5bc0de;
+}
+
+.tag-info[href]:focus, .tag-info[href]:hover {
+  background-color: #31b0d5;
+}
+
+.tag-warning {
+  background-color: #f0ad4e;
+}
+
+.tag-warning[href]:focus, .tag-warning[href]:hover {
+  background-color: #ec971f;
+}
+
+.tag-danger {
+  background-color: #d9534f;
+}
+
+.tag-danger[href]:focus, .tag-danger[href]:hover {
+  background-color: #c9302c;
+}
+
+.jumbotron {
+  padding: 2rem 1rem;
+  margin-bottom: 2rem;
+  background-color: #eceeef;
+  border-radius: 0.3rem;
+}
+
+@media (min-width: 576px) {
+  .jumbotron {
+    padding: 4rem 2rem;
+  }
+}
+
+.jumbotron-hr {
+  border-top-color: #d0d5d8;
+}
+
+.jumbotron-fluid {
+  padding-right: 0;
+  padding-left: 0;
+  border-radius: 0;
+}
+
+.alert {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 1rem;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.alert-heading {
+  color: inherit;
+}
+
+.alert-link {
+  font-weight: bold;
+}
+
+.alert-dismissible {
+  padding-right: 2.5rem;
+}
+
+.alert-dismissible .close {
+  position: relative;
+  top: -.125rem;
+  right: -1.25rem;
+  color: inherit;
+}
+
+.alert-success {
+  background-color: #dff0d8;
+  border-color: #d0e9c6;
+  color: #3c763d;
+}
+
+.alert-success hr {
+  border-top-color: #c1e2b3;
+}
+
+.alert-success .alert-link {
+  color: #2b542c;
+}
+
+.alert-info {
+  background-color: #d9edf7;
+  border-color: #bcdff1;
+  color: #31708f;
+}
+
+.alert-info hr {
+  border-top-color: #a6d5ec;
+}
+
+.alert-info .alert-link {
+  color: #245269;
+}
+
+.alert-warning {
+  background-color: #fcf8e3;
+  border-color: #faf2cc;
+  color: #8a6d3b;
+}
+
+.alert-warning hr {
+  border-top-color: #f7ecb5;
+}
+
+.alert-warning .alert-link {
+  color: #66512c;
+}
+
+.alert-danger {
+  background-color: #f2dede;
+  border-color: #ebcccc;
+  color: #a94442;
+}
+
+.alert-danger hr {
+  border-top-color: #e4b9b9;
+}
+
+.alert-danger .alert-link {
+  color: #843534;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  display: block;
+  width: 100%;
+  height: 1rem;
+  margin-bottom: 1rem;
+}
+
+.progress[value] {
+  background-color: #eee;
+  border: 0;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  border-radius: 0.25rem;
+}
+
+.progress[value]::-ms-fill {
+  background-color: #0074d9;
+  border: 0;
+}
+
+.progress[value]::-moz-progress-bar {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-value {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value="100"]::-moz-progress-bar {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value="100"]::-webkit-progress-value {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-bar {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+base::-moz-progress-bar,
+.progress[value] {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress {
+    background-color: #eee;
+    border-radius: 0.25rem;
+  }
+  .progress-bar {
+    display: inline-block;
+    height: 1rem;
+    text-indent: -999rem;
+    background-color: #0074d9;
+    border-bottom-left-radius: 0.25rem;
+    border-top-left-radius: 0.25rem;
+  }
+  .progress[width="100%"] {
+    border-bottom-right-radius: 0.25rem;
+    border-top-right-radius: 0.25rem;
+  }
+}
+
+.progress-striped[value]::-webkit-progress-value {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 1rem 1rem;
+          background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-moz-progress-bar {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-ms-fill {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-bar-striped {
+    background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    -webkit-background-size: 1rem 1rem;
+            background-size: 1rem 1rem;
+  }
+}
+
+.progress-animated[value]::-webkit-progress-value {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-animated[value]::-moz-progress-bar {
+  animation: progress-bar-stripes 2s linear infinite;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-animated .progress-bar-striped {
+    -webkit-animation: progress-bar-stripes 2s linear infinite;
+         -o-animation: progress-bar-stripes 2s linear infinite;
+            animation: progress-bar-stripes 2s linear infinite;
+  }
+}
+
+.progress-success[value]::-webkit-progress-value {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-moz-progress-bar {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-ms-fill {
+  background-color: #5cb85c;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-success .progress-bar {
+    background-color: #5cb85c;
+  }
+}
+
+.progress-info[value]::-webkit-progress-value {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-moz-progress-bar {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-ms-fill {
+  background-color: #5bc0de;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-info .progress-bar {
+    background-color: #5bc0de;
+  }
+}
+
+.progress-warning[value]::-webkit-progress-value {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-moz-progress-bar {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-ms-fill {
+  background-color: #f0ad4e;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-warning .progress-bar {
+    background-color: #f0ad4e;
+  }
+}
+
+.progress-danger[value]::-webkit-progress-value {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-moz-progress-bar {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-ms-fill {
+  background-color: #d9534f;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-danger .progress-bar {
+    background-color: #d9534f;
+  }
+}
+
+.media,
+.media-body {
+  overflow: hidden;
+}
+
+.media-body {
+  width: 10000px;
+}
+
+.media-left,
+.media-right,
+.media-body {
+  display: table-cell;
+  vertical-align: top;
+}
+
+.media-middle {
+  vertical-align: middle;
+}
+
+.media-bottom {
+  vertical-align: bottom;
+}
+
+.media-object {
+  display: block;
+}
+
+.media-object.img-thumbnail {
+  max-width: none;
+}
+
+.media-right {
+  padding-left: 10px;
+}
+
+.media-left {
+  padding-right: 10px;
+}
+
+.media-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-group {
+  padding-left: 0;
+  margin-bottom: 0;
+}
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 0.75rem 1.25rem;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.list-group-item.disabled, .list-group-item.disabled:focus, .list-group-item.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading {
+  color: inherit;
+}
+
+.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text {
+  color: #818a91;
+}
+
+.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover {
+  z-index: 2;
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > .small {
+  color: inherit;
+}
+
+.list-group-item.active .list-group-item-text, .list-group-item.active:focus .list-group-item-text, .list-group-item.active:hover .list-group-item-text {
+  color: #a8d6fe;
+}
+
+.list-group-flush .list-group-item {
+  border-right: 0;
+  border-left: 0;
+  border-radius: 0;
+}
+
+.list-group-item-action {
+  width: 100%;
+  color: #555;
+  text-align: inherit;
+}
+
+.list-group-item-action .list-group-item-heading {
+  color: #333;
+}
+
+.list-group-item-action:focus, .list-group-item-action:hover {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+
+a.list-group-item-success,
+button.list-group-item-success {
+  color: #3c763d;
+}
+
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-success:focus, a.list-group-item-success:hover,
+button.list-group-item-success:focus,
+button.list-group-item-success:hover {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+
+a.list-group-item-success.active, a.list-group-item-success.active:focus, a.list-group-item-success.active:hover,
+button.list-group-item-success.active,
+button.list-group-item-success.active:focus,
+button.list-group-item-success.active:hover {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+
+a.list-group-item-info,
+button.list-group-item-info {
+  color: #31708f;
+}
+
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-info:focus, a.list-group-item-info:hover,
+button.list-group-item-info:focus,
+button.list-group-item-info:hover {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+
+a.list-group-item-info.active, a.list-group-item-info.active:focus, a.list-group-item-info.active:hover,
+button.list-group-item-info.active,
+button.list-group-item-info.active:focus,
+button.list-group-item-info.active:hover {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+
+a.list-group-item-warning,
+button.list-group-item-warning {
+  color: #8a6d3b;
+}
+
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-warning:focus, a.list-group-item-warning:hover,
+button.list-group-item-warning:focus,
+button.list-group-item-warning:hover {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+
+a.list-group-item-warning.active, a.list-group-item-warning.active:focus, a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active,
+button.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:hover {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+
+a.list-group-item-danger,
+button.list-group-item-danger {
+  color: #a94442;
+}
+
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-danger:focus, a.list-group-item-danger:hover,
+button.list-group-item-danger:focus,
+button.list-group-item-danger:hover {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+
+a.list-group-item-danger.active, a.list-group-item-danger.active:focus, a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active,
+button.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:hover {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+.embed-responsive-21by9 {
+  padding-bottom: 42.857143%;
+}
+
+.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+
+.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+
+.embed-responsive-1by1 {
+  padding-bottom: 100%;
+}
+
+.close {
+  float: right;
+  font-size: 1.5rem;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  opacity: .2;
+}
+
+.close:focus, .close:hover {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  opacity: .5;
+}
+
+button.close {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.modal-open {
+  overflow: hidden;
+}
+
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  outline: 0;
+}
+
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+  transition: -webkit-transform .3s ease-out;
+  -o-transition: -o-transform .3s ease-out;
+  transition: transform .3s ease-out;
+  transition: transform .3s ease-out, -webkit-transform .3s ease-out, -o-transform .3s ease-out;
+  -webkit-transform: translate(0, -25%);
+      -ms-transform: translate(0, -25%);
+       -o-transform: translate(0, -25%);
+          transform: translate(0, -25%);
+}
+
+.modal.in .modal-dialog {
+  -webkit-transform: translate(0, 0);
+      -ms-transform: translate(0, 0);
+       -o-transform: translate(0, 0);
+          transform: translate(0, 0);
+}
+
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+  outline: 0;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop.in {
+  opacity: 0.5;
+}
+
+.modal-header {
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+.modal-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-header .close {
+  margin-top: -2px;
+}
+
+.modal-title {
+  margin: 0;
+  line-height: 1.5;
+}
+
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+
+.modal-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+
+@media (min-width: 576px) {
+  .modal-dialog {
+    max-width: 600px;
+    margin: 30px auto;
+  }
+  .modal-sm {
+    max-width: 300px;
+  }
+}
+
+@media (min-width: 992px) {
+  .modal-lg {
+    max-width: 900px;
+  }
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  opacity: 0;
+}
+
+.tooltip.in {
+  opacity: 0.9;
+}
+
+.tooltip.tooltip-top, .tooltip.bs-tether-element-attached-bottom {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+
+.tooltip.tooltip-top .tooltip-inner::before, .tooltip.bs-tether-element-attached-bottom .tooltip-inner::before {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+
+.tooltip.tooltip-right, .tooltip.bs-tether-element-attached-left {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+
+.tooltip.tooltip-right .tooltip-inner::before, .tooltip.bs-tether-element-attached-left .tooltip-inner::before {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+
+.tooltip.tooltip-bottom, .tooltip.bs-tether-element-attached-top {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+
+.tooltip.tooltip-bottom .tooltip-inner::before, .tooltip.bs-tether-element-attached-top .tooltip-inner::before {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+
+.tooltip.tooltip-left, .tooltip.bs-tether-element-attached-right {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+
+.tooltip.tooltip-left .tooltip-inner::before, .tooltip.bs-tether-element-attached-right .tooltip-inner::before {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  background-color: #000;
+  border-radius: 0.25rem;
+}
+
+.tooltip-inner::before {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: block;
+  max-width: 276px;
+  padding: 1px;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+}
+
+.popover.popover-top, .popover.bs-tether-element-attached-bottom {
+  margin-top: -10px;
+}
+
+.popover.popover-top::before, .popover.popover-top::after, .popover.bs-tether-element-attached-bottom::before, .popover.bs-tether-element-attached-bottom::after {
+  left: 50%;
+  border-bottom-width: 0;
+}
+
+.popover.popover-top::before, .popover.bs-tether-element-attached-bottom::before {
+  bottom: -11px;
+  margin-left: -11px;
+  border-top-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-top::after, .popover.bs-tether-element-attached-bottom::after {
+  bottom: -10px;
+  margin-left: -10px;
+  border-top-color: #fff;
+}
+
+.popover.popover-right, .popover.bs-tether-element-attached-left {
+  margin-left: 10px;
+}
+
+.popover.popover-right::before, .popover.popover-right::after, .popover.bs-tether-element-attached-left::before, .popover.bs-tether-element-attached-left::after {
+  top: 50%;
+  border-left-width: 0;
+}
+
+.popover.popover-right::before, .popover.bs-tether-element-attached-left::before {
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-right::after, .popover.bs-tether-element-attached-left::after {
+  left: -10px;
+  margin-top: -10px;
+  border-right-color: #fff;
+}
+
+.popover.popover-bottom, .popover.bs-tether-element-attached-top {
+  margin-top: 10px;
+}
+
+.popover.popover-bottom::before, .popover.popover-bottom::after, .popover.bs-tether-element-attached-top::before, .popover.bs-tether-element-attached-top::after {
+  left: 50%;
+  border-top-width: 0;
+}
+
+.popover.popover-bottom::before, .popover.bs-tether-element-attached-top::before {
+  top: -11px;
+  margin-left: -11px;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-bottom::after, .popover.bs-tether-element-attached-top::after {
+  top: -10px;
+  margin-left: -10px;
+  border-bottom-color: #f7f7f7;
+}
+
+.popover.popover-bottom .popover-title::before, .popover.bs-tether-element-attached-top .popover-title::before {
+  position: absolute;
+  top: 0;
+  left: 50%;
+  display: block;
+  width: 20px;
+  margin-left: -10px;
+  content: "";
+  border-bottom: 1px solid #f7f7f7;
+}
+
+.popover.popover-left, .popover.bs-tether-element-attached-right {
+  margin-left: -10px;
+}
+
+.popover.popover-left::before, .popover.popover-left::after, .popover.bs-tether-element-attached-right::before, .popover.bs-tether-element-attached-right::after {
+  top: 50%;
+  border-right-width: 0;
+}
+
+.popover.popover-left::before, .popover.bs-tether-element-attached-right::before {
+  right: -11px;
+  margin-top: -11px;
+  border-left-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-left::after, .popover.bs-tether-element-attached-right::after {
+  right: -10px;
+  margin-top: -10px;
+  border-left-color: #fff;
+}
+
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 1rem;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 0.2375rem 0.2375rem 0 0;
+}
+
+.popover-title:empty {
+  display: none;
+}
+
+.popover-content {
+  padding: 9px 14px;
+}
+
+.popover::before,
+.popover::after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover::before {
+  content: "";
+  border-width: 11px;
+}
+
+.popover::after {
+  content: "";
+  border-width: 10px;
+}
+
+.carousel {
+  position: relative;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-inner > .carousel-item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+  -o-transition: .6s ease-in-out left;
+  transition: .6s ease-in-out left;
+}
+
+.carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  line-height: 1;
+}
+
+@media all and (transform-3d), (-webkit-transform-3d) {
+  .carousel-inner > .carousel-item {
+    -webkit-transition: -webkit-transform .6s ease-in-out;
+    transition: -webkit-transform .6s ease-in-out;
+    -o-transition: -o-transform .6s ease-in-out;
+    transition: transform .6s ease-in-out;
+    transition: transform .6s ease-in-out, -webkit-transform .6s ease-in-out, -o-transform .6s ease-in-out;
+    -webkit-backface-visibility: hidden;
+            backface-visibility: hidden;
+    -webkit-perspective: 1000px;
+            perspective: 1000px;
+  }
+  .carousel-inner > .carousel-item.next, .carousel-inner > .carousel-item.active.right {
+    left: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+            transform: translate3d(100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.prev, .carousel-inner > .carousel-item.active.left {
+    left: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+            transform: translate3d(-100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.next.left, .carousel-inner > .carousel-item.prev.right, .carousel-inner > .carousel-item.active {
+    left: 0;
+    -webkit-transform: translate3d(0, 0, 0);
+            transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+
+.carousel-inner > .active {
+  left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.carousel-inner > .next {
+  left: 100%;
+}
+
+.carousel-inner > .prev {
+  left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+
+.carousel-inner > .active.left {
+  left: -100%;
+}
+
+.carousel-inner > .active.right {
+  left: 100%;
+}
+
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+  opacity: 0.5;
+}
+
+.carousel-control.left {
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+
+.carousel-control:focus, .carousel-control:hover {
+  color: #fff;
+  text-decoration: none;
+  outline: 0;
+  opacity: .9;
+}
+
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+  line-height: 1;
+}
+
+.carousel-control .icon-prev {
+  left: 50%;
+  margin-left: -10px;
+}
+
+.carousel-control .icon-next {
+  right: 50%;
+  margin-right: -10px;
+}
+
+.carousel-control .icon-prev::before {
+  content: "\2039";
+}
+
+.carousel-control .icon-next::before {
+  content: "\203a";
+}
+
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: transparent;
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+
+.carousel-caption .btn {
+  text-shadow: none;
+}
+
+@media (min-width: 576px) {
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+
+.align-baseline {
+  vertical-align: baseline !important;
+}
+
+.align-top {
+  vertical-align: top !important;
+}
+
+.align-middle {
+  vertical-align: middle !important;
+}
+
+.align-bottom {
+  vertical-align: bottom !important;
+}
+
+.align-text-bottom {
+  vertical-align: text-bottom !important;
+}
+
+.align-text-top {
+  vertical-align: text-top !important;
+}
+
+.bg-faded {
+  background-color: #f7f7f9;
+}
+
+.bg-primary {
+  background-color: #0275d8 !important;
+}
+
+a.bg-primary:focus, a.bg-primary:hover {
+  background-color: #025aa5 !important;
+}
+
+.bg-success {
+  background-color: #5cb85c !important;
+}
+
+a.bg-success:focus, a.bg-success:hover {
+  background-color: #449d44 !important;
+}
+
+.bg-info {
+  background-color: #5bc0de !important;
+}
+
+a.bg-info:focus, a.bg-info:hover {
+  background-color: #31b0d5 !important;
+}
+
+.bg-warning {
+  background-color: #f0ad4e !important;
+}
+
+a.bg-warning:focus, a.bg-warning:hover {
+  background-color: #ec971f !important;
+}
+
+.bg-danger {
+  background-color: #d9534f !important;
+}
+
+a.bg-danger:focus, a.bg-danger:hover {
+  background-color: #c9302c !important;
+}
+
+.bg-inverse {
+  background-color: #373a3c !important;
+}
+
+a.bg-inverse:focus, a.bg-inverse:hover {
+  background-color: #1f2021 !important;
+}
+
+.rounded {
+  border-radius: 0.25rem;
+}
+
+.rounded-top {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-right {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.rounded-bottom {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.rounded-left {
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-circle {
+  border-radius: 50%;
+}
+
+.clearfix::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.d-block {
+  display: block !important;
+}
+
+.d-inline-block {
+  display: inline-block !important;
+}
+
+.d-inline {
+  display: inline !important;
+}
+
+.float-xs-left {
+  float: left !important;
+}
+
+.float-xs-right {
+  float: right !important;
+}
+
+.float-xs-none {
+  float: none !important;
+}
+
+@media (min-width: 576px) {
+  .float-sm-left {
+    float: left !important;
+  }
+  .float-sm-right {
+    float: right !important;
+  }
+  .float-sm-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .float-md-left {
+    float: left !important;
+  }
+  .float-md-right {
+    float: right !important;
+  }
+  .float-md-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .float-lg-left {
+    float: left !important;
+  }
+  .float-lg-right {
+    float: right !important;
+  }
+  .float-lg-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .float-xl-left {
+    float: left !important;
+  }
+  .float-xl-right {
+    float: right !important;
+  }
+  .float-xl-none {
+    float: none !important;
+  }
+}
+
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+
+.w-100 {
+  width: 100% !important;
+}
+
+.h-100 {
+  height: 100% !important;
+}
+
+.mx-auto {
+  margin-right: auto !important;
+  margin-left: auto !important;
+}
+
+.m-0 {
+  margin: 0 0 !important;
+}
+
+.mt-0 {
+  margin-top: 0 !important;
+}
+
+.mr-0 {
+  margin-right: 0 !important;
+}
+
+.mb-0 {
+  margin-bottom: 0 !important;
+}
+
+.ml-0 {
+  margin-left: 0 !important;
+}
+
+.mx-0 {
+  margin-right: 0 !important;
+  margin-left: 0 !important;
+}
+
+.my-0 {
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+
+.m-1 {
+  margin: 1rem 1rem !important;
+}
+
+.mt-1 {
+  margin-top: 1rem !important;
+}
+
+.mr-1 {
+  margin-right: 1rem !important;
+}
+
+.mb-1 {
+  margin-bottom: 1rem !important;
+}
+
+.ml-1 {
+  margin-left: 1rem !important;
+}
+
+.mx-1 {
+  margin-right: 1rem !important;
+  margin-left: 1rem !important;
+}
+
+.my-1 {
+  margin-top: 1rem !important;
+  margin-bottom: 1rem !important;
+}
+
+.m-2 {
+  margin: 1.5rem 1.5rem !important;
+}
+
+.mt-2 {
+  margin-top: 1.5rem !important;
+}
+
+.mr-2 {
+  margin-right: 1.5rem !important;
+}
+
+.mb-2 {
+  margin-bottom: 1.5rem !important;
+}
+
+.ml-2 {
+  margin-left: 1.5rem !important;
+}
+
+.mx-2 {
+  margin-right: 1.5rem !important;
+  margin-left: 1.5rem !important;
+}
+
+.my-2 {
+  margin-top: 1.5rem !important;
+  margin-bottom: 1.5rem !important;
+}
+
+.m-3 {
+  margin: 3rem 3rem !important;
+}
+
+.mt-3 {
+  margin-top: 3rem !important;
+}
+
+.mr-3 {
+  margin-right: 3rem !important;
+}
+
+.mb-3 {
+  margin-bottom: 3rem !important;
+}
+
+.ml-3 {
+  margin-left: 3rem !important;
+}
+
+.mx-3 {
+  margin-right: 3rem !important;
+  margin-left: 3rem !important;
+}
+
+.my-3 {
+  margin-top: 3rem !important;
+  margin-bottom: 3rem !important;
+}
+
+.p-0 {
+  padding: 0 0 !important;
+}
+
+.pt-0 {
+  padding-top: 0 !important;
+}
+
+.pr-0 {
+  padding-right: 0 !important;
+}
+
+.pb-0 {
+  padding-bottom: 0 !important;
+}
+
+.pl-0 {
+  padding-left: 0 !important;
+}
+
+.px-0 {
+  padding-right: 0 !important;
+  padding-left: 0 !important;
+}
+
+.py-0 {
+  padding-top: 0 !important;
+  padding-bottom: 0 !important;
+}
+
+.p-1 {
+  padding: 1rem 1rem !important;
+}
+
+.pt-1 {
+  padding-top: 1rem !important;
+}
+
+.pr-1 {
+  padding-right: 1rem !important;
+}
+
+.pb-1 {
+  padding-bottom: 1rem !important;
+}
+
+.pl-1 {
+  padding-left: 1rem !important;
+}
+
+.px-1 {
+  padding-right: 1rem !important;
+  padding-left: 1rem !important;
+}
+
+.py-1 {
+  padding-top: 1rem !important;
+  padding-bottom: 1rem !important;
+}
+
+.p-2 {
+  padding: 1.5rem 1.5rem !important;
+}
+
+.pt-2 {
+  padding-top: 1.5rem !important;
+}
+
+.pr-2 {
+  padding-right: 1.5rem !important;
+}
+
+.pb-2 {
+  padding-bottom: 1.5rem !important;
+}
+
+.pl-2 {
+  padding-left: 1.5rem !important;
+}
+
+.px-2 {
+  padding-right: 1.5rem !important;
+  padding-left: 1.5rem !important;
+}
+
+.py-2 {
+  padding-top: 1.5rem !important;
+  padding-bottom: 1.5rem !important;
+}
+
+.p-3 {
+  padding: 3rem 3rem !important;
+}
+
+.pt-3 {
+  padding-top: 3rem !important;
+}
+
+.pr-3 {
+  padding-right: 3rem !important;
+}
+
+.pb-3 {
+  padding-bottom: 3rem !important;
+}
+
+.pl-3 {
+  padding-left: 3rem !important;
+}
+
+.px-3 {
+  padding-right: 3rem !important;
+  padding-left: 3rem !important;
+}
+
+.py-3 {
+  padding-top: 3rem !important;
+  padding-bottom: 3rem !important;
+}
+
+.pos-f-t {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+.text-justify {
+  text-align: justify !important;
+}
+
+.text-nowrap {
+  white-space: nowrap !important;
+}
+
+.text-truncate {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.text-xs-left {
+  text-align: left !important;
+}
+
+.text-xs-right {
+  text-align: right !important;
+}
+
+.text-xs-center {
+  text-align: center !important;
+}
+
+@media (min-width: 576px) {
+  .text-sm-left {
+    text-align: left !important;
+  }
+  .text-sm-right {
+    text-align: right !important;
+  }
+  .text-sm-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .text-md-left {
+    text-align: left !important;
+  }
+  .text-md-right {
+    text-align: right !important;
+  }
+  .text-md-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .text-lg-left {
+    text-align: left !important;
+  }
+  .text-lg-right {
+    text-align: right !important;
+  }
+  .text-lg-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .text-xl-left {
+    text-align: left !important;
+  }
+  .text-xl-right {
+    text-align: right !important;
+  }
+  .text-xl-center {
+    text-align: center !important;
+  }
+}
+
+.text-lowercase {
+  text-transform: lowercase !important;
+}
+
+.text-uppercase {
+  text-transform: uppercase !important;
+}
+
+.text-capitalize {
+  text-transform: capitalize !important;
+}
+
+.font-weight-normal {
+  font-weight: normal;
+}
+
+.font-weight-bold {
+  font-weight: bold;
+}
+
+.font-italic {
+  font-style: italic;
+}
+
+.text-white {
+  color: #fff !important;
+}
+
+.text-muted {
+  color: #818a91 !important;
+}
+
+a.text-muted:focus, a.text-muted:hover {
+  color: #687077 !important;
+}
+
+.text-primary {
+  color: #0275d8 !important;
+}
+
+a.text-primary:focus, a.text-primary:hover {
+  color: #025aa5 !important;
+}
+
+.text-success {
+  color: #5cb85c !important;
+}
+
+a.text-success:focus, a.text-success:hover {
+  color: #449d44 !important;
+}
+
+.text-info {
+  color: #5bc0de !important;
+}
+
+a.text-info:focus, a.text-info:hover {
+  color: #31b0d5 !important;
+}
+
+.text-warning {
+  color: #f0ad4e !important;
+}
+
+a.text-warning:focus, a.text-warning:hover {
+  color: #ec971f !important;
+}
+
+.text-danger {
+  color: #d9534f !important;
+}
+
+a.text-danger:focus, a.text-danger:hover {
+  color: #c9302c !important;
+}
+
+.text-gray-dark {
+  color: #373a3c !important;
+}
+
+a.text-gray-dark:focus, a.text-gray-dark:hover {
+  color: #1f2021 !important;
+}
+
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.invisible {
+  visibility: hidden !important;
+}
+
+.hidden-xs-up {
+  display: none !important;
+}
+
+@media (max-width: 575px) {
+  .hidden-xs-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 576px) {
+  .hidden-sm-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-sm-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .hidden-md-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 991px) {
+  .hidden-md-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .hidden-lg-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 1199px) {
+  .hidden-lg-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .hidden-xl-up {
+    display: none !important;
+  }
+}
+
+.hidden-xl-down {
+  display: none !important;
+}
+
+.visible-print-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+
+.visible-print-inline {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+
+.visible-print-inline-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
new file mode 100644
index 0000000..f3cf5be
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_custom.scss","../../scss/_tobago.scss","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_hover.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
new file mode 100644
index 0000000..99f2788
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.tobago-box-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center}.tobago-button>img{margin-top:-1px;margin-bottom:-1px}.tobago-collapsed.tobago-box .card-block,.tobago-collapsed.tobago-panel,.tobago-collapsed.tobago-section .tobago-section-content{display:none}.tobago-d [...]
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
new file mode 100644
index 0000000..fcaf1a0
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/_tobago.scss","dist/css/bootstrap.css","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_cle [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.js b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.js
new file mode 100644
index 0000000..0a37e60
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.js
@@ -0,0 +1,3430 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+if (typeof jQuery === 'undefined') {
+  throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+  var version = $.fn.jquery.split(' ')[0].split('.')
+  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {
+    throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
+  }
+}(jQuery);
+
+
++function () {
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) [...]
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): util.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Util = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Private TransitionEnd Helpers
+   * ------------------------------------------------------------------------
+   */
+
+  var transition = false;
+
+  var MAX_UID = 1000000;
+
+  var TransitionEndEvent = {
+    WebkitTransition: 'webkitTransitionEnd',
+    MozTransition: 'transitionend',
+    OTransition: 'oTransitionEnd otransitionend',
+    transition: 'transitionend'
+  };
+
+  // shoutout AngusCroll (https://goo.gl/pxwQGp)
+  function toType(obj) {
+    return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
+  }
+
+  function isElement(obj) {
+    return (obj[0] || obj).nodeType;
+  }
+
+  function getSpecialTransitionEndEvent() {
+    return {
+      bindType: transition.end,
+      delegateType: transition.end,
+      handle: function handle(event) {
+        if ($(event.target).is(this)) {
+          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
+        }
+        return undefined;
+      }
+    };
+  }
+
+  function transitionEndTest() {
+    if (window.QUnit) {
+      return false;
+    }
+
+    var el = document.createElement('bootstrap');
+
+    for (var name in TransitionEndEvent) {
+      if (el.style[name] !== undefined) {
+        return { end: TransitionEndEvent[name] };
+      }
+    }
+
+    return false;
+  }
+
+  function transitionEndEmulator(duration) {
+    var _this = this;
+
+    var called = false;
+
+    $(this).one(Util.TRANSITION_END, function () {
+      called = true;
+    });
+
+    setTimeout(function () {
+      if (!called) {
+        Util.triggerTransitionEnd(_this);
+      }
+    }, duration);
+
+    return this;
+  }
+
+  function setTransitionEndSupport() {
+    transition = transitionEndTest();
+
+    $.fn.emulateTransitionEnd = transitionEndEmulator;
+
+    if (Util.supportsTransitionEnd()) {
+      $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
+    }
+  }
+
+  /**
+   * --------------------------------------------------------------------------
+   * Public Util Api
+   * --------------------------------------------------------------------------
+   */
+
+  var Util = {
+
+    TRANSITION_END: 'bsTransitionEnd',
+
+    getUID: function getUID(prefix) {
+      do {
+        /* eslint-disable no-bitwise */
+        prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
+        /* eslint-enable no-bitwise */
+      } while (document.getElementById(prefix));
+      return prefix;
+    },
+    getSelectorFromElement: function getSelectorFromElement(element) {
+      var selector = element.getAttribute('data-target');
+
+      if (!selector) {
+        selector = element.getAttribute('href') || '';
+        selector = /^#[a-z]/i.test(selector) ? selector : null;
+      }
+
+      return selector;
+    },
+    reflow: function reflow(element) {
+      new Function('bs', 'return bs')(element.offsetHeight);
+    },
+    triggerTransitionEnd: function triggerTransitionEnd(element) {
+      $(element).trigger(transition.end);
+    },
+    supportsTransitionEnd: function supportsTransitionEnd() {
+      return Boolean(transition);
+    },
+    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
+      for (var property in configTypes) {
+        if (configTypes.hasOwnProperty(property)) {
+          var expectedTypes = configTypes[property];
+          var value = config[property];
+          var valueType = void 0;
+
+          if (value && isElement(value)) {
+            valueType = 'element';
+          } else {
+            valueType = toType(value);
+          }
+
+          if (!new RegExp(expectedTypes).test(valueType)) {
+            throw new Error(componentName.toUpperCase() + ': ' + ('Option "' + property + '" provided type "' + valueType + '" ') + ('but expected type "' + expectedTypes + '".'));
+          }
+        }
+      }
+    }
+  };
+
+  setTransitionEndSupport();
+
+  return Util;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): alert.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Alert = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'alert';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.alert';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Selector = {
+    DISMISS: '[data-dismiss="alert"]'
+  };
+
+  var Event = {
+    CLOSE: 'close' + EVENT_KEY,
+    CLOSED: 'closed' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    ALERT: 'alert',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Alert = function () {
+    function Alert(element) {
+      _classCallCheck(this, Alert);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Alert.prototype.close = function close(element) {
+      element = element || this._element;
+
+      var rootElement = this._getRootElement(element);
+      var customEvent = this._triggerCloseEvent(rootElement);
+
+      if (customEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._removeElement(rootElement);
+    };
+
+    Alert.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Alert.prototype._getRootElement = function _getRootElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      var parent = false;
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      if (!parent) {
+        parent = $(element).closest('.' + ClassName.ALERT)[0];
+      }
+
+      return parent;
+    };
+
+    Alert.prototype._triggerCloseEvent = function _triggerCloseEvent(element) {
+      var closeEvent = $.Event(Event.CLOSE);
+
+      $(element).trigger(closeEvent);
+      return closeEvent;
+    };
+
+    Alert.prototype._removeElement = function _removeElement(element) {
+      $(element).removeClass(ClassName.IN);
+
+      if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {
+        this._destroyElement(element);
+        return;
+      }
+
+      $(element).one(Util.TRANSITION_END, $.proxy(this._destroyElement, this, element)).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Alert.prototype._destroyElement = function _destroyElement(element) {
+      $(element).detach().trigger(Event.CLOSED).remove();
+    };
+
+    // static
+
+    Alert._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $element = $(this);
+        var data = $element.data(DATA_KEY);
+
+        if (!data) {
+          data = new Alert(this);
+          $element.data(DATA_KEY, data);
+        }
+
+        if (config === 'close') {
+          data[config](this);
+        }
+      });
+    };
+
+    Alert._handleDismiss = function _handleDismiss(alertInstance) {
+      return function (event) {
+        if (event) {
+          event.preventDefault();
+        }
+
+        alertInstance.close(this);
+      };
+    };
+
+    _createClass(Alert, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Alert;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Alert._jQueryInterface;
+  $.fn[NAME].Constructor = Alert;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Alert._jQueryInterface;
+  };
+
+  return Alert;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): button.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Button = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'button';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.button';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var ClassName = {
+    ACTIVE: 'active',
+    BUTTON: 'btn',
+    FOCUS: 'focus'
+  };
+
+  var Selector = {
+    DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
+    DATA_TOGGLE: '[data-toggle="buttons"]',
+    INPUT: 'input',
+    ACTIVE: '.active',
+    BUTTON: '.btn'
+  };
+
+  var Event = {
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    FOCUS_BLUR_DATA_API: 'focus' + EVENT_KEY + DATA_API_KEY + ' ' + ('blur' + EVENT_KEY + DATA_API_KEY)
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Button = function () {
+    function Button(element) {
+      _classCallCheck(this, Button);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Button.prototype.toggle = function toggle() {
+      var triggerChangeEvent = true;
+      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];
+
+      if (rootElement) {
+        var input = $(this._element).find(Selector.INPUT)[0];
+
+        if (input) {
+          if (input.type === 'radio') {
+            if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) {
+              triggerChangeEvent = false;
+            } else {
+              var activeElement = $(rootElement).find(Selector.ACTIVE)[0];
+
+              if (activeElement) {
+                $(activeElement).removeClass(ClassName.ACTIVE);
+              }
+            }
+          }
+
+          if (triggerChangeEvent) {
+            input.checked = !$(this._element).hasClass(ClassName.ACTIVE);
+            $(this._element).trigger('change');
+          }
+
+          input.focus();
+        }
+      } else {
+        this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));
+      }
+
+      if (triggerChangeEvent) {
+        $(this._element).toggleClass(ClassName.ACTIVE);
+      }
+    };
+
+    Button.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // static
+
+    Button._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          data = new Button(this);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (config === 'toggle') {
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Button, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Button;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    event.preventDefault();
+
+    var button = event.target;
+
+    if (!$(button).hasClass(ClassName.BUTTON)) {
+      button = $(button).closest(Selector.BUTTON);
+    }
+
+    Button._jQueryInterface.call($(button), 'toggle');
+  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    var button = $(event.target).closest(Selector.BUTTON)[0];
+    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Button._jQueryInterface;
+  $.fn[NAME].Constructor = Button;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Button._jQueryInterface;
+  };
+
+  return Button;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): carousel.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Carousel = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'carousel';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.carousel';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
+  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
+
+  var Default = {
+    interval: 5000,
+    keyboard: true,
+    slide: false,
+    pause: 'hover',
+    wrap: true
+  };
+
+  var DefaultType = {
+    interval: '(number|boolean)',
+    keyboard: 'boolean',
+    slide: '(boolean|string)',
+    pause: '(string|boolean)',
+    wrap: 'boolean'
+  };
+
+  var Direction = {
+    NEXT: 'next',
+    PREVIOUS: 'prev'
+  };
+
+  var Event = {
+    SLIDE: 'slide' + EVENT_KEY,
+    SLID: 'slid' + EVENT_KEY,
+    KEYDOWN: 'keydown' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    CAROUSEL: 'carousel',
+    ACTIVE: 'active',
+    SLIDE: 'slide',
+    RIGHT: 'right',
+    LEFT: 'left',
+    ITEM: 'carousel-item'
+  };
+
+  var Selector = {
+    ACTIVE: '.active',
+    ACTIVE_ITEM: '.active.carousel-item',
+    ITEM: '.carousel-item',
+    NEXT_PREV: '.next, .prev',
+    INDICATORS: '.carousel-indicators',
+    DATA_SLIDE: '[data-slide], [data-slide-to]',
+    DATA_RIDE: '[data-ride="carousel"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Carousel = function () {
+    function Carousel(element, config) {
+      _classCallCheck(this, Carousel);
+
+      this._items = null;
+      this._interval = null;
+      this._activeElement = null;
+
+      this._isPaused = false;
+      this._isSliding = false;
+
+      this._config = this._getConfig(config);
+      this._element = $(element)[0];
+      this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Carousel.prototype.next = function next() {
+      if (!this._isSliding) {
+        this._slide(Direction.NEXT);
+      }
+    };
+
+    Carousel.prototype.nextWhenVisible = function nextWhenVisible() {
+      // Don't call next when the page isn't visible
+      if (!document.hidden) {
+        this.next();
+      }
+    };
+
+    Carousel.prototype.prev = function prev() {
+      if (!this._isSliding) {
+        this._slide(Direction.PREVIOUS);
+      }
+    };
+
+    Carousel.prototype.pause = function pause(event) {
+      if (!event) {
+        this._isPaused = true;
+      }
+
+      if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {
+        Util.triggerTransitionEnd(this._element);
+        this.cycle(true);
+      }
+
+      clearInterval(this._interval);
+      this._interval = null;
+    };
+
+    Carousel.prototype.cycle = function cycle(event) {
+      if (!event) {
+        this._isPaused = false;
+      }
+
+      if (this._interval) {
+        clearInterval(this._interval);
+        this._interval = null;
+      }
+
+      if (this._config.interval && !this._isPaused) {
+        this._interval = setInterval($.proxy(document.visibilityState ? this.nextWhenVisible : this.next, this), this._config.interval);
+      }
+    };
+
+    Carousel.prototype.to = function to(index) {
+      var _this2 = this;
+
+      this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+
+      var activeIndex = this._getItemIndex(this._activeElement);
+
+      if (index > this._items.length - 1 || index < 0) {
+        return;
+      }
+
+      if (this._isSliding) {
+        $(this._element).one(Event.SLID, function () {
+          return _this2.to(index);
+        });
+        return;
+      }
+
+      if (activeIndex === index) {
+        this.pause();
+        this.cycle();
+        return;
+      }
+
+      var direction = index > activeIndex ? Direction.NEXT : Direction.PREVIOUS;
+
+      this._slide(direction, this._items[index]);
+    };
+
+    Carousel.prototype.dispose = function dispose() {
+      $(this._element).off(EVENT_KEY);
+      $.removeData(this._element, DATA_KEY);
+
+      this._items = null;
+      this._config = null;
+      this._element = null;
+      this._interval = null;
+      this._isPaused = null;
+      this._isSliding = null;
+      this._activeElement = null;
+      this._indicatorsElement = null;
+    };
+
+    // private
+
+    Carousel.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Carousel.prototype._addEventListeners = function _addEventListeners() {
+      if (this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN, $.proxy(this._keydown, this));
+      }
+
+      if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
+        $(this._element).on(Event.MOUSEENTER, $.proxy(this.pause, this)).on(Event.MOUSELEAVE, $.proxy(this.cycle, this));
+      }
+    };
+
+    Carousel.prototype._keydown = function _keydown(event) {
+      event.preventDefault();
+
+      if (/input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      switch (event.which) {
+        case ARROW_LEFT_KEYCODE:
+          this.prev();
+          break;
+        case ARROW_RIGHT_KEYCODE:
+          this.next();
+          break;
+        default:
+          return;
+      }
+    };
+
+    Carousel.prototype._getItemIndex = function _getItemIndex(element) {
+      this._items = $.makeArray($(element).parent().find(Selector.ITEM));
+      return this._items.indexOf(element);
+    };
+
+    Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) {
+      var isNextDirection = direction === Direction.NEXT;
+      var isPrevDirection = direction === Direction.PREVIOUS;
+      var activeIndex = this._getItemIndex(activeElement);
+      var lastItemIndex = this._items.length - 1;
+      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
+
+      if (isGoingToWrap && !this._config.wrap) {
+        return activeElement;
+      }
+
+      var delta = direction === Direction.PREVIOUS ? -1 : 1;
+      var itemIndex = (activeIndex + delta) % this._items.length;
+
+      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
+    };
+
+    Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, directionalClassname) {
+      var slideEvent = $.Event(Event.SLIDE, {
+        relatedTarget: relatedTarget,
+        direction: directionalClassname
+      });
+
+      $(this._element).trigger(slideEvent);
+
+      return slideEvent;
+    };
+
+    Carousel.prototype._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
+      if (this._indicatorsElement) {
+        $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+
+        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
+
+        if (nextIndicator) {
+          $(nextIndicator).addClass(ClassName.ACTIVE);
+        }
+      }
+    };
+
+    Carousel.prototype._slide = function _slide(direction, element) {
+      var _this3 = this;
+
+      var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
+
+      var isCycling = Boolean(this._interval);
+
+      var directionalClassName = direction === Direction.NEXT ? ClassName.LEFT : ClassName.RIGHT;
+
+      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {
+        this._isSliding = false;
+        return;
+      }
+
+      var slideEvent = this._triggerSlideEvent(nextElement, directionalClassName);
+      if (slideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (!activeElement || !nextElement) {
+        // some weirdness is happening, so we bail
+        return;
+      }
+
+      this._isSliding = true;
+
+      if (isCycling) {
+        this.pause();
+      }
+
+      this._setActiveIndicatorElement(nextElement);
+
+      var slidEvent = $.Event(Event.SLID, {
+        relatedTarget: nextElement,
+        direction: directionalClassName
+      });
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {
+
+        $(nextElement).addClass(direction);
+
+        Util.reflow(nextElement);
+
+        $(activeElement).addClass(directionalClassName);
+        $(nextElement).addClass(directionalClassName);
+
+        $(activeElement).one(Util.TRANSITION_END, function () {
+          $(nextElement).removeClass(directionalClassName).removeClass(direction);
+
+          $(nextElement).addClass(ClassName.ACTIVE);
+
+          $(activeElement).removeClass(ClassName.ACTIVE).removeClass(direction).removeClass(directionalClassName);
+
+          _this3._isSliding = false;
+
+          setTimeout(function () {
+            return $(_this3._element).trigger(slidEvent);
+          }, 0);
+        }).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        $(activeElement).removeClass(ClassName.ACTIVE);
+        $(nextElement).addClass(ClassName.ACTIVE);
+
+        this._isSliding = false;
+        $(this._element).trigger(slidEvent);
+      }
+
+      if (isCycling) {
+        this.cycle();
+      }
+    };
+
+    // static
+
+    Carousel._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Default, $(this).data());
+
+        if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
+          $.extend(_config, config);
+        }
+
+        var action = typeof config === 'string' ? config : _config.slide;
+
+        if (!data) {
+          data = new Carousel(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'number') {
+          data.to(config);
+        } else if (typeof action === 'string') {
+          if (data[action] === undefined) {
+            throw new Error('No method named "' + action + '"');
+          }
+          data[action]();
+        } else if (_config.interval) {
+          data.pause();
+          data.cycle();
+        }
+      });
+    };
+
+    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
+      var selector = Util.getSelectorFromElement(this);
+
+      if (!selector) {
+        return;
+      }
+
+      var target = $(selector)[0];
+
+      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {
+        return;
+      }
+
+      var config = $.extend({}, $(target).data(), $(this).data());
+      var slideIndex = this.getAttribute('data-slide-to');
+
+      if (slideIndex) {
+        config.interval = false;
+      }
+
+      Carousel._jQueryInterface.call($(target), config);
+
+      if (slideIndex) {
+        $(target).data(DATA_KEY).to(slideIndex);
+      }
+
+      event.preventDefault();
+    };
+
+    _createClass(Carousel, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Carousel;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    $(Selector.DATA_RIDE).each(function () {
+      var $carousel = $(this);
+      Carousel._jQueryInterface.call($carousel, $carousel.data());
+    });
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Carousel._jQueryInterface;
+  $.fn[NAME].Constructor = Carousel;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Carousel._jQueryInterface;
+  };
+
+  return Carousel;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): collapse.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Collapse = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'collapse';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.collapse';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+
+  var Default = {
+    toggle: true,
+    parent: ''
+  };
+
+  var DefaultType = {
+    toggle: 'boolean',
+    parent: 'string'
+  };
+
+  var Event = {
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    IN: 'in',
+    COLLAPSE: 'collapse',
+    COLLAPSING: 'collapsing',
+    COLLAPSED: 'collapsed'
+  };
+
+  var Dimension = {
+    WIDTH: 'width',
+    HEIGHT: 'height'
+  };
+
+  var Selector = {
+    ACTIVES: '.card > .in, .card > .collapsing',
+    DATA_TOGGLE: '[data-toggle="collapse"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Collapse = function () {
+    function Collapse(element, config) {
+      _classCallCheck(this, Collapse);
+
+      this._isTransitioning = false;
+      this._element = element;
+      this._config = this._getConfig(config);
+      this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
+
+      this._parent = this._config.parent ? this._getParent() : null;
+
+      if (!this._config.parent) {
+        this._addAriaAndCollapsedClass(this._element, this._triggerArray);
+      }
+
+      if (this._config.toggle) {
+        this.toggle();
+      }
+    }
+
+    // getters
+
+    // public
+
+    Collapse.prototype.toggle = function toggle() {
+      if ($(this._element).hasClass(ClassName.IN)) {
+        this.hide();
+      } else {
+        this.show();
+      }
+    };
+
+    Collapse.prototype.show = function show() {
+      var _this4 = this;
+
+      if (this._isTransitioning || $(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var actives = void 0;
+      var activesData = void 0;
+
+      if (this._parent) {
+        actives = $.makeArray($(Selector.ACTIVES));
+        if (!actives.length) {
+          actives = null;
+        }
+      }
+
+      if (actives) {
+        activesData = $(actives).data(DATA_KEY);
+        if (activesData && activesData._isTransitioning) {
+          return;
+        }
+      }
+
+      var startEvent = $.Event(Event.SHOW);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (actives) {
+        Collapse._jQueryInterface.call($(actives), 'hide');
+        if (!activesData) {
+          $(actives).data(DATA_KEY, null);
+        }
+      }
+
+      var dimension = this._getDimension();
+
+      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
+
+      this._element.style[dimension] = 0;
+      this._element.setAttribute('aria-expanded', true);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        $(_this4._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.IN);
+
+        _this4._element.style[dimension] = '';
+
+        _this4.setTransitioning(false);
+
+        $(_this4._element).trigger(Event.SHOWN);
+      };
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
+      var scrollSize = 'scroll' + capitalizedDimension;
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+
+      this._element.style[dimension] = this._element[scrollSize] + 'px';
+    };
+
+    Collapse.prototype.hide = function hide() {
+      var _this5 = this;
+
+      if (this._isTransitioning || !$(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var startEvent = $.Event(Event.HIDE);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      var dimension = this._getDimension();
+      var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight';
+
+      this._element.style[dimension] = this._element[offsetDimension] + 'px';
+
+      Util.reflow(this._element);
+
+      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.IN);
+
+      this._element.setAttribute('aria-expanded', false);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        _this5.setTransitioning(false);
+        $(_this5._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
+      };
+
+      this._element.style[dimension] = '';
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Collapse.prototype.setTransitioning = function setTransitioning(isTransitioning) {
+      this._isTransitioning = isTransitioning;
+    };
+
+    Collapse.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      this._config = null;
+      this._parent = null;
+      this._element = null;
+      this._triggerArray = null;
+      this._isTransitioning = null;
+    };
+
+    // private
+
+    Collapse.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      config.toggle = Boolean(config.toggle); // coerce string values
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Collapse.prototype._getDimension = function _getDimension() {
+      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);
+      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
+    };
+
+    Collapse.prototype._getParent = function _getParent() {
+      var _this6 = this;
+
+      var parent = $(this._config.parent)[0];
+      var selector = '[data-toggle="collapse"][data-parent="' + this._config.parent + '"]';
+
+      $(parent).find(selector).each(function (i, element) {
+        _this6._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
+      });
+
+      return parent;
+    };
+
+    Collapse.prototype._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
+      if (element) {
+        var isOpen = $(element).hasClass(ClassName.IN);
+        element.setAttribute('aria-expanded', isOpen);
+
+        if (triggerArray.length) {
+          $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
+        }
+      }
+    };
+
+    // static
+
+    Collapse._getTargetFromElement = function _getTargetFromElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      return selector ? $(selector)[0] : null;
+    };
+
+    Collapse._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+        var _config = $.extend({}, Default, $this.data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data && _config.toggle && /show|hide/.test(config)) {
+          _config.toggle = false;
+        }
+
+        if (!data) {
+          data = new Collapse(this, _config);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Collapse, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Collapse;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+
+    var target = Collapse._getTargetFromElement(this);
+    var data = $(target).data(DATA_KEY);
+    var config = data ? 'toggle' : $(this).data();
+
+    Collapse._jQueryInterface.call($(target), config);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Collapse._jQueryInterface;
+  $.fn[NAME].Constructor = Collapse;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Collapse._jQueryInterface;
+  };
+
+  return Collapse;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): dropdown.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Dropdown = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'dropdown';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.dropdown';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
+  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
+  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    BACKDROP: 'dropdown-backdrop',
+    DISABLED: 'disabled',
+    OPEN: 'open'
+  };
+
+  var Selector = {
+    BACKDROP: '.dropdown-backdrop',
+    DATA_TOGGLE: '[data-toggle="dropdown"]',
+    FORM_CHILD: '.dropdown form',
+    ROLE_MENU: '[role="menu"]',
+    ROLE_LISTBOX: '[role="listbox"]',
+    NAVBAR_NAV: '.navbar-nav',
+    VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Dropdown = function () {
+    function Dropdown(element) {
+      _classCallCheck(this, Dropdown);
+
+      this._element = element;
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Dropdown.prototype.toggle = function toggle() {
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return false;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      Dropdown._clearMenus();
+
+      if (isActive) {
+        return false;
+      }
+
+      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
+
+        // if mobile we use a backdrop because click events don't delegate
+        var dropdown = document.createElement('div');
+        dropdown.className = ClassName.BACKDROP;
+        $(dropdown).insertBefore(this);
+        $(dropdown).on('click', Dropdown._clearMenus);
+      }
+
+      var relatedTarget = { relatedTarget: this };
+      var showEvent = $.Event(Event.SHOW, relatedTarget);
+
+      $(parent).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented()) {
+        return false;
+      }
+
+      this.focus();
+      this.setAttribute('aria-expanded', 'true');
+
+      $(parent).toggleClass(ClassName.OPEN);
+      $(parent).trigger($.Event(Event.SHOWN, relatedTarget));
+
+      return false;
+    };
+
+    Dropdown.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._element).off(EVENT_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Dropdown.prototype._addEventListeners = function _addEventListeners() {
+      $(this._element).on(Event.CLICK, this.toggle);
+    };
+
+    // static
+
+    Dropdown._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          $(this).data(DATA_KEY, data = new Dropdown(this));
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config].call(this);
+        }
+      });
+    };
+
+    Dropdown._clearMenus = function _clearMenus(event) {
+      if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
+        return;
+      }
+
+      var backdrop = $(Selector.BACKDROP)[0];
+      if (backdrop) {
+        backdrop.parentNode.removeChild(backdrop);
+      }
+
+      var toggles = $.makeArray($(Selector.DATA_TOGGLE));
+
+      for (var i = 0; i < toggles.length; i++) {
+        var parent = Dropdown._getParentFromElement(toggles[i]);
+        var relatedTarget = { relatedTarget: toggles[i] };
+
+        if (!$(parent).hasClass(ClassName.OPEN)) {
+          continue;
+        }
+
+        if (event && event.type === 'click' && /input|textarea/i.test(event.target.tagName) && $.contains(parent, event.target)) {
+          continue;
+        }
+
+        var hideEvent = $.Event(Event.HIDE, relatedTarget);
+        $(parent).trigger(hideEvent);
+        if (hideEvent.isDefaultPrevented()) {
+          continue;
+        }
+
+        toggles[i].setAttribute('aria-expanded', 'false');
+
+        $(parent).removeClass(ClassName.OPEN).trigger($.Event(Event.HIDDEN, relatedTarget));
+      }
+    };
+
+    Dropdown._getParentFromElement = function _getParentFromElement(element) {
+      var parent = void 0;
+      var selector = Util.getSelectorFromElement(element);
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      return parent || element.parentNode;
+    };
+
+    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
+      if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      event.preventDefault();
+      event.stopPropagation();
+
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {
+
+        if (event.which === ESCAPE_KEYCODE) {
+          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
+          $(toggle).trigger('focus');
+        }
+
+        $(this).trigger('click');
+        return;
+      }
+
+      var items = $.makeArray($(Selector.VISIBLE_ITEMS));
+
+      items = items.filter(function (item) {
+        return item.offsetWidth || item.offsetHeight;
+      });
+
+      if (!items.length) {
+        return;
+      }
+
+      var index = items.indexOf(event.target);
+
+      if (event.which === ARROW_UP_KEYCODE && index > 0) {
+        // up
+        index--;
+      }
+
+      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
+        // down
+        index++;
+      }
+
+      if (index < 0) {
+        index = 0;
+      }
+
+      items[index].focus();
+    };
+
+    _createClass(Dropdown, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Dropdown;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
+    e.stopPropagation();
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Dropdown._jQueryInterface;
+  $.fn[NAME].Constructor = Dropdown;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Dropdown._jQueryInterface;
+  };
+
+  return Dropdown;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): modal.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Modal = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'modal';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.modal';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 300;
+  var BACKDROP_TRANSITION_DURATION = 150;
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+
+  var Default = {
+    backdrop: true,
+    keyboard: true,
+    focus: true,
+    show: true
+  };
+
+  var DefaultType = {
+    backdrop: '(boolean|string)',
+    keyboard: 'boolean',
+    focus: 'boolean',
+    show: 'boolean'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    RESIZE: 'resize' + EVENT_KEY,
+    CLICK_DISMISS: 'click.dismiss' + EVENT_KEY,
+    KEYDOWN_DISMISS: 'keydown.dismiss' + EVENT_KEY,
+    MOUSEUP_DISMISS: 'mouseup.dismiss' + EVENT_KEY,
+    MOUSEDOWN_DISMISS: 'mousedown.dismiss' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
+    BACKDROP: 'modal-backdrop',
+    OPEN: 'modal-open',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    DIALOG: '.modal-dialog',
+    DATA_TOGGLE: '[data-toggle="modal"]',
+    DATA_DISMISS: '[data-dismiss="modal"]',
+    FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Modal = function () {
+    function Modal(element, config) {
+      _classCallCheck(this, Modal);
+
+      this._config = this._getConfig(config);
+      this._element = element;
+      this._dialog = $(element).find(Selector.DIALOG)[0];
+      this._backdrop = null;
+      this._isShown = false;
+      this._isBodyOverflowing = false;
+      this._ignoreBackdropClick = false;
+      this._originalBodyPadding = 0;
+      this._scrollbarWidth = 0;
+    }
+
+    // getters
+
+    // public
+
+    Modal.prototype.toggle = function toggle(relatedTarget) {
+      return this._isShown ? this.hide() : this.show(relatedTarget);
+    };
+
+    Modal.prototype.show = function show(relatedTarget) {
+      var _this7 = this;
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: relatedTarget
+      });
+
+      $(this._element).trigger(showEvent);
+
+      if (this._isShown || showEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = true;
+
+      this._checkScrollbar();
+      this._setScrollbar();
+
+      $(document.body).addClass(ClassName.OPEN);
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, $.proxy(this.hide, this));
+
+      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
+        $(_this7._element).one(Event.MOUSEUP_DISMISS, function (event) {
+          if ($(event.target).is(_this7._element)) {
+            _this7._ignoreBackdropClick = true;
+          }
+        });
+      });
+
+      this._showBackdrop($.proxy(this._showElement, this, relatedTarget));
+    };
+
+    Modal.prototype.hide = function hide(event) {
+      if (event) {
+        event.preventDefault();
+      }
+
+      var hideEvent = $.Event(Event.HIDE);
+
+      $(this._element).trigger(hideEvent);
+
+      if (!this._isShown || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = false;
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(document).off(Event.FOCUSIN);
+
+      $(this._element).removeClass(ClassName.IN);
+
+      $(this._element).off(Event.CLICK_DISMISS);
+      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+
+        $(this._element).one(Util.TRANSITION_END, $.proxy(this._hideModal, this)).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        this._hideModal();
+      }
+    };
+
+    Modal.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      $(window).off(EVENT_KEY);
+      $(document).off(EVENT_KEY);
+      $(this._element).off(EVENT_KEY);
+      $(this._backdrop).off(EVENT_KEY);
+
+      this._config = null;
+      this._element = null;
+      this._dialog = null;
+      this._backdrop = null;
+      this._isShown = null;
+      this._isBodyOverflowing = null;
+      this._ignoreBackdropClick = null;
+      this._originalBodyPadding = null;
+      this._scrollbarWidth = null;
+    };
+
+    // private
+
+    Modal.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Modal.prototype._showElement = function _showElement(relatedTarget) {
+      var _this8 = this;
+
+      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);
+
+      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
+        // don't move modals dom position
+        document.body.appendChild(this._element);
+      }
+
+      this._element.style.display = 'block';
+      this._element.removeAttribute('aria-hidden');
+      this._element.scrollTop = 0;
+
+      if (transition) {
+        Util.reflow(this._element);
+      }
+
+      $(this._element).addClass(ClassName.IN);
+
+      if (this._config.focus) {
+        this._enforceFocus();
+      }
+
+      var shownEvent = $.Event(Event.SHOWN, {
+        relatedTarget: relatedTarget
+      });
+
+      var transitionComplete = function transitionComplete() {
+        if (_this8._config.focus) {
+          _this8._element.focus();
+        }
+        $(_this8._element).trigger(shownEvent);
+      };
+
+      if (transition) {
+        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        transitionComplete();
+      }
+    };
+
+    Modal.prototype._enforceFocus = function _enforceFocus() {
+      var _this9 = this;
+
+      $(document).off(Event.FOCUSIN) // guard against infinite focus loop
+      .on(Event.FOCUSIN, function (event) {
+        if (document !== event.target && _this9._element !== event.target && !$(_this9._element).has(event.target).length) {
+          _this9._element.focus();
+        }
+      });
+    };
+
+    Modal.prototype._setEscapeEvent = function _setEscapeEvent() {
+      var _this10 = this;
+
+      if (this._isShown && this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
+          if (event.which === ESCAPE_KEYCODE) {
+            _this10.hide();
+          }
+        });
+      } else if (!this._isShown) {
+        $(this._element).off(Event.KEYDOWN_DISMISS);
+      }
+    };
+
+    Modal.prototype._setResizeEvent = function _setResizeEvent() {
+      if (this._isShown) {
+        $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this));
+      } else {
+        $(window).off(Event.RESIZE);
+      }
+    };
+
+    Modal.prototype._hideModal = function _hideModal() {
+      var _this11 = this;
+
+      this._element.style.display = 'none';
+      this._element.setAttribute('aria-hidden', 'true');
+      this._showBackdrop(function () {
+        $(document.body).removeClass(ClassName.OPEN);
+        _this11._resetAdjustments();
+        _this11._resetScrollbar();
+        $(_this11._element).trigger(Event.HIDDEN);
+      });
+    };
+
+    Modal.prototype._removeBackdrop = function _removeBackdrop() {
+      if (this._backdrop) {
+        $(this._backdrop).remove();
+        this._backdrop = null;
+      }
+    };
+
+    Modal.prototype._showBackdrop = function _showBackdrop(callback) {
+      var _this12 = this;
+
+      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
+
+      if (this._isShown && this._config.backdrop) {
+        var doAnimate = Util.supportsTransitionEnd() && animate;
+
+        this._backdrop = document.createElement('div');
+        this._backdrop.className = ClassName.BACKDROP;
+
+        if (animate) {
+          $(this._backdrop).addClass(animate);
+        }
+
+        $(this._backdrop).appendTo(document.body);
+
+        $(this._element).on(Event.CLICK_DISMISS, function (event) {
+          if (_this12._ignoreBackdropClick) {
+            _this12._ignoreBackdropClick = false;
+            return;
+          }
+          if (event.target !== event.currentTarget) {
+            return;
+          }
+          if (_this12._config.backdrop === 'static') {
+            _this12._element.focus();
+          } else {
+            _this12.hide();
+          }
+        });
+
+        if (doAnimate) {
+          Util.reflow(this._backdrop);
+        }
+
+        $(this._backdrop).addClass(ClassName.IN);
+
+        if (!callback) {
+          return;
+        }
+
+        if (!doAnimate) {
+          callback();
+          return;
+        }
+
+        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+      } else if (!this._isShown && this._backdrop) {
+        $(this._backdrop).removeClass(ClassName.IN);
+
+        var callbackRemove = function callbackRemove() {
+          _this12._removeBackdrop();
+          if (callback) {
+            callback();
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+        } else {
+          callbackRemove();
+        }
+      } else if (callback) {
+        callback();
+      }
+    };
+
+    // ----------------------------------------------------------------------
+    // the following methods are used to handle overflowing modals
+    // todo (fat): these should probably be refactored out of modal.js
+    // ----------------------------------------------------------------------
+
+    Modal.prototype._handleUpdate = function _handleUpdate() {
+      this._adjustDialog();
+    };
+
+    Modal.prototype._adjustDialog = function _adjustDialog() {
+      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+      if (!this._isBodyOverflowing && isModalOverflowing) {
+        this._element.style.paddingLeft = this._scrollbarWidth + 'px';
+      }
+
+      if (this._isBodyOverflowing && !isModalOverflowing) {
+        this._element.style.paddingRight = this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetAdjustments = function _resetAdjustments() {
+      this._element.style.paddingLeft = '';
+      this._element.style.paddingRight = '';
+    };
+
+    Modal.prototype._checkScrollbar = function _checkScrollbar() {
+      this._isBodyOverflowing = document.body.clientWidth < window.innerWidth;
+      this._scrollbarWidth = this._getScrollbarWidth();
+    };
+
+    Modal.prototype._setScrollbar = function _setScrollbar() {
+      var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10);
+
+      this._originalBodyPadding = document.body.style.paddingRight || '';
+
+      if (this._isBodyOverflowing) {
+        document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetScrollbar = function _resetScrollbar() {
+      document.body.style.paddingRight = this._originalBodyPadding;
+    };
+
+    Modal.prototype._getScrollbarWidth = function _getScrollbarWidth() {
+      // thx d.walsh
+      var scrollDiv = document.createElement('div');
+      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
+      document.body.appendChild(scrollDiv);
+      var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+      document.body.removeChild(scrollDiv);
+      return scrollbarWidth;
+    };
+
+    // static
+
+    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Modal.Default, $(this).data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data) {
+          data = new Modal(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config](relatedTarget);
+        } else if (_config.show) {
+          data.show(relatedTarget);
+        }
+      });
+    };
+
+    _createClass(Modal, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Modal;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    var _this13 = this;
+
+    var target = void 0;
+    var selector = Util.getSelectorFromElement(this);
+
+    if (selector) {
+      target = $(selector)[0];
+    }
+
+    var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data());
+
+    if (this.tagName === 'A') {
+      event.preventDefault();
+    }
+
+    var $target = $(target).one(Event.SHOW, function (showEvent) {
+      if (showEvent.isDefaultPrevented()) {
+        // only register focus restorer if modal will actually get shown
+        return;
+      }
+
+      $target.one(Event.HIDDEN, function () {
+        if ($(_this13).is(':visible')) {
+          _this13.focus();
+        }
+      });
+    });
+
+    Modal._jQueryInterface.call($(target), config, this);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Modal._jQueryInterface;
+  $.fn[NAME].Constructor = Modal;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Modal._jQueryInterface;
+  };
+
+  return Modal;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): scrollspy.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var ScrollSpy = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'scrollspy';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.scrollspy';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = {
+    offset: 10,
+    method: 'auto',
+    target: ''
+  };
+
+  var DefaultType = {
+    offset: 'number',
+    method: 'string',
+    target: '(string|element)'
+  };
+
+  var Event = {
+    ACTIVATE: 'activate' + EVENT_KEY,
+    SCROLL: 'scroll' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_ITEM: 'dropdown-item',
+    DROPDOWN_MENU: 'dropdown-menu',
+    NAV_LINK: 'nav-link',
+    NAV: 'nav',
+    ACTIVE: 'active'
+  };
+
+  var Selector = {
+    DATA_SPY: '[data-spy="scroll"]',
+    ACTIVE: '.active',
+    LIST_ITEM: '.list-item',
+    LI: 'li',
+    LI_DROPDOWN: 'li.dropdown',
+    NAV_LINKS: '.nav-link',
+    DROPDOWN: '.dropdown',
+    DROPDOWN_ITEMS: '.dropdown-item',
+    DROPDOWN_TOGGLE: '.dropdown-toggle'
+  };
+
+  var OffsetMethod = {
+    OFFSET: 'offset',
+    POSITION: 'position'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var ScrollSpy = function () {
+    function ScrollSpy(element, config) {
+      _classCallCheck(this, ScrollSpy);
+
+      this._element = element;
+      this._scrollElement = element.tagName === 'BODY' ? window : element;
+      this._config = this._getConfig(config);
+      this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
+      this._offsets = [];
+      this._targets = [];
+      this._activeTarget = null;
+      this._scrollHeight = 0;
+
+      $(this._scrollElement).on(Event.SCROLL, $.proxy(this._process, this));
+
+      this.refresh();
+      this._process();
+    }
+
+    // getters
+
+    // public
+
+    ScrollSpy.prototype.refresh = function refresh() {
+      var _this14 = this;
+
+      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
+
+      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
+
+      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
+
+      this._offsets = [];
+      this._targets = [];
+
+      this._scrollHeight = this._getScrollHeight();
+
+      var targets = $.makeArray($(this._selector));
+
+      targets.map(function (element) {
+        var target = void 0;
+        var targetSelector = Util.getSelectorFromElement(element);
+
+        if (targetSelector) {
+          target = $(targetSelector)[0];
+        }
+
+        if (target && (target.offsetWidth || target.offsetHeight)) {
+          // todo (fat): remove sketch reliance on jQuery position/offset
+          return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
+        }
+        return null;
+      }).filter(function (item) {
+        return item;
+      }).sort(function (a, b) {
+        return a[0] - b[0];
+      }).forEach(function (item) {
+        _this14._offsets.push(item[0]);
+        _this14._targets.push(item[1]);
+      });
+    };
+
+    ScrollSpy.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._scrollElement).off(EVENT_KEY);
+
+      this._element = null;
+      this._scrollElement = null;
+      this._config = null;
+      this._selector = null;
+      this._offsets = null;
+      this._targets = null;
+      this._activeTarget = null;
+      this._scrollHeight = null;
+    };
+
+    // private
+
+    ScrollSpy.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+
+      if (typeof config.target !== 'string') {
+        var id = $(config.target).attr('id');
+        if (!id) {
+          id = Util.getUID(NAME);
+          $(config.target).attr('id', id);
+        }
+        config.target = '#' + id;
+      }
+
+      Util.typeCheckConfig(NAME, config, DefaultType);
+
+      return config;
+    };
+
+    ScrollSpy.prototype._getScrollTop = function _getScrollTop() {
+      return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
+    };
+
+    ScrollSpy.prototype._getScrollHeight = function _getScrollHeight() {
+      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
+    };
+
+    ScrollSpy.prototype._process = function _process() {
+      var scrollTop = this._getScrollTop() + this._config.offset;
+      var scrollHeight = this._getScrollHeight();
+      var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight;
+
+      if (this._scrollHeight !== scrollHeight) {
+        this.refresh();
+      }
+
+      if (scrollTop >= maxScroll) {
+        var target = this._targets[this._targets.length - 1];
+
+        if (this._activeTarget !== target) {
+          this._activate(target);
+        }
+      }
+
+      if (this._activeTarget && scrollTop < this._offsets[0]) {
+        this._activeTarget = null;
+        this._clear();
+        return;
+      }
+
+      for (var i = this._offsets.length; i--;) {
+        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (this._offsets[i + 1] === undefined || scrollTop < this._offsets[i + 1]);
+
+        if (isActiveTarget) {
+          this._activate(this._targets[i]);
+        }
+      }
+    };
+
+    ScrollSpy.prototype._activate = function _activate(target) {
+      this._activeTarget = target;
+
+      this._clear();
+
+      var queries = this._selector.split(',');
+      queries = queries.map(function (selector) {
+        return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
+      });
+
+      var $link = $(queries.join(','));
+
+      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
+        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        $link.addClass(ClassName.ACTIVE);
+      } else {
+        // todo (fat) this is kinda sus...
+        // recursively add actives to tested nav-links
+        $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
+      }
+
+      $(this._scrollElement).trigger(Event.ACTIVATE, {
+        relatedTarget: target
+      });
+    };
+
+    ScrollSpy.prototype._clear = function _clear() {
+      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+    };
+
+    // static
+
+    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config || null;
+
+        if (!data) {
+          data = new ScrollSpy(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(ScrollSpy, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return ScrollSpy;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    var scrollSpys = $.makeArray($(Selector.DATA_SPY));
+
+    for (var i = scrollSpys.length; i--;) {
+      var $spy = $(scrollSpys[i]);
+      ScrollSpy._jQueryInterface.call($spy, $spy.data());
+    }
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = ScrollSpy._jQueryInterface;
+  $.fn[NAME].Constructor = ScrollSpy;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return ScrollSpy._jQueryInterface;
+  };
+
+  return ScrollSpy;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tab.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tab = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tab';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tab';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_MENU: 'dropdown-menu',
+    ACTIVE: 'active',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    A: 'a',
+    LI: 'li',
+    DROPDOWN: '.dropdown',
+    UL: 'ul:not(.dropdown-menu)',
+    FADE_CHILD: '> .nav-item .fade, > .fade',
+    ACTIVE: '.active',
+    ACTIVE_CHILD: '> .nav-item > .active, > .active',
+    DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"]',
+    DROPDOWN_TOGGLE: '.dropdown-toggle',
+    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tab = function () {
+    function Tab(element) {
+      _classCallCheck(this, Tab);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Tab.prototype.show = function show() {
+      var _this15 = this;
+
+      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE)) {
+        return;
+      }
+
+      var target = void 0;
+      var previous = void 0;
+      var ulElement = $(this._element).closest(Selector.UL)[0];
+      var selector = Util.getSelectorFromElement(this._element);
+
+      if (ulElement) {
+        previous = $.makeArray($(ulElement).find(Selector.ACTIVE));
+        previous = previous[previous.length - 1];
+      }
+
+      var hideEvent = $.Event(Event.HIDE, {
+        relatedTarget: this._element
+      });
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: previous
+      });
+
+      if (previous) {
+        $(previous).trigger(hideEvent);
+      }
+
+      $(this._element).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (selector) {
+        target = $(selector)[0];
+      }
+
+      this._activate(this._element, ulElement);
+
+      var complete = function complete() {
+        var hiddenEvent = $.Event(Event.HIDDEN, {
+          relatedTarget: _this15._element
+        });
+
+        var shownEvent = $.Event(Event.SHOWN, {
+          relatedTarget: previous
+        });
+
+        $(previous).trigger(hiddenEvent);
+        $(_this15._element).trigger(shownEvent);
+      };
+
+      if (target) {
+        this._activate(target, target.parentNode, complete);
+      } else {
+        complete();
+      }
+    };
+
+    Tab.prototype.dispose = function dispose() {
+      $.removeClass(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Tab.prototype._activate = function _activate(element, container, callback) {
+      var active = $(container).find(Selector.ACTIVE_CHILD)[0];
+      var isTransitioning = callback && Util.supportsTransitionEnd() && (active && $(active).hasClass(ClassName.FADE) || Boolean($(container).find(Selector.FADE_CHILD)[0]));
+
+      var complete = $.proxy(this._transitionComplete, this, element, active, isTransitioning, callback);
+
+      if (active && isTransitioning) {
+        $(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      if (active) {
+        $(active).removeClass(ClassName.IN);
+      }
+    };
+
+    Tab.prototype._transitionComplete = function _transitionComplete(element, active, isTransitioning, callback) {
+      if (active) {
+        $(active).removeClass(ClassName.ACTIVE);
+
+        var dropdownChild = $(active).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
+
+        if (dropdownChild) {
+          $(dropdownChild).removeClass(ClassName.ACTIVE);
+        }
+
+        active.setAttribute('aria-expanded', false);
+      }
+
+      $(element).addClass(ClassName.ACTIVE);
+      element.setAttribute('aria-expanded', true);
+
+      if (isTransitioning) {
+        Util.reflow(element);
+        $(element).addClass(ClassName.IN);
+      } else {
+        $(element).removeClass(ClassName.FADE);
+      }
+
+      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
+
+        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];
+        if (dropdownElement) {
+          $(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        }
+
+        element.setAttribute('aria-expanded', true);
+      }
+
+      if (callback) {
+        callback();
+      }
+    };
+
+    // static
+
+    Tab._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+
+        if (!data) {
+          data = data = new Tab(this);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tab, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Tab;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+    Tab._jQueryInterface.call($(this), 'show');
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tab._jQueryInterface;
+  $.fn[NAME].Constructor = Tab;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tab._jQueryInterface;
+  };
+
+  return Tab;
+}(jQuery);
+
+/* global Tether */
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tooltip.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tooltip = function ($) {
+
+  /**
+   * Check for Tether dependency
+   * Tether - http://tether.io/
+   */
+  if (window.Tether === undefined) {
+    throw new Error('Bootstrap tooltips require Tether (http://tether.io/)');
+  }
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tooltip';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tooltip';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+  var CLASS_PREFIX = 'bs-tether';
+
+  var Default = {
+    animation: true,
+    template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    selector: false,
+    placement: 'top',
+    offset: '0 0',
+    constraints: []
+  };
+
+  var DefaultType = {
+    animation: 'boolean',
+    template: 'string',
+    title: '(string|element|function)',
+    trigger: 'string',
+    delay: '(number|object)',
+    html: 'boolean',
+    selector: '(string|boolean)',
+    placement: '(string|function)',
+    offset: 'string',
+    constraints: 'array'
+  };
+
+  var AttachmentMap = {
+    TOP: 'bottom center',
+    RIGHT: 'middle left',
+    BOTTOM: 'top center',
+    LEFT: 'middle right'
+  };
+
+  var HoverState = {
+    IN: 'in',
+    OUT: 'out'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TOOLTIP: '.tooltip',
+    TOOLTIP_INNER: '.tooltip-inner'
+  };
+
+  var TetherClass = {
+    element: false,
+    enabled: false
+  };
+
+  var Trigger = {
+    HOVER: 'hover',
+    FOCUS: 'focus',
+    CLICK: 'click',
+    MANUAL: 'manual'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tooltip = function () {
+    function Tooltip(element, config) {
+      _classCallCheck(this, Tooltip);
+
+      // private
+      this._isEnabled = true;
+      this._timeout = 0;
+      this._hoverState = '';
+      this._activeTrigger = {};
+      this._tether = null;
+
+      // protected
+      this.element = element;
+      this.config = this._getConfig(config);
+      this.tip = null;
+
+      this._setListeners();
+    }
+
+    // getters
+
+    // public
+
+    Tooltip.prototype.enable = function enable() {
+      this._isEnabled = true;
+    };
+
+    Tooltip.prototype.disable = function disable() {
+      this._isEnabled = false;
+    };
+
+    Tooltip.prototype.toggleEnabled = function toggleEnabled() {
+      this._isEnabled = !this._isEnabled;
+    };
+
+    Tooltip.prototype.toggle = function toggle(event) {
+      if (event) {
+        var dataKey = this.constructor.DATA_KEY;
+        var context = $(event.currentTarget).data(dataKey);
+
+        if (!context) {
+          context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+          $(event.currentTarget).data(dataKey, context);
+        }
+
+        context._activeTrigger.click = !context._activeTrigger.click;
+
+        if (context._isWithActiveTrigger()) {
+          context._enter(null, context);
+        } else {
+          context._leave(null, context);
+        }
+      } else {
+
+        if ($(this.getTipElement()).hasClass(ClassName.IN)) {
+          this._leave(null, this);
+          return;
+        }
+
+        this._enter(null, this);
+      }
+    };
+
+    Tooltip.prototype.dispose = function dispose() {
+      clearTimeout(this._timeout);
+
+      this.cleanupTether();
+
+      $.removeData(this.element, this.constructor.DATA_KEY);
+
+      $(this.element).off(this.constructor.EVENT_KEY);
+
+      if (this.tip) {
+        $(this.tip).remove();
+      }
+
+      this._isEnabled = null;
+      this._timeout = null;
+      this._hoverState = null;
+      this._activeTrigger = null;
+      this._tether = null;
+
+      this.element = null;
+      this.config = null;
+      this.tip = null;
+    };
+
+    Tooltip.prototype.show = function show() {
+      var _this16 = this;
+
+      var showEvent = $.Event(this.constructor.Event.SHOW);
+
+      if (this.isWithContent() && this._isEnabled) {
+        $(this.element).trigger(showEvent);
+
+        var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
+
+        if (showEvent.isDefaultPrevented() || !isInTheDom) {
+          return;
+        }
+
+        var tip = this.getTipElement();
+        var tipId = Util.getUID(this.constructor.NAME);
+
+        tip.setAttribute('id', tipId);
+        this.element.setAttribute('aria-describedby', tipId);
+
+        this.setContent();
+
+        if (this.config.animation) {
+          $(tip).addClass(ClassName.FADE);
+        }
+
+        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
+
+        var attachment = this._getAttachment(placement);
+
+        $(tip).data(this.constructor.DATA_KEY, this).appendTo(document.body);
+
+        $(this.element).trigger(this.constructor.Event.INSERTED);
+
+        this._tether = new Tether({
+          attachment: attachment,
+          element: tip,
+          target: this.element,
+          classes: TetherClass,
+          classPrefix: CLASS_PREFIX,
+          offset: this.config.offset,
+          constraints: this.config.constraints,
+          addTargetClasses: false
+        });
+
+        Util.reflow(tip);
+        this._tether.position();
+
+        $(tip).addClass(ClassName.IN);
+
+        var complete = function complete() {
+          var prevHoverState = _this16._hoverState;
+          _this16._hoverState = null;
+
+          $(_this16.element).trigger(_this16.constructor.Event.SHOWN);
+
+          if (prevHoverState === HoverState.OUT) {
+            _this16._leave(null, _this16);
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
+          return;
+        }
+
+        complete();
+      }
+    };
+
+    Tooltip.prototype.hide = function hide(callback) {
+      var _this17 = this;
+
+      var tip = this.getTipElement();
+      var hideEvent = $.Event(this.constructor.Event.HIDE);
+      var complete = function complete() {
+        if (_this17._hoverState !== HoverState.IN && tip.parentNode) {
+          tip.parentNode.removeChild(tip);
+        }
+
+        _this17.element.removeAttribute('aria-describedby');
+        $(_this17.element).trigger(_this17.constructor.Event.HIDDEN);
+        _this17.cleanupTether();
+
+        if (callback) {
+          callback();
+        }
+      };
+
+      $(this.element).trigger(hideEvent);
+
+      if (hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      $(tip).removeClass(ClassName.IN);
+
+      if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+
+        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      this._hoverState = '';
+    };
+
+    // protected
+
+    Tooltip.prototype.isWithContent = function isWithContent() {
+      return Boolean(this.getTitle());
+    };
+
+    Tooltip.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Tooltip.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    Tooltip.prototype.setElementContent = function setElementContent($element, content) {
+      var html = this.config.html;
+      if ((typeof content === 'undefined' ? 'undefined' : _typeof(content)) === 'object' && (content.nodeType || content.jquery)) {
+        // content is a DOM node or a jQuery
+        if (html) {
+          if (!$(content).parent().is($element)) {
+            $element.empty().append(content);
+          }
+        } else {
+          $element.text($(content).text());
+        }
+      } else {
+        $element[html ? 'html' : 'text'](content);
+      }
+    };
+
+    Tooltip.prototype.getTitle = function getTitle() {
+      var title = this.element.getAttribute('data-original-title');
+
+      if (!title) {
+        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
+      }
+
+      return title;
+    };
+
+    Tooltip.prototype.cleanupTether = function cleanupTether() {
+      if (this._tether) {
+        this._tether.destroy();
+      }
+    };
+
+    // private
+
+    Tooltip.prototype._getAttachment = function _getAttachment(placement) {
+      return AttachmentMap[placement.toUpperCase()];
+    };
+
+    Tooltip.prototype._setListeners = function _setListeners() {
+      var _this18 = this;
+
+      var triggers = this.config.trigger.split(' ');
+
+      triggers.forEach(function (trigger) {
+        if (trigger === 'click') {
+          $(_this18.element).on(_this18.constructor.Event.CLICK, _this18.config.selector, $.proxy(_this18.toggle, _this18));
+        } else if (trigger !== Trigger.MANUAL) {
+          var eventIn = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSEENTER : _this18.constructor.Event.FOCUSIN;
+          var eventOut = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSELEAVE : _this18.constructor.Event.FOCUSOUT;
+
+          $(_this18.element).on(eventIn, _this18.config.selector, $.proxy(_this18._enter, _this18)).on(eventOut, _this18.config.selector, $.proxy(_this18._leave, _this18));
+        }
+      });
+
+      if (this.config.selector) {
+        this.config = $.extend({}, this.config, {
+          trigger: 'manual',
+          selector: ''
+        });
+      } else {
+        this._fixTitle();
+      }
+    };
+
+    Tooltip.prototype._fixTitle = function _fixTitle() {
+      var titleType = _typeof(this.element.getAttribute('data-original-title'));
+      if (this.element.getAttribute('title') || titleType !== 'string') {
+        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
+        this.element.setAttribute('title', '');
+      }
+    };
+
+    Tooltip.prototype._enter = function _enter(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
+      }
+
+      if ($(context.getTipElement()).hasClass(ClassName.IN) || context._hoverState === HoverState.IN) {
+        context._hoverState = HoverState.IN;
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.IN;
+
+      if (!context.config.delay || !context.config.delay.show) {
+        context.show();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.IN) {
+          context.show();
+        }
+      }, context.config.delay.show);
+    };
+
+    Tooltip.prototype._leave = function _leave(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
+      }
+
+      if (context._isWithActiveTrigger()) {
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.OUT;
+
+      if (!context.config.delay || !context.config.delay.hide) {
+        context.hide();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.OUT) {
+          context.hide();
+        }
+      }, context.config.delay.hide);
+    };
+
+    Tooltip.prototype._isWithActiveTrigger = function _isWithActiveTrigger() {
+      for (var trigger in this._activeTrigger) {
+        if (this._activeTrigger[trigger]) {
+          return true;
+        }
+      }
+
+      return false;
+    };
+
+    Tooltip.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, this.constructor.Default, $(this.element).data(), config);
+
+      if (config.delay && typeof config.delay === 'number') {
+        config.delay = {
+          show: config.delay,
+          hide: config.delay
+        };
+      }
+
+      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
+
+      return config;
+    };
+
+    Tooltip.prototype._getDelegateConfig = function _getDelegateConfig() {
+      var config = {};
+
+      if (this.config) {
+        for (var key in this.config) {
+          if (this.constructor.Default[key] !== this.config[key]) {
+            config[key] = this.config[key];
+          }
+        }
+      }
+
+      return config;
+    };
+
+    // static
+
+    Tooltip._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /dispose|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Tooltip(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tooltip, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Tooltip;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tooltip._jQueryInterface;
+  $.fn[NAME].Constructor = Tooltip;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tooltip._jQueryInterface;
+  };
+
+  return Tooltip;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Popover = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'popover';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.popover';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = $.extend({}, Tooltip.Default, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip">' + '<h3 class="popover-title"></h3>' + '<div class="popover-content"></div></div>'
+  });
+
+  var DefaultType = $.extend({}, Tooltip.DefaultType, {
+    content: '(string|element|function)'
+  });
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TITLE: '.popover-title',
+    CONTENT: '.popover-content'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Popover = function (_Tooltip) {
+    _inherits(Popover, _Tooltip);
+
+    function Popover() {
+      _classCallCheck(this, Popover);
+
+      return _possibleConstructorReturn(this, _Tooltip.apply(this, arguments));
+    }
+
+    // overrides
+
+    Popover.prototype.isWithContent = function isWithContent() {
+      return this.getTitle() || this._getContent();
+    };
+
+    Popover.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Popover.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      // we use append for html objects to maintain js events
+      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
+      this.setElementContent($tip.find(Selector.CONTENT), this._getContent());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    // private
+
+    Popover.prototype._getContent = function _getContent() {
+      return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);
+    };
+
+    // static
+
+    Popover._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /destroy|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Popover(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Popover, null, [{
+      key: 'VERSION',
+
+
+      // getters
+
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Popover;
+  }(Tooltip);
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Popover._jQueryInterface;
+  $.fn[NAME].Constructor = Popover;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Popover._jQueryInterface;
+  };
+
+  return Popover;
+}(jQuery);
+
+}();
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
new file mode 100644
index 0000000..f8559b3
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(jQuery),+function(){function a(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function b(a,b){ [...]
+DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},o=function(){function b(a){c(this,b),this._element=a}return b.prototype.show=function(){var b=this;if(!this._element.parentNode||this._element.parentNode.nodeType!==Node.ELEMENT_NODE||!a(this._element).hasClass(m.ACTIVE)){var c=void 0,d=void 0,e=a(this._element).closest(n.UL)[0],g=f.getSelectorFromElement(this._element);e&&(d=a.makeArray(a(e).find(n.ACTIVE)),d=d[d.length-1]);var h=a.Event(l.HIDE,{related [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/I.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/I.png
new file mode 100644
index 0000000..d4906b6
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/I.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/L.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/L.png
new file mode 100644
index 0000000..665071d
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/L.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Lminus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Lminus.png
new file mode 100644
index 0000000..db7a93f
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Lminus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Lplus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Lplus.png
new file mode 100644
index 0000000..70195f8
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Lplus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuArrow.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuArrow.png
new file mode 100644
index 0000000..673ff90
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuArrow.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuCheckmark.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuCheckmark.png
new file mode 100644
index 0000000..9cfb036
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuCheckmark.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuRadioChecked.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuRadioChecked.png
new file mode 100644
index 0000000..39b8bcc
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/MenuRadioChecked.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Rminus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Rminus.png
new file mode 100644
index 0000000..fe6955a
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Rminus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Rplus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Rplus.png
new file mode 100644
index 0000000..44affcb
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Rplus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/T.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/T.png
new file mode 100644
index 0000000..bc5ae2d
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/T.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Tminus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Tminus.png
new file mode 100644
index 0000000..db7a93f
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Tminus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Tplus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Tplus.png
new file mode 100644
index 0000000..70195f8
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/Tplus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/box-header-bg.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/box-header-bg.png
new file mode 100644
index 0000000..970989b
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/box-header-bg.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/file-upload.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/file-upload.png
new file mode 100644
index 0000000..5cc0b89
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/file-upload.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/label-error-bg.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/label-error-bg.png
new file mode 100644
index 0000000..39cc86f
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/label-error-bg.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/label_underline.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/label_underline.png
new file mode 100644
index 0000000..4b5b302
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/label_underline.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/minus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/minus.png
new file mode 100644
index 0000000..fe6955a
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/minus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/nav_bg.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/nav_bg.png
new file mode 100644
index 0000000..b716593
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/nav_bg.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/next.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/next.png
new file mode 100644
index 0000000..499e4b4
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/next.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/nextDisabled.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/nextDisabled.png
new file mode 100644
index 0000000..6f60e45
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/nextDisabled.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/plus.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/plus.png
new file mode 100644
index 0000000..70195f8
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/plus.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/poweredBy.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/poweredBy.png
new file mode 100644
index 0000000..b5fcfb3
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/poweredBy.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/prev.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/prev.png
new file mode 100644
index 0000000..844907b
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/prev.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/prevDisabled.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/prevDisabled.png
new file mode 100644
index 0000000..32bc726
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/prevDisabled.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/red.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/red.png
new file mode 100644
index 0000000..8ae453f
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/red.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/remove.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/remove.png
new file mode 100644
index 0000000..705d268
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/remove.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tab-header-selected-bg.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tab-header-selected-bg.png
new file mode 100644
index 0000000..7d6ef32
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tab-header-selected-bg.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tab-header-unselected-bg.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tab-header-unselected-bg.png
new file mode 100644
index 0000000..8ed20b2
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tab-header-unselected-bg.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabNext.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabNext.png
new file mode 100644
index 0000000..2b91769
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabNext.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabNextDisabled.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabNextDisabled.png
new file mode 100644
index 0000000..6e5e7a7
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabNextDisabled.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabPrev.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabPrev.png
new file mode 100644
index 0000000..7cfc675
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabPrev.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabPrevDisabled.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabPrevDisabled.png
new file mode 100644
index 0000000..bcf937e
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/tabPrevDisabled.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/toolbarButtonMenu.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/toolbarButtonMenu.png
new file mode 100644
index 0000000..6cd46e8
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/toolbarButtonMenu.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/toolbarButtonMenuDisabled.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/toolbarButtonMenuDisabled.png
new file mode 100644
index 0000000..f23a7e6
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/toolbarButtonMenuDisabled.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeMenuClose.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeMenuClose.png
new file mode 100644
index 0000000..fc20d36
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeMenuClose.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeMenuOpen.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeMenuOpen.png
new file mode 100644
index 0000000..720228f
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeMenuOpen.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon-leaf.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon-leaf.png
new file mode 100644
index 0000000..e827681
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon-leaf.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon-open.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon-open.png
new file mode 100644
index 0000000..3348a74
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon-open.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon.png
new file mode 100644
index 0000000..5cc0b89
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/treeNode-icon.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/unchecked.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/unchecked.png
new file mode 100644
index 0000000..7931c4c
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/unchecked.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/uncheckedDisabled.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/uncheckedDisabled.png
new file mode 100644
index 0000000..ec6513f
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/uncheckedDisabled.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/upload.png b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/upload.png
new file mode 100644
index 0000000..8762416
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/resources/tobago/speyside/image/upload.png differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/tobago-config.xml b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/tobago-config.xml
new file mode 100644
index 0000000..47341ba
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/resources/META-INF/tobago-config.xml
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+    version="3.0">
+  <name>tobago-theme-speyside</name>
+  <ordering>
+    <after>
+      <name>tobago-theme-standard</name>
+    </after>
+  </ordering>
+  <theme-definitions>
+    <theme-definition>
+      <name>speyside</name>
+      <display-name>Speyside</display-name>
+      <fallback>standard</fallback>
+      <versioned>true</versioned>
+      <resources production="true">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+        </excludes>
+        <script name="/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+        <style name="/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+      </resources>
+      <resources production="false">
+        <excludes>
+          <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+          <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+        </excludes>
+        <script name="/tobago/speyside/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+        <style name="/tobago/speyside/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/scss/_custom.scss b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/scss/_custom.scss
new file mode 100644
index 0000000..0886961
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/scss/_custom.scss
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+// Bootstrap overrides
+//
+// Copy variables from `_variables.scss` to this file to override default values
+// without modifying source files.
+
+$body-bg:    #e2e2e2 !default;
+
+// todo: get this from the JAR
+@import "tobago";
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/scss/_tobago.scss b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/scss/_tobago.scss
new file mode 100644
index 0000000..b342151
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-speyside/src/main/scss/_tobago.scss
@@ -0,0 +1,918 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+
+/*
+ * theme: standard
+ * agent: standard
+ */
+
+/* box -------------------------------------------------------------- */
+
+.tobago-box-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+
+.tobago-flexLayout {
+    display: -webkit-flex; /* needed e.g. for Safari 8.0.2 */
+    display: -ms-flexbox; /* needed for IE 10 */
+    display: flex;
+    min-width: 0; /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+    flex-direction: column;
+    -webkit-flex-direction: column;
+    -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+    margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd{
+  justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween{
+  justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround{
+  justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  -moz-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+
+.tobago-gridLayout {
+    width: 100%;
+    height: 100%;
+/*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+    vertical-align: top;
+    padding: 0;
+    border-left: 5px solid transparent;
+    border-top: 5px solid transparent;
+    height: 100%; /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+    border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+    border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+
+.tobago-header {
+    margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+    margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+
+.tobago-image-markup-disabled {
+  filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  -webkit-border-radius: 6px 6px 6px 6px;
+  -moz-border-radius: 6px 6px 6px 6px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  -webkit-border-radius: 6px 0 6px 6px;
+  -moz-border-radius: 6px 0 6px 6px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+
+.tobago-selectManyShuttle {
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  flex: 1 0 0px;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: flex;
+  flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  flex: 1 0 0px;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: flex;
+  flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important; /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+.tobago-sheet-paging-markup-center {
+}
+
+.tobago-sheet-paging-markup-right {
+  float:right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important; /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+    padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+    background-color: #0097CF;
+    color: #FFFFFF;
+    cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+
+.tobago-tab {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}.form-horizontal .control-label {
+   margin-top: 10px;
+   margin-bottom: 5px;
+ }
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content:"*";
+  color:red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/lib/closure-compiler-LICENSE.txt b/tobago-3.0.x/tobago-theme/tobago-theme-standard/lib/closure-compiler-LICENSE.txt
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/lib/closure-compiler-LICENSE.txt
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/lib/compiler-20120430.jar b/tobago-3.0.x/tobago-theme/tobago-theme-standard/lib/compiler-20120430.jar
new file mode 100644
index 0000000..3042ba3
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-standard/lib/compiler-20120430.jar differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/pom.xml b/tobago-3.0.x/tobago-theme/tobago-theme-standard/pom.xml
new file mode 100644
index 0000000..e0c2e3a
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/pom.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-theme</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-theme-standard</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Theme Standard</name>
+
+  <properties>
+    <theme.name>standard</theme.name>
+  </properties>
+
+  <build>
+    <plugins>
+      <plugin>
+        <artifactId>maven-antrun-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>strip-javascript</id>
+            <goals>
+              <goal>run</goal>
+            </goals>
+            <phase>compile</phase>
+            <configuration>
+              <target>
+                <concat destfile="${project.build.directory}/javascript-min/standard/script/tobago.min.js" force="no">
+                  <filelist dir="${basedir}/src/main/resources/META-INF/resources/tobago/standard/script" files="tobago-jsf.js,tobago.js,tobago-calendar.js,tobago-in.js,tobago-layout.js,tobago-overlay.js,tobago-popup.js,tobago-sheet.js,tobago-suggest.js,tobago-tab.js,tobago-tree.js,tobago-utils.js" />
+                </concat>
+                <replaceregexp match="^.*//.*@DEV_ONLY.*$" replace="" byline="true">
+                  <fileset dir="${project.build.directory}/javascript-min">
+                    <include name="**/tobago.min.js" />
+                  </fileset>
+                </replaceregexp>
+              </target>
+            </configuration>
+          </execution>
+        </executions>
+        <dependencies>
+          <dependency>
+            <groupId>ant</groupId>
+            <artifactId>ant-apache-regexp</artifactId>
+            <version>1.6.5</version>
+          </dependency>
+        </dependencies>
+      </plugin>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>exec-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>compress-standard</id>
+            <goals>
+              <goal>exec</goal>
+            </goals>
+            <phase>compile</phase>
+            <configuration>
+              <executable>java</executable>
+              <arguments>
+                <argument>-jar</argument>
+                <argument>lib/compiler-20120430.jar</argument>
+                <argument>--js</argument>
+                <argument>${project.build.directory}/javascript-min/standard/script/tobago.min.js</argument>
+                <argument>--js_output_file</argument>
+                <argument>target/classes/META-INF/resources/tobago/standard/script/tobago.min.js</argument>
+              </arguments>
+            </configuration>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
+        <groupId>net.alchim31.maven</groupId>
+        <artifactId>yuicompressor-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>compress</goal>
+            </goals>
+          </execution>
+        </executions>
+        <configuration>
+          <suffix>.min</suffix>
+          <excludes>
+            <exclude>**/*.js</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>nl.geodienstencentrum.maven</groupId>
+        <artifactId>sass-maven-plugin</artifactId>
+        <version>2.14</version>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.test</groupId>
+      <artifactId>myfaces-test20</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-core</artifactId>
+      <version>${project.version}</version>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/appended-resources/META-INF/LICENSE b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/appended-resources/META-INF/LICENSE
new file mode 100644
index 0000000..c43ab3d
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/appended-resources/META-INF/LICENSE
@@ -0,0 +1,263 @@
+------------------------------------------------------------------------------
+For jQuery:
+------------------------------------------------------------------------------
+
+Copyright 2012, 2014 jQuery Foundation and other contributors,
+https://jquery.org/
+
+This software consists of voluntary contributions made by many
+individuals. For exact contribution history, see the revision history
+available at https://github.com/jquery/jquery.org
+
+The following license applies to all parts of this software except as
+documented below:
+
+====
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+====
+
+All files located in the node_modules directory are externally
+maintained libraries used by this software which have their own
+licenses; we recommend you read them, as their terms may differ from the
+terms above.
+
+------------------------------------------------------------------------------
+For jQuery UI:
+------------------------------------------------------------------------------
+
+Copyright 2014 jQuery Foundation and other contributors,
+http://jqueryui.com/
+
+This software consists of voluntary contributions made by many
+individuals (AUTHORS.txt, http://jqueryui.com/about) For exact
+contribution history, see the revision history and logs, available
+at http://jquery-ui.googlecode.com/svn/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For jQuery Timepicker Addon:
+------------------------------------------------------------------------------
+
+Copyright (c) 2009 Trent Richardson, http://trentrichardson.com/Impromptu/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For Bootstrap:
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2011-2014 Twitter, Inc
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For Font Awesome:
+------------------------------------------------------------------------------
+
+Font Awesome by Dave Gandy - http://fontawesome.io
+
+
+SIL OFL 1.1 for the font
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+This license is copied below, and is also available with a FAQ at:
+http://scripts.sil.org/OFL
+
+------------------------------------------------------------------------------
+
+The MIT License (MIT) for the code
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For Font Awesome:
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2014 HubSpot, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For Tether:
+------------------------------------------------------------------------------
+
+Copyright (c) 2014-2016 HubSpot, Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+------------------------------------------------------------------------------
+For Bootstrap-DateTimePicker:
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2015 Jonathan Peterson (@Eonasdan)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
+------------------------------------------------------------------------------
+For Momentum:
+------------------------------------------------------------------------------
+
+The MIT License (MIT)
+
+Copyright (c) 2011-2016 Tim Wood, Iskren Chernev, Moment.js contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/appended-resources/META-INF/NOTICE b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/appended-resources/META-INF/NOTICE
new file mode 100644
index 0000000..3f233da
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/appended-resources/META-INF/NOTICE
@@ -0,0 +1,26 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
+
+This product includes software developed by
+The jQuery Foundation (http://jquery.org/ and http://jqueryui.com/)
+
+This product includes software developed by
+Trent Richardson (http://trentrichardson.com/)
+
+This product includes software developed by
+Twitter, Inc. (http://getbootstrap.com/)
+
+normalize.css v3.0.0 | MIT License | git.io/normalize
+
+This product includes software and fonts developed by
+"Font Awesome by Dave Gandy - http://fontawesome.io"
+
+This product includes software developed by
+HubSpot, Inc. (http://github.hubspot.com/tether/)
+
+This product includes software developed by
+Jonathan Peterson (@Eonasdan)
+
+This product includes software developed by
+Tim Wood, Iskren Chernev, Moment.js contributors
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.css
new file mode 100644
index 0000000..b8bf43b
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.css
@@ -0,0 +1,373 @@
+/*!
+ * Datetimepicker for Bootstrap 3
+ * version : 4.17.37
+ * https://github.com/Eonasdan/bootstrap-datetimepicker/
+ */
+.bootstrap-datetimepicker-widget {
+  list-style: none;
+}
+.bootstrap-datetimepicker-widget.dropdown-menu {
+  margin: 2px 0;
+  padding: 4px;
+  width: 19em;
+}
+@media (min-width: 768px) {
+  .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
+    width: 38em;
+  }
+}
+@media (min-width: 992px) {
+  .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
+    width: 38em;
+  }
+}
+@media (min-width: 1200px) {
+  .bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs {
+    width: 38em;
+  }
+}
+.bootstrap-datetimepicker-widget.dropdown-menu:before,
+.bootstrap-datetimepicker-widget.dropdown-menu:after {
+  content: '';
+  display: inline-block;
+  position: absolute;
+}
+.bootstrap-datetimepicker-widget.dropdown-menu.bottom:before {
+  border-left: 7px solid transparent;
+  border-right: 7px solid transparent;
+  border-bottom: 7px solid #cccccc;
+  border-bottom-color: rgba(0, 0, 0, 0.2);
+  top: -7px;
+  left: 7px;
+}
+.bootstrap-datetimepicker-widget.dropdown-menu.bottom:after {
+  border-left: 6px solid transparent;
+  border-right: 6px solid transparent;
+  border-bottom: 6px solid white;
+  top: -6px;
+  left: 8px;
+}
+.bootstrap-datetimepicker-widget.dropdown-menu.top:before {
+  border-left: 7px solid transparent;
+  border-right: 7px solid transparent;
+  border-top: 7px solid #cccccc;
+  border-top-color: rgba(0, 0, 0, 0.2);
+  bottom: -7px;
+  left: 6px;
+}
+.bootstrap-datetimepicker-widget.dropdown-menu.top:after {
+  border-left: 6px solid transparent;
+  border-right: 6px solid transparent;
+  border-top: 6px solid white;
+  bottom: -6px;
+  left: 7px;
+}
+.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:before {
+  left: auto;
+  right: 6px;
+}
+.bootstrap-datetimepicker-widget.dropdown-menu.pull-right:after {
+  left: auto;
+  right: 7px;
+}
+.bootstrap-datetimepicker-widget .list-unstyled {
+  margin: 0;
+}
+.bootstrap-datetimepicker-widget a[data-action] {
+  padding: 6px 0;
+}
+.bootstrap-datetimepicker-widget a[data-action]:active {
+  box-shadow: none;
+}
+.bootstrap-datetimepicker-widget .timepicker-hour,
+.bootstrap-datetimepicker-widget .timepicker-minute,
+.bootstrap-datetimepicker-widget .timepicker-second {
+  width: 54px;
+  font-weight: bold;
+  font-size: 1.2em;
+  margin: 0;
+}
+.bootstrap-datetimepicker-widget button[data-action] {
+  padding: 6px;
+}
+.bootstrap-datetimepicker-widget .btn[data-action="incrementHours"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Increment Hours";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="incrementMinutes"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Increment Minutes";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="decrementHours"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Decrement Hours";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="decrementMinutes"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Decrement Minutes";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="showHours"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Show Hours";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="showMinutes"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Show Minutes";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="togglePeriod"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Toggle AM/PM";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="clear"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Clear the picker";
+}
+.bootstrap-datetimepicker-widget .btn[data-action="today"]::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Set the date to today";
+}
+.bootstrap-datetimepicker-widget .picker-switch {
+  text-align: center;
+}
+.bootstrap-datetimepicker-widget .picker-switch::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Toggle Date and Time Screens";
+}
+.bootstrap-datetimepicker-widget .picker-switch td {
+  padding: 0;
+  margin: 0;
+  height: auto;
+  width: auto;
+  line-height: inherit;
+}
+.bootstrap-datetimepicker-widget .picker-switch td span {
+  line-height: 2.5;
+  height: 2.5em;
+  width: 100%;
+}
+.bootstrap-datetimepicker-widget table {
+  width: 100%;
+  margin: 0;
+}
+.bootstrap-datetimepicker-widget table td,
+.bootstrap-datetimepicker-widget table th {
+  text-align: center;
+  border-radius: 4px;
+}
+.bootstrap-datetimepicker-widget table th {
+  height: 20px;
+  line-height: 20px;
+  width: 20px;
+}
+.bootstrap-datetimepicker-widget table th.picker-switch {
+  width: 145px;
+}
+.bootstrap-datetimepicker-widget table th.disabled,
+.bootstrap-datetimepicker-widget table th.disabled:hover {
+  background: none;
+  color: #777777;
+  cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget table th.prev::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Previous Month";
+}
+.bootstrap-datetimepicker-widget table th.next::after {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+  content: "Next Month";
+}
+.bootstrap-datetimepicker-widget table thead tr:first-child th {
+  cursor: pointer;
+}
+.bootstrap-datetimepicker-widget table thead tr:first-child th:hover {
+  background: #eeeeee;
+}
+.bootstrap-datetimepicker-widget table td {
+  height: 54px;
+  line-height: 54px;
+  width: 54px;
+}
+.bootstrap-datetimepicker-widget table td.cw {
+  font-size: .8em;
+  height: 20px;
+  line-height: 20px;
+  color: #777777;
+}
+.bootstrap-datetimepicker-widget table td.day {
+  height: 20px;
+  line-height: 20px;
+  width: 20px;
+}
+.bootstrap-datetimepicker-widget table td.day:hover,
+.bootstrap-datetimepicker-widget table td.hour:hover,
+.bootstrap-datetimepicker-widget table td.minute:hover,
+.bootstrap-datetimepicker-widget table td.second:hover {
+  background: #eeeeee;
+  cursor: pointer;
+}
+.bootstrap-datetimepicker-widget table td.old,
+.bootstrap-datetimepicker-widget table td.new {
+  color: #777777;
+}
+.bootstrap-datetimepicker-widget table td.today {
+  position: relative;
+}
+.bootstrap-datetimepicker-widget table td.today:before {
+  content: '';
+  display: inline-block;
+  border: solid transparent;
+  border-width: 0 0 7px 7px;
+  border-bottom-color: #337ab7;
+  border-top-color: rgba(0, 0, 0, 0.2);
+  position: absolute;
+  bottom: 4px;
+  right: 4px;
+}
+.bootstrap-datetimepicker-widget table td.active,
+.bootstrap-datetimepicker-widget table td.active:hover {
+  background-color: #337ab7;
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.bootstrap-datetimepicker-widget table td.active.today:before {
+  border-bottom-color: #fff;
+}
+.bootstrap-datetimepicker-widget table td.disabled,
+.bootstrap-datetimepicker-widget table td.disabled:hover {
+  background: none;
+  color: #777777;
+  cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget table td span {
+  display: inline-block;
+  width: 54px;
+  height: 54px;
+  line-height: 54px;
+  margin: 2px 1.5px;
+  cursor: pointer;
+  border-radius: 4px;
+}
+.bootstrap-datetimepicker-widget table td span:hover {
+  background: #eeeeee;
+}
+.bootstrap-datetimepicker-widget table td span.active {
+  background-color: #337ab7;
+  color: #ffffff;
+  text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+.bootstrap-datetimepicker-widget table td span.old {
+  color: #777777;
+}
+.bootstrap-datetimepicker-widget table td span.disabled,
+.bootstrap-datetimepicker-widget table td span.disabled:hover {
+  background: none;
+  color: #777777;
+  cursor: not-allowed;
+}
+.bootstrap-datetimepicker-widget.usetwentyfour td.hour {
+  height: 27px;
+  line-height: 27px;
+}
+.bootstrap-datetimepicker-widget.wider {
+  width: 21em;
+}
+.bootstrap-datetimepicker-widget .datepicker-decades .decade {
+  line-height: 1.8em !important;
+}
+.input-group.date .input-group-addon {
+  cursor: pointer;
+}
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  margin: -1px;
+  padding: 0;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css
new file mode 100644
index 0000000..63c2a3a
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css
@@ -0,0 +1,5 @@
+/*!
+ * Datetimepicker for Bootstrap 3
+ * version : 4.17.37
+ * https://github.com/Eonasdan/bootstrap-datetimepicker/
+ */.bootstrap-datetimepicker-widget{list-style:none}.bootstrap-datetimepicker-widget.dropdown-menu{margin:2px 0;padding:4px;width:19em}@media (min-width:768px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:992px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}@media (min-width:1200px){.bootstrap-datetimepicker-widget.dropdown-menu.timepicker-sbs{width:38em}}.bootstrap-datetimepicker-widget.dropdown-menu:before,.boot [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.js
new file mode 100644
index 0000000..31e4e6a
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.js
@@ -0,0 +1,2552 @@
+/*! version : 4.17.37
+ =========================================================
+ bootstrap-datetimejs
+ https://github.com/Eonasdan/bootstrap-datetimepicker
+ Copyright (c) 2015 Jonathan Peterson
+ =========================================================
+ */
+/*
+ The MIT License (MIT)
+
+ Copyright (c) 2015 Jonathan Peterson
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+/*global define:false */
+/*global exports:false */
+/*global require:false */
+/*global jQuery:false */
+/*global moment:false */
+(function (factory) {
+    'use strict';
+    if (typeof define === 'function' && define.amd) {
+        // AMD is used - Register as an anonymous module.
+        define(['jquery', 'moment'], factory);
+    } else if (typeof exports === 'object') {
+        factory(require('jquery'), require('moment'));
+    } else {
+        // Neither AMD nor CommonJS used. Use global variables.
+        if (typeof jQuery === 'undefined') {
+            throw 'bootstrap-datetimepicker requires jQuery to be loaded first';
+        }
+        if (typeof moment === 'undefined') {
+            throw 'bootstrap-datetimepicker requires Moment.js to be loaded first';
+        }
+        factory(jQuery, moment);
+    }
+}(function ($, moment) {
+    'use strict';
+    if (!moment) {
+        throw new Error('bootstrap-datetimepicker requires Moment.js to be loaded first');
+    }
+
+    var dateTimePicker = function (element, options) {
+        var picker = {},
+            date,
+            viewDate,
+            unset = true,
+            input,
+            component = false,
+            widget = false,
+            use24Hours,
+            minViewModeNumber = 0,
+            actualFormat,
+            parseFormats,
+            currentViewMode,
+            datePickerModes = [
+                {
+                    clsName: 'days',
+                    navFnc: 'M',
+                    navStep: 1
+                },
+                {
+                    clsName: 'months',
+                    navFnc: 'y',
+                    navStep: 1
+                },
+                {
+                    clsName: 'years',
+                    navFnc: 'y',
+                    navStep: 10
+                },
+                {
+                    clsName: 'decades',
+                    navFnc: 'y',
+                    navStep: 100
+                }
+            ],
+            viewModes = ['days', 'months', 'years', 'decades'],
+            verticalModes = ['top', 'bottom', 'auto'],
+            horizontalModes = ['left', 'right', 'auto'],
+            toolbarPlacements = ['default', 'top', 'bottom'],
+            keyMap = {
+                'up': 38,
+                38: 'up',
+                'down': 40,
+                40: 'down',
+                'left': 37,
+                37: 'left',
+                'right': 39,
+                39: 'right',
+                'tab': 9,
+                9: 'tab',
+                'escape': 27,
+                27: 'escape',
+                'enter': 13,
+                13: 'enter',
+                'pageUp': 33,
+                33: 'pageUp',
+                'pageDown': 34,
+                34: 'pageDown',
+                'shift': 16,
+                16: 'shift',
+                'control': 17,
+                17: 'control',
+                'space': 32,
+                32: 'space',
+                't': 84,
+                84: 't',
+                'delete': 46,
+                46: 'delete'
+            },
+            keyState = {},
+
+            /********************************************************************************
+             *
+             * Private functions
+             *
+             ********************************************************************************/
+            getMoment = function (d) {
+                var tzEnabled = false,
+                    returnMoment,
+                    currentZoneOffset,
+                    incomingZoneOffset,
+                    timeZoneIndicator,
+                    dateWithTimeZoneInfo;
+
+                if (moment.tz !== undefined && options.timeZone !== undefined && options.timeZone !== null && options.timeZone !== '') {
+                    tzEnabled = true;
+                }
+                if (d === undefined || d === null) {
+                    if (tzEnabled) {
+                        returnMoment = moment().tz(options.timeZone).startOf('d');
+                    } else {
+                        returnMoment = moment().startOf('d');
+                    }
+                } else {
+                    if (tzEnabled) {
+                        currentZoneOffset = moment().tz(options.timeZone).utcOffset();
+                        incomingZoneOffset = moment(d, parseFormats, options.useStrict).utcOffset();
+                        if (incomingZoneOffset !== currentZoneOffset) {
+                            timeZoneIndicator = moment().tz(options.timeZone).format('Z');
+                            dateWithTimeZoneInfo = moment(d, parseFormats, options.useStrict).format('YYYY-MM-DD[T]HH:mm:ss') + timeZoneIndicator;
+                            returnMoment = moment(dateWithTimeZoneInfo, parseFormats, options.useStrict).tz(options.timeZone);
+                        } else {
+                            returnMoment = moment(d, parseFormats, options.useStrict).tz(options.timeZone);
+                        }
+                    } else {
+                        returnMoment = moment(d, parseFormats, options.useStrict);
+                    }
+                }
+                return returnMoment;
+            },
+            isEnabled = function (granularity) {
+                if (typeof granularity !== 'string' || granularity.length > 1) {
+                    throw new TypeError('isEnabled expects a single character string parameter');
+                }
+                switch (granularity) {
+                    case 'y':
+                        return actualFormat.indexOf('Y') !== -1;
+                    case 'M':
+                        return actualFormat.indexOf('M') !== -1;
+                    case 'd':
+                        return actualFormat.toLowerCase().indexOf('d') !== -1;
+                    case 'h':
+                    case 'H':
+                        return actualFormat.toLowerCase().indexOf('h') !== -1;
+                    case 'm':
+                        return actualFormat.indexOf('m') !== -1;
+                    case 's':
+                        return actualFormat.indexOf('s') !== -1;
+                    default:
+                        return false;
+                }
+            },
+            hasTime = function () {
+                return (isEnabled('h') || isEnabled('m') || isEnabled('s'));
+            },
+
+            hasDate = function () {
+                return (isEnabled('y') || isEnabled('M') || isEnabled('d'));
+            },
+
+            getDatePickerTemplate = function () {
+                var headTemplate = $('<thead>')
+                        .append($('<tr>')
+                            .append($('<th>').addClass('prev').attr('data-action', 'previous')
+                                .append($('<span>').addClass(options.icons.previous))
+                                )
+                            .append($('<th>').addClass('picker-switch').attr('data-action', 'pickerSwitch').attr('colspan', (options.calendarWeeks ? '6' : '5')))
+                            .append($('<th>').addClass('next').attr('data-action', 'next')
+                                .append($('<span>').addClass(options.icons.next))
+                                )
+                            ),
+                    contTemplate = $('<tbody>')
+                        .append($('<tr>')
+                            .append($('<td>').attr('colspan', (options.calendarWeeks ? '8' : '7')))
+                            );
+
+                return [
+                    $('<div>').addClass('datepicker-days')
+                        .append($('<table>').addClass('table-condensed')
+                            .append(headTemplate)
+                            .append($('<tbody>'))
+                            ),
+                    $('<div>').addClass('datepicker-months')
+                        .append($('<table>').addClass('table-condensed')
+                            .append(headTemplate.clone())
+                            .append(contTemplate.clone())
+                            ),
+                    $('<div>').addClass('datepicker-years')
+                        .append($('<table>').addClass('table-condensed')
+                            .append(headTemplate.clone())
+                            .append(contTemplate.clone())
+                            ),
+                    $('<div>').addClass('datepicker-decades')
+                        .append($('<table>').addClass('table-condensed')
+                            .append(headTemplate.clone())
+                            .append(contTemplate.clone())
+                            )
+                ];
+            },
+
+            getTimePickerMainTemplate = function () {
+                var topRow = $('<tr>'),
+                    middleRow = $('<tr>'),
+                    bottomRow = $('<tr>');
+
+                if (isEnabled('h')) {
+                    topRow.append($('<td>')
+                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementHour}).addClass('btn').attr('data-action', 'incrementHours')
+                            .append($('<span>').addClass(options.icons.up))));
+                    middleRow.append($('<td>')
+                        .append($('<span>').addClass('timepicker-hour').attr({'data-time-component':'hours', 'title': options.tooltips.pickHour}).attr('data-action', 'showHours')));
+                    bottomRow.append($('<td>')
+                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementHour}).addClass('btn').attr('data-action', 'decrementHours')
+                            .append($('<span>').addClass(options.icons.down))));
+                }
+                if (isEnabled('m')) {
+                    if (isEnabled('h')) {
+                        topRow.append($('<td>').addClass('separator'));
+                        middleRow.append($('<td>').addClass('separator').html(':'));
+                        bottomRow.append($('<td>').addClass('separator'));
+                    }
+                    topRow.append($('<td>')
+                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementMinute}).addClass('btn').attr('data-action', 'incrementMinutes')
+                            .append($('<span>').addClass(options.icons.up))));
+                    middleRow.append($('<td>')
+                        .append($('<span>').addClass('timepicker-minute').attr({'data-time-component': 'minutes', 'title': options.tooltips.pickMinute}).attr('data-action', 'showMinutes')));
+                    bottomRow.append($('<td>')
+                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementMinute}).addClass('btn').attr('data-action', 'decrementMinutes')
+                            .append($('<span>').addClass(options.icons.down))));
+                }
+                if (isEnabled('s')) {
+                    if (isEnabled('m')) {
+                        topRow.append($('<td>').addClass('separator'));
+                        middleRow.append($('<td>').addClass('separator').html(':'));
+                        bottomRow.append($('<td>').addClass('separator'));
+                    }
+                    topRow.append($('<td>')
+                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.incrementSecond}).addClass('btn').attr('data-action', 'incrementSeconds')
+                            .append($('<span>').addClass(options.icons.up))));
+                    middleRow.append($('<td>')
+                        .append($('<span>').addClass('timepicker-second').attr({'data-time-component': 'seconds', 'title': options.tooltips.pickSecond}).attr('data-action', 'showSeconds')));
+                    bottomRow.append($('<td>')
+                        .append($('<a>').attr({href: '#', tabindex: '-1', 'title': options.tooltips.decrementSecond}).addClass('btn').attr('data-action', 'decrementSeconds')
+                            .append($('<span>').addClass(options.icons.down))));
+                }
+
+                if (!use24Hours) {
+                    topRow.append($('<td>').addClass('separator'));
+                    middleRow.append($('<td>')
+                        .append($('<button>').addClass('btn btn-primary').attr({'data-action': 'togglePeriod', tabindex: '-1', 'title': options.tooltips.togglePeriod})));
+                    bottomRow.append($('<td>').addClass('separator'));
+                }
+
+                return $('<div>').addClass('timepicker-picker')
+                    .append($('<table>').addClass('table-condensed')
+                        .append([topRow, middleRow, bottomRow]));
+            },
+
+            getTimePickerTemplate = function () {
+                var hoursView = $('<div>').addClass('timepicker-hours')
+                        .append($('<table>').addClass('table-condensed')),
+                    minutesView = $('<div>').addClass('timepicker-minutes')
+                        .append($('<table>').addClass('table-condensed')),
+                    secondsView = $('<div>').addClass('timepicker-seconds')
+                        .append($('<table>').addClass('table-condensed')),
+                    ret = [getTimePickerMainTemplate()];
+
+                if (isEnabled('h')) {
+                    ret.push(hoursView);
+                }
+                if (isEnabled('m')) {
+                    ret.push(minutesView);
+                }
+                if (isEnabled('s')) {
+                    ret.push(secondsView);
+                }
+
+                return ret;
+            },
+
+            getToolbar = function () {
+                var row = [];
+                if (options.showTodayButton) {
+                    row.push($('<td>').append($('<a>').attr({'data-action':'today', 'title': options.tooltips.today}).append($('<span>').addClass(options.icons.today))));
+                }
+                if (!options.sideBySide && hasDate() && hasTime()) {
+                    row.push($('<td>').append($('<a>').attr({'data-action':'togglePicker', 'title': options.tooltips.selectTime}).append($('<span>').addClass(options.icons.time))));
+                }
+                if (options.showClear) {
+                    row.push($('<td>').append($('<a>').attr({'data-action':'clear', 'title': options.tooltips.clear}).append($('<span>').addClass(options.icons.clear))));
+                }
+                if (options.showClose) {
+                    row.push($('<td>').append($('<a>').attr({'data-action':'close', 'title': options.tooltips.close}).append($('<span>').addClass(options.icons.close))));
+                }
+                return $('<table>').addClass('table-condensed').append($('<tbody>').append($('<tr>').append(row)));
+            },
+
+            getTemplate = function () {
+                var template = $('<div>').addClass('bootstrap-datetimepicker-widget dropdown-menu'),
+                    dateView = $('<div>').addClass('datepicker').append(getDatePickerTemplate()),
+                    timeView = $('<div>').addClass('timepicker').append(getTimePickerTemplate()),
+                    content = $('<ul>').addClass('list-unstyled'),
+                    toolbar = $('<li>').addClass('picker-switch' + (options.collapse ? ' accordion-toggle' : '')).append(getToolbar());
+
+                if (options.inline) {
+                    template.removeClass('dropdown-menu');
+                }
+
+                if (use24Hours) {
+                    template.addClass('usetwentyfour');
+                }
+                if (isEnabled('s') && !use24Hours) {
+                    template.addClass('wider');
+                }
+
+                if (options.sideBySide && hasDate() && hasTime()) {
+                    template.addClass('timepicker-sbs');
+                    if (options.toolbarPlacement === 'top') {
+                        template.append(toolbar);
+                    }
+                    template.append(
+                        $('<div>').addClass('row')
+                            .append(dateView.addClass('col-md-6'))
+                            .append(timeView.addClass('col-md-6'))
+                    );
+                    if (options.toolbarPlacement === 'bottom') {
+                        template.append(toolbar);
+                    }
+                    return template;
+                }
+
+                if (options.toolbarPlacement === 'top') {
+                    content.append(toolbar);
+                }
+                if (hasDate()) {
+                    content.append($('<li>').addClass((options.collapse && hasTime() ? 'collapse in' : '')).append(dateView));
+                }
+                if (options.toolbarPlacement === 'default') {
+                    content.append(toolbar);
+                }
+                if (hasTime()) {
+                    content.append($('<li>').addClass((options.collapse && hasDate() ? 'collapse' : '')).append(timeView));
+                }
+                if (options.toolbarPlacement === 'bottom') {
+                    content.append(toolbar);
+                }
+                return template.append(content);
+            },
+
+            dataToOptions = function () {
+                var eData,
+                    dataOptions = {};
+
+                if (element.is('input') || options.inline) {
+                    eData = element.data();
+                } else {
+                    eData = element.find('input').data();
+                }
+
+                if (eData.dateOptions && eData.dateOptions instanceof Object) {
+                    dataOptions = $.extend(true, dataOptions, eData.dateOptions);
+                }
+
+                $.each(options, function (key) {
+                    var attributeName = 'date' + key.charAt(0).toUpperCase() + key.slice(1);
+                    if (eData[attributeName] !== undefined) {
+                        dataOptions[key] = eData[attributeName];
+                    }
+                });
+                return dataOptions;
+            },
+
+            place = function () {
+                var position = (component || element).position(),
+                    offset = (component || element).offset(),
+                    vertical = options.widgetPositioning.vertical,
+                    horizontal = options.widgetPositioning.horizontal,
+                    parent;
+
+                if (options.widgetParent) {
+                    parent = options.widgetParent.append(widget);
+                } else if (element.is('input')) {
+                    parent = element.after(widget).parent();
+                } else if (options.inline) {
+                    parent = element.append(widget);
+                    return;
+                } else {
+                    parent = element;
+                    element.children().first().after(widget);
+                }
+
+                // Top and bottom logic
+                if (vertical === 'auto') {
+                    if (offset.top + widget.height() * 1.5 >= $(window).height() + $(window).scrollTop() &&
+                        widget.height() + element.outerHeight() < offset.top) {
+                        vertical = 'top';
+                    } else {
+                        vertical = 'bottom';
+                    }
+                }
+
+                // Left and right logic
+                if (horizontal === 'auto') {
+                    if (parent.width() < offset.left + widget.outerWidth() / 2 &&
+                        offset.left + widget.outerWidth() > $(window).width()) {
+                        horizontal = 'right';
+                    } else {
+                        horizontal = 'left';
+                    }
+                }
+
+                if (vertical === 'top') {
+                    widget.addClass('top').removeClass('bottom');
+                } else {
+                    widget.addClass('bottom').removeClass('top');
+                }
+
+                if (horizontal === 'right') {
+                    widget.addClass('pull-right');
+                } else {
+                    widget.removeClass('pull-right');
+                }
+
+                // find the first parent element that has a relative css positioning
+                if (parent.css('position') !== 'relative') {
+                    parent = parent.parents().filter(function () {
+                        return $(this).css('position') === 'relative';
+                    }).first();
+                }
+
+                if (parent.length === 0) {
+                    throw new Error('datetimepicker component should be placed within a relative positioned container');
+                }
+
+                widget.css({
+                    top: vertical === 'top' ? 'auto' : position.top + element.outerHeight(),
+                    bottom: vertical === 'top' ? position.top + element.outerHeight() : 'auto',
+                    left: horizontal === 'left' ? (parent === element ? 0 : position.left) : 'auto',
+                    right: horizontal === 'left' ? 'auto' : parent.outerWidth() - element.outerWidth() - (parent === element ? 0 : position.left)
+                });
+            },
+
+            notifyEvent = function (e) {
+                if (e.type === 'dp.change' && ((e.date && e.date.isSame(e.oldDate)) || (!e.date && !e.oldDate))) {
+                    return;
+                }
+                element.trigger(e);
+            },
+
+            viewUpdate = function (e) {
+                if (e === 'y') {
+                    e = 'YYYY';
+                }
+                notifyEvent({
+                    type: 'dp.update',
+                    change: e,
+                    viewDate: viewDate.clone()
+                });
+            },
+
+            showMode = function (dir) {
+                if (!widget) {
+                    return;
+                }
+                if (dir) {
+                    currentViewMode = Math.max(minViewModeNumber, Math.min(3, currentViewMode + dir));
+                }
+                widget.find('.datepicker > div').hide().filter('.datepicker-' + datePickerModes[currentViewMode].clsName).show();
+            },
+
+            fillDow = function () {
+                var row = $('<tr>'),
+                    currentDate = viewDate.clone().startOf('w').startOf('d');
+
+                if (options.calendarWeeks === true) {
+                    row.append($('<th>').addClass('cw').text('#'));
+                }
+
+                while (currentDate.isBefore(viewDate.clone().endOf('w'))) {
+                    row.append($('<th>').addClass('dow').text(currentDate.format('dd')));
+                    currentDate.add(1, 'd');
+                }
+                widget.find('.datepicker-days thead').append(row);
+            },
+
+            isInDisabledDates = function (testDate) {
+                return options.disabledDates[testDate.format('YYYY-MM-DD')] === true;
+            },
+
+            isInEnabledDates = function (testDate) {
+                return options.enabledDates[testDate.format('YYYY-MM-DD')] === true;
+            },
+
+            isInDisabledHours = function (testDate) {
+                return options.disabledHours[testDate.format('H')] === true;
+            },
+
+            isInEnabledHours = function (testDate) {
+                return options.enabledHours[testDate.format('H')] === true;
+            },
+
+            isValid = function (targetMoment, granularity) {
+                if (!targetMoment.isValid()) {
+                    return false;
+                }
+                if (options.disabledDates && granularity === 'd' && isInDisabledDates(targetMoment)) {
+                    return false;
+                }
+                if (options.enabledDates && granularity === 'd' && !isInEnabledDates(targetMoment)) {
+                    return false;
+                }
+                if (options.minDate && targetMoment.isBefore(options.minDate, granularity)) {
+                    return false;
+                }
+                if (options.maxDate && targetMoment.isAfter(options.maxDate, granularity)) {
+                    return false;
+                }
+                if (options.daysOfWeekDisabled && granularity === 'd' && options.daysOfWeekDisabled.indexOf(targetMoment.day()) !== -1) {
+                    return false;
+                }
+                if (options.disabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && isInDisabledHours(targetMoment)) {
+                    return false;
+                }
+                if (options.enabledHours && (granularity === 'h' || granularity === 'm' || granularity === 's') && !isInEnabledHours(targetMoment)) {
+                    return false;
+                }
+                if (options.disabledTimeIntervals && (granularity === 'h' || granularity === 'm' || granularity === 's')) {
+                    var found = false;
+                    $.each(options.disabledTimeIntervals, function () {
+                        if (targetMoment.isBetween(this[0], this[1])) {
+                            found = true;
+                            return false;
+                        }
+                    });
+                    if (found) {
+                        return false;
+                    }
+                }
+                return true;
+            },
+
+            fillMonths = function () {
+                var spans = [],
+                    monthsShort = viewDate.clone().startOf('y').startOf('d');
+                while (monthsShort.isSame(viewDate, 'y')) {
+                    spans.push($('<span>').attr('data-action', 'selectMonth').addClass('month').text(monthsShort.format('MMM')));
+                    monthsShort.add(1, 'M');
+                }
+                widget.find('.datepicker-months td').empty().append(spans);
+            },
+
+            updateMonths = function () {
+                var monthsView = widget.find('.datepicker-months'),
+                    monthsViewHeader = monthsView.find('th'),
+                    months = monthsView.find('tbody').find('span');
+
+                monthsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevYear);
+                monthsViewHeader.eq(1).attr('title', options.tooltips.selectYear);
+                monthsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextYear);
+
+                monthsView.find('.disabled').removeClass('disabled');
+
+                if (!isValid(viewDate.clone().subtract(1, 'y'), 'y')) {
+                    monthsViewHeader.eq(0).addClass('disabled');
+                }
+
+                monthsViewHeader.eq(1).text(viewDate.year());
+
+                if (!isValid(viewDate.clone().add(1, 'y'), 'y')) {
+                    monthsViewHeader.eq(2).addClass('disabled');
+                }
+
+                months.removeClass('active');
+                if (date.isSame(viewDate, 'y') && !unset) {
+                    months.eq(date.month()).addClass('active');
+                }
+
+                months.each(function (index) {
+                    if (!isValid(viewDate.clone().month(index), 'M')) {
+                        $(this).addClass('disabled');
+                    }
+                });
+            },
+
+            updateYears = function () {
+                var yearsView = widget.find('.datepicker-years'),
+                    yearsViewHeader = yearsView.find('th'),
+                    startYear = viewDate.clone().subtract(5, 'y'),
+                    endYear = viewDate.clone().add(6, 'y'),
+                    html = '';
+
+                yearsViewHeader.eq(0).find('span').attr('title', options.tooltips.prevDecade);
+                yearsViewHeader.eq(1).attr('title', options.tooltips.selectDecade);
+                yearsViewHeader.eq(2).find('span').attr('title', options.tooltips.nextDecade);
+
+                yearsView.find('.disabled').removeClass('disabled');
+
+                if (options.minDate && options.minDate.isAfter(startYear, 'y')) {
+                    yearsViewHeader.eq(0).addClass('disabled');
+                }
+
+                yearsViewHeader.eq(1).text(startYear.year() + '-' + endYear.year());
+
+                if (options.maxDate && options.maxDate.isBefore(endYear, 'y')) {
+                    yearsViewHeader.eq(2).addClass('disabled');
+                }
+
+                while (!startYear.isAfter(endYear, 'y')) {
+                    html += '<span data-action="selectYear" class="year' + (startYear.isSame(date, 'y') && !unset ? ' active' : '') + (!isValid(startYear, 'y') ? ' disabled' : '') + '">' + startYear.year() + '</span>';
+                    startYear.add(1, 'y');
+                }
+
+                yearsView.find('td').html(html);
+            },
+
+            updateDecades = function () {
+                var decadesView = widget.find('.datepicker-decades'),
+                    decadesViewHeader = decadesView.find('th'),
+                    startDecade = moment({y: viewDate.year() - (viewDate.year() % 100) - 1}),
+                    endDecade = startDecade.clone().add(100, 'y'),
+                    startedAt = startDecade.clone(),
+                    html = '';
+
+                decadesViewHeader.eq(0).find('span').attr('title', options.tooltips.prevCentury);
+                decadesViewHeader.eq(2).find('span').attr('title', options.tooltips.nextCentury);
+
+                decadesView.find('.disabled').removeClass('disabled');
+
+                if (startDecade.isSame(moment({y: 1900})) || (options.minDate && options.minDate.isAfter(startDecade, 'y'))) {
+                    decadesViewHeader.eq(0).addClass('disabled');
+                }
+
+                decadesViewHeader.eq(1).text(startDecade.year() + '-' + endDecade.year());
+
+                if (startDecade.isSame(moment({y: 2000})) || (options.maxDate && options.maxDate.isBefore(endDecade, 'y'))) {
+                    decadesViewHeader.eq(2).addClass('disabled');
+                }
+
+                while (!startDecade.isAfter(endDecade, 'y')) {
+                    html += '<span data-action="selectDecade" class="decade' + (startDecade.isSame(date, 'y') ? ' active' : '') +
+                        (!isValid(startDecade, 'y') ? ' disabled' : '') + '" data-selection="' + (startDecade.year() + 6) + '">' + (startDecade.year() + 1) + ' - ' + (startDecade.year() + 12) + '</span>';
+                    startDecade.add(12, 'y');
+                }
+                html += '<span></span><span></span><span></span>'; //push the dangling block over, at least this way it's even
+
+                decadesView.find('td').html(html);
+                decadesViewHeader.eq(1).text((startedAt.year() + 1) + '-' + (startDecade.year()));
+            },
+
+            fillDate = function () {
+                var daysView = widget.find('.datepicker-days'),
+                    daysViewHeader = daysView.find('th'),
+                    currentDate,
+                    html = [],
+                    row,
+                    clsName,
+                    i;
+
+                if (!hasDate()) {
+                    return;
+                }
+
+                daysViewHeader.eq(0).find('span').attr('title', options.tooltips.prevMonth);
+                daysViewHeader.eq(1).attr('title', options.tooltips.selectMonth);
+                daysViewHeader.eq(2).find('span').attr('title', options.tooltips.nextMonth);
+
+                daysView.find('.disabled').removeClass('disabled');
+                daysViewHeader.eq(1).text(viewDate.format(options.dayViewHeaderFormat));
+
+                if (!isValid(viewDate.clone().subtract(1, 'M'), 'M')) {
+                    daysViewHeader.eq(0).addClass('disabled');
+                }
+                if (!isValid(viewDate.clone().add(1, 'M'), 'M')) {
+                    daysViewHeader.eq(2).addClass('disabled');
+                }
+
+                currentDate = viewDate.clone().startOf('M').startOf('w').startOf('d');
+
+                for (i = 0; i < 42; i++) { //always display 42 days (should show 6 weeks)
+                    if (currentDate.weekday() === 0) {
+                        row = $('<tr>');
+                        if (options.calendarWeeks) {
+                            row.append('<td class="cw">' + currentDate.week() + '</td>');
+                        }
+                        html.push(row);
+                    }
+                    clsName = '';
+                    if (currentDate.isBefore(viewDate, 'M')) {
+                        clsName += ' old';
+                    }
+                    if (currentDate.isAfter(viewDate, 'M')) {
+                        clsName += ' new';
+                    }
+                    if (currentDate.isSame(date, 'd') && !unset) {
+                        clsName += ' active';
+                    }
+                    if (!isValid(currentDate, 'd')) {
+                        clsName += ' disabled';
+                    }
+                    if (currentDate.isSame(getMoment(), 'd')) {
+                        clsName += ' today';
+                    }
+                    if (currentDate.day() === 0 || currentDate.day() === 6) {
+                        clsName += ' weekend';
+                    }
+                    row.append('<td data-action="selectDay" data-day="' + currentDate.format('L') + '" class="day' + clsName + '">' + currentDate.date() + '</td>');
+                    currentDate.add(1, 'd');
+                }
+
+                daysView.find('tbody').empty().append(html);
+
+                updateMonths();
+
+                updateYears();
+
+                updateDecades();
+            },
+
+            fillHours = function () {
+                var table = widget.find('.timepicker-hours table'),
+                    currentHour = viewDate.clone().startOf('d'),
+                    html = [],
+                    row = $('<tr>');
+
+                if (viewDate.hour() > 11 && !use24Hours) {
+                    currentHour.hour(12);
+                }
+                while (currentHour.isSame(viewDate, 'd') && (use24Hours || (viewDate.hour() < 12 && currentHour.hour() < 12) || viewDate.hour() > 11)) {
+                    if (currentHour.hour() % 4 === 0) {
+                        row = $('<tr>');
+                        html.push(row);
+                    }
+                    row.append('<td data-action="selectHour" class="hour' + (!isValid(currentHour, 'h') ? ' disabled' : '') + '">' + currentHour.format(use24Hours ? 'HH' : 'hh') + '</td>');
+                    currentHour.add(1, 'h');
+                }
+                table.empty().append(html);
+            },
+
+            fillMinutes = function () {
+                var table = widget.find('.timepicker-minutes table'),
+                    currentMinute = viewDate.clone().startOf('h'),
+                    html = [],
+                    row = $('<tr>'),
+                    step = options.stepping === 1 ? 5 : options.stepping;
+
+                while (viewDate.isSame(currentMinute, 'h')) {
+                    if (currentMinute.minute() % (step * 4) === 0) {
+                        row = $('<tr>');
+                        html.push(row);
+                    }
+                    row.append('<td data-action="selectMinute" class="minute' + (!isValid(currentMinute, 'm') ? ' disabled' : '') + '">' + currentMinute.format('mm') + '</td>');
+                    currentMinute.add(step, 'm');
+                }
+                table.empty().append(html);
+            },
+
+            fillSeconds = function () {
+                var table = widget.find('.timepicker-seconds table'),
+                    currentSecond = viewDate.clone().startOf('m'),
+                    html = [],
+                    row = $('<tr>');
+
+                while (viewDate.isSame(currentSecond, 'm')) {
+                    if (currentSecond.second() % 20 === 0) {
+                        row = $('<tr>');
+                        html.push(row);
+                    }
+                    row.append('<td data-action="selectSecond" class="second' + (!isValid(currentSecond, 's') ? ' disabled' : '') + '">' + currentSecond.format('ss') + '</td>');
+                    currentSecond.add(5, 's');
+                }
+
+                table.empty().append(html);
+            },
+
+            fillTime = function () {
+                var toggle, newDate, timeComponents = widget.find('.timepicker span[data-time-component]');
+
+                if (!use24Hours) {
+                    toggle = widget.find('.timepicker [data-action=togglePeriod]');
+                    newDate = date.clone().add((date.hours() >= 12) ? -12 : 12, 'h');
+
+                    toggle.text(date.format('A'));
+
+                    if (isValid(newDate, 'h')) {
+                        toggle.removeClass('disabled');
+                    } else {
+                        toggle.addClass('disabled');
+                    }
+                }
+                timeComponents.filter('[data-time-component=hours]').text(date.format(use24Hours ? 'HH' : 'hh'));
+                timeComponents.filter('[data-time-component=minutes]').text(date.format('mm'));
+                timeComponents.filter('[data-time-component=seconds]').text(date.format('ss'));
+
+                fillHours();
+                fillMinutes();
+                fillSeconds();
+            },
+
+            update = function () {
+                if (!widget) {
+                    return;
+                }
+                fillDate();
+                fillTime();
+            },
+
+            setValue = function (targetMoment) {
+                var oldDate = unset ? null : date;
+
+                // case of calling setValue(null or false)
+                if (!targetMoment) {
+                    unset = true;
+                    input.val('');
+                    element.data('date', '');
+                    notifyEvent({
+                        type: 'dp.change',
+                        date: false,
+                        oldDate: oldDate
+                    });
+                    update();
+                    return;
+                }
+
+                targetMoment = targetMoment.clone().locale(options.locale);
+
+                if (options.stepping !== 1) {
+                    targetMoment.minutes((Math.round(targetMoment.minutes() / options.stepping) * options.stepping) % 60).seconds(0);
+                }
+
+                if (isValid(targetMoment)) {
+                    date = targetMoment;
+                    viewDate = date.clone();
+                    input.val(date.format(actualFormat));
+                    element.data('date', date.format(actualFormat));
+                    unset = false;
+                    update();
+                    notifyEvent({
+                        type: 'dp.change',
+                        date: date.clone(),
+                        oldDate: oldDate
+                    });
+                } else {
+                    if (!options.keepInvalid) {
+                        input.val(unset ? '' : date.format(actualFormat));
+                    }
+                    notifyEvent({
+                        type: 'dp.error',
+                        date: targetMoment
+                    });
+                }
+            },
+
+            hide = function () {
+                ///<summary>Hides the widget. Possibly will emit dp.hide</summary>
+                var transitioning = false;
+                if (!widget) {
+                    return picker;
+                }
+                // Ignore event if in the middle of a picker transition
+                widget.find('.collapse').each(function () {
+                    var collapseData = $(this).data('collapse');
+                    if (collapseData && collapseData.transitioning) {
+                        transitioning = true;
+                        return false;
+                    }
+                    return true;
+                });
+                if (transitioning) {
+                    return picker;
+                }
+                if (component && component.hasClass('btn')) {
+                    component.toggleClass('active');
+                }
+                widget.hide();
+
+                $(window).off('resize', place);
+                widget.off('click', '[data-action]');
+                widget.off('mousedown', false);
+
+                widget.remove();
+                widget = false;
+
+                notifyEvent({
+                    type: 'dp.hide',
+                    date: date.clone()
+                });
+
+                input.blur();
+
+                return picker;
+            },
+
+            clear = function () {
+                setValue(null);
+            },
+
+            /********************************************************************************
+             *
+             * Widget UI interaction functions
+             *
+             ********************************************************************************/
+            actions = {
+                next: function () {
+                    var navFnc = datePickerModes[currentViewMode].navFnc;
+                    viewDate.add(datePickerModes[currentViewMode].navStep, navFnc);
+                    fillDate();
+                    viewUpdate(navFnc);
+                },
+
+                previous: function () {
+                    var navFnc = datePickerModes[currentViewMode].navFnc;
+                    viewDate.subtract(datePickerModes[currentViewMode].navStep, navFnc);
+                    fillDate();
+                    viewUpdate(navFnc);
+                },
+
+                pickerSwitch: function () {
+                    showMode(1);
+                },
+
+                selectMonth: function (e) {
+                    var month = $(e.target).closest('tbody').find('span').index($(e.target));
+                    viewDate.month(month);
+                    if (currentViewMode === minViewModeNumber) {
+                        setValue(date.clone().year(viewDate.year()).month(viewDate.month()));
+                        if (!options.inline) {
+                            hide();
+                        }
+                    } else {
+                        showMode(-1);
+                        fillDate();
+                    }
+                    viewUpdate('M');
+                },
+
+                selectYear: function (e) {
+                    var year = parseInt($(e.target).text(), 10) || 0;
+                    viewDate.year(year);
+                    if (currentViewMode === minViewModeNumber) {
+                        setValue(date.clone().year(viewDate.year()));
+                        if (!options.inline) {
+                            hide();
+                        }
+                    } else {
+                        showMode(-1);
+                        fillDate();
+                    }
+                    viewUpdate('YYYY');
+                },
+
+                selectDecade: function (e) {
+                    var year = parseInt($(e.target).data('selection'), 10) || 0;
+                    viewDate.year(year);
+                    if (currentViewMode === minViewModeNumber) {
+                        setValue(date.clone().year(viewDate.year()));
+                        if (!options.inline) {
+                            hide();
+                        }
+                    } else {
+                        showMode(-1);
+                        fillDate();
+                    }
+                    viewUpdate('YYYY');
+                },
+
+                selectDay: function (e) {
+                    var day = viewDate.clone();
+                    if ($(e.target).is('.old')) {
+                        day.subtract(1, 'M');
+                    }
+                    if ($(e.target).is('.new')) {
+                        day.add(1, 'M');
+                    }
+                    setValue(day.date(parseInt($(e.target).text(), 10)));
+                    if (!hasTime() && !options.keepOpen && !options.inline) {
+                        hide();
+                    }
+                },
+
+                incrementHours: function () {
+                    var newDate = date.clone().add(1, 'h');
+                    if (isValid(newDate, 'h')) {
+                        setValue(newDate);
+                    }
+                },
+
+                incrementMinutes: function () {
+                    var newDate = date.clone().add(options.stepping, 'm');
+                    if (isValid(newDate, 'm')) {
+                        setValue(newDate);
+                    }
+                },
+
+                incrementSeconds: function () {
+                    var newDate = date.clone().add(1, 's');
+                    if (isValid(newDate, 's')) {
+                        setValue(newDate);
+                    }
+                },
+
+                decrementHours: function () {
+                    var newDate = date.clone().subtract(1, 'h');
+                    if (isValid(newDate, 'h')) {
+                        setValue(newDate);
+                    }
+                },
+
+                decrementMinutes: function () {
+                    var newDate = date.clone().subtract(options.stepping, 'm');
+                    if (isValid(newDate, 'm')) {
+                        setValue(newDate);
+                    }
+                },
+
+                decrementSeconds: function () {
+                    var newDate = date.clone().subtract(1, 's');
+                    if (isValid(newDate, 's')) {
+                        setValue(newDate);
+                    }
+                },
+
+                togglePeriod: function () {
+                    setValue(date.clone().add((date.hours() >= 12) ? -12 : 12, 'h'));
+                },
+
+                togglePicker: function (e) {
+                    var $this = $(e.target),
+                        $parent = $this.closest('ul'),
+                        expanded = $parent.find('.in'),
+                        closed = $parent.find('.collapse:not(.in)'),
+                        collapseData;
+
+                    if (expanded && expanded.length) {
+                        collapseData = expanded.data('collapse');
+                        if (collapseData && collapseData.transitioning) {
+                            return;
+                        }
+                        if (expanded.collapse) { // if collapse plugin is available through bootstrap.js then use it
+                            expanded.collapse('hide');
+                            closed.collapse('show');
+                        } else { // otherwise just toggle in class on the two views
+                            expanded.removeClass('in');
+                            closed.addClass('in');
+                        }
+                        if ($this.is('span')) {
+                            $this.toggleClass(options.icons.time + ' ' + options.icons.date);
+                        } else {
+                            $this.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
+                        }
+
+                        // NOTE: uncomment if toggled state will be restored in show()
+                        //if (component) {
+                        //    component.find('span').toggleClass(options.icons.time + ' ' + options.icons.date);
+                        //}
+                    }
+                },
+
+                showPicker: function () {
+                    widget.find('.timepicker > div:not(.timepicker-picker)').hide();
+                    widget.find('.timepicker .timepicker-picker').show();
+                },
+
+                showHours: function () {
+                    widget.find('.timepicker .timepicker-picker').hide();
+                    widget.find('.timepicker .timepicker-hours').show();
+                },
+
+                showMinutes: function () {
+                    widget.find('.timepicker .timepicker-picker').hide();
+                    widget.find('.timepicker .timepicker-minutes').show();
+                },
+
+                showSeconds: function () {
+                    widget.find('.timepicker .timepicker-picker').hide();
+                    widget.find('.timepicker .timepicker-seconds').show();
+                },
+
+                selectHour: function (e) {
+                    var hour = parseInt($(e.target).text(), 10);
+
+                    if (!use24Hours) {
+                        if (date.hours() >= 12) {
+                            if (hour !== 12) {
+                                hour += 12;
+                            }
+                        } else {
+                            if (hour === 12) {
+                                hour = 0;
+                            }
+                        }
+                    }
+                    setValue(date.clone().hours(hour));
+                    actions.showPicker.call(picker);
+                },
+
+                selectMinute: function (e) {
+                    setValue(date.clone().minutes(parseInt($(e.target).text(), 10)));
+                    actions.showPicker.call(picker);
+                },
+
+                selectSecond: function (e) {
+                    setValue(date.clone().seconds(parseInt($(e.target).text(), 10)));
+                    actions.showPicker.call(picker);
+                },
+
+                clear: clear,
+
+                today: function () {
+                    var todaysDate = getMoment();
+                    if (isValid(todaysDate, 'd')) {
+                        setValue(todaysDate);
+                    }
+                },
+
+                close: hide
+            },
+
+            doAction = function (e) {
+                if ($(e.currentTarget).is('.disabled')) {
+                    return false;
+                }
+                actions[$(e.currentTarget).data('action')].apply(picker, arguments);
+                return false;
+            },
+
+            show = function () {
+                ///<summary>Shows the widget. Possibly will emit dp.show and dp.change</summary>
+                var currentMoment,
+                    useCurrentGranularity = {
+                        'year': function (m) {
+                            return m.month(0).date(1).hours(0).seconds(0).minutes(0);
+                        },
+                        'month': function (m) {
+                            return m.date(1).hours(0).seconds(0).minutes(0);
+                        },
+                        'day': function (m) {
+                            return m.hours(0).seconds(0).minutes(0);
+                        },
+                        'hour': function (m) {
+                            return m.seconds(0).minutes(0);
+                        },
+                        'minute': function (m) {
+                            return m.seconds(0);
+                        }
+                    };
+
+                if (input.prop('disabled') || (!options.ignoreReadonly && input.prop('readonly')) || widget) {
+                    return picker;
+                }
+                if (input.val() !== undefined && input.val().trim().length !== 0) {
+                    setValue(parseInputDate(input.val().trim()));
+                } else if (options.useCurrent && unset && ((input.is('input') && input.val().trim().length === 0) || options.inline)) {
+                    currentMoment = getMoment();
+                    if (typeof options.useCurrent === 'string') {
+                        currentMoment = useCurrentGranularity[options.useCurrent](currentMoment);
+                    }
+                    setValue(currentMoment);
+                }
+
+                widget = getTemplate();
+
+                fillDow();
+                fillMonths();
+
+                widget.find('.timepicker-hours').hide();
+                widget.find('.timepicker-minutes').hide();
+                widget.find('.timepicker-seconds').hide();
+
+                update();
+                showMode();
+
+                $(window).on('resize', place);
+                widget.on('click', '[data-action]', doAction); // this handles clicks on the widget
+                widget.on('mousedown', false);
+
+                if (component && component.hasClass('btn')) {
+                    component.toggleClass('active');
+                }
+                widget.show();
+                place();
+
+                if (options.focusOnShow && !input.is(':focus')) {
+                    input.focus();
+                }
+
+                notifyEvent({
+                    type: 'dp.show'
+                });
+                return picker;
+            },
+
+            toggle = function () {
+                /// <summary>Shows or hides the widget</summary>
+                return (widget ? hide() : show());
+            },
+
+            parseInputDate = function (inputDate) {
+                if (options.parseInputDate === undefined) {
+                    if (moment.isMoment(inputDate) || inputDate instanceof Date) {
+                        inputDate = moment(inputDate);
+                    } else {
+                        inputDate = getMoment(inputDate);
+                    }
+                } else {
+                    inputDate = options.parseInputDate(inputDate);
+                }
+                inputDate.locale(options.locale);
+                return inputDate;
+            },
+
+            keydown = function (e) {
+                var handler = null,
+                    index,
+                    index2,
+                    pressedKeys = [],
+                    pressedModifiers = {},
+                    currentKey = e.which,
+                    keyBindKeys,
+                    allModifiersPressed,
+                    pressed = 'p';
+
+                keyState[currentKey] = pressed;
+
+                for (index in keyState) {
+                    if (keyState.hasOwnProperty(index) && keyState[index] === pressed) {
+                        pressedKeys.push(index);
+                        if (parseInt(index, 10) !== currentKey) {
+                            pressedModifiers[index] = true;
+                        }
+                    }
+                }
+
+                for (index in options.keyBinds) {
+                    if (options.keyBinds.hasOwnProperty(index) && typeof (options.keyBinds[index]) === 'function') {
+                        keyBindKeys = index.split(' ');
+                        if (keyBindKeys.length === pressedKeys.length && keyMap[currentKey] === keyBindKeys[keyBindKeys.length - 1]) {
+                            allModifiersPressed = true;
+                            for (index2 = keyBindKeys.length - 2; index2 >= 0; index2--) {
+                                if (!(keyMap[keyBindKeys[index2]] in pressedModifiers)) {
+                                    allModifiersPressed = false;
+                                    break;
+                                }
+                            }
+                            if (allModifiersPressed) {
+                                handler = options.keyBinds[index];
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                if (handler) {
+                    handler.call(picker, widget);
+                    e.stopPropagation();
+                    e.preventDefault();
+                }
+            },
+
+            keyup = function (e) {
+                keyState[e.which] = 'r';
+                e.stopPropagation();
+                e.preventDefault();
+            },
+
+            change = function (e) {
+                var val = $(e.target).val().trim(),
+                    parsedDate = val ? parseInputDate(val) : null;
+                setValue(parsedDate);
+                e.stopImmediatePropagation();
+                return false;
+            },
+
+            attachDatePickerElementEvents = function () {
+                input.on({
+                    'change': change,
+                    'blur': options.debug ? '' : hide,
+                    'keydown': keydown,
+                    'keyup': keyup,
+                    'focus': options.allowInputToggle ? show : ''
+                });
+
+                if (element.is('input')) {
+                    input.on({
+                        'focus': show
+                    });
+                } else if (component) {
+                    component.on('click', toggle);
+                    component.on('mousedown', false);
+                }
+            },
+
+            detachDatePickerElementEvents = function () {
+                input.off({
+                    'change': change,
+                    'blur': blur,
+                    'keydown': keydown,
+                    'keyup': keyup,
+                    'focus': options.allowInputToggle ? hide : ''
+                });
+
+                if (element.is('input')) {
+                    input.off({
+                        'focus': show
+                    });
+                } else if (component) {
+                    component.off('click', toggle);
+                    component.off('mousedown', false);
+                }
+            },
+
+            indexGivenDates = function (givenDatesArray) {
+                // Store given enabledDates and disabledDates as keys.
+                // This way we can check their existence in O(1) time instead of looping through whole array.
+                // (for example: options.enabledDates['2014-02-27'] === true)
+                var givenDatesIndexed = {};
+                $.each(givenDatesArray, function () {
+                    var dDate = parseInputDate(this);
+                    if (dDate.isValid()) {
+                        givenDatesIndexed[dDate.format('YYYY-MM-DD')] = true;
+                    }
+                });
+                return (Object.keys(givenDatesIndexed).length) ? givenDatesIndexed : false;
+            },
+
+            indexGivenHours = function (givenHoursArray) {
+                // Store given enabledHours and disabledHours as keys.
+                // This way we can check their existence in O(1) time instead of looping through whole array.
+                // (for example: options.enabledHours['2014-02-27'] === true)
+                var givenHoursIndexed = {};
+                $.each(givenHoursArray, function () {
+                    givenHoursIndexed[this] = true;
+                });
+                return (Object.keys(givenHoursIndexed).length) ? givenHoursIndexed : false;
+            },
+
+            initFormatting = function () {
+                var format = options.format || 'L LT';
+
+                actualFormat = format.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput) {
+                    var newinput = date.localeData().longDateFormat(formatInput) || formatInput;
+                    return newinput.replace(/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g, function (formatInput2) { //temp fix for #740
+                        return date.localeData().longDateFormat(formatInput2) || formatInput2;
+                    });
+                });
+
+
+                parseFormats = options.extraFormats ? options.extraFormats.slice() : [];
+                if (parseFormats.indexOf(format) < 0 && parseFormats.indexOf(actualFormat) < 0) {
+                    parseFormats.push(actualFormat);
+                }
+
+                use24Hours = (actualFormat.toLowerCase().indexOf('a') < 1 && actualFormat.replace(/\[.*?\]/g, '').indexOf('h') < 1);
+
+                if (isEnabled('y')) {
+                    minViewModeNumber = 2;
+                }
+                if (isEnabled('M')) {
+                    minViewModeNumber = 1;
+                }
+                if (isEnabled('d')) {
+                    minViewModeNumber = 0;
+                }
+
+                currentViewMode = Math.max(minViewModeNumber, currentViewMode);
+
+                if (!unset) {
+                    setValue(date);
+                }
+            };
+
+        /********************************************************************************
+         *
+         * Public API functions
+         * =====================
+         *
+         * Important: Do not expose direct references to private objects or the options
+         * object to the outer world. Always return a clone when returning values or make
+         * a clone when setting a private variable.
+         *
+         ********************************************************************************/
+        picker.destroy = function () {
+            ///<summary>Destroys the widget and removes all attached event listeners</summary>
+            hide();
+            detachDatePickerElementEvents();
+            element.removeData('DateTimePicker');
+            element.removeData('date');
+        };
+
+        picker.toggle = toggle;
+
+        picker.show = show;
+
+        picker.hide = hide;
+
+        picker.disable = function () {
+            ///<summary>Disables the input element, the component is attached to, by adding a disabled="true" attribute to it.
+            ///If the widget was visible before that call it is hidden. Possibly emits dp.hide</summary>
+            hide();
+            if (component && component.hasClass('btn')) {
+                component.addClass('disabled');
+            }
+            input.prop('disabled', true);
+            return picker;
+        };
+
+        picker.enable = function () {
+            ///<summary>Enables the input element, the component is attached to, by removing disabled attribute from it.</summary>
+            if (component && component.hasClass('btn')) {
+                component.removeClass('disabled');
+            }
+            input.prop('disabled', false);
+            return picker;
+        };
+
+        picker.ignoreReadonly = function (ignoreReadonly) {
+            if (arguments.length === 0) {
+                return options.ignoreReadonly;
+            }
+            if (typeof ignoreReadonly !== 'boolean') {
+                throw new TypeError('ignoreReadonly () expects a boolean parameter');
+            }
+            options.ignoreReadonly = ignoreReadonly;
+            return picker;
+        };
+
+        picker.options = function (newOptions) {
+            if (arguments.length === 0) {
+                return $.extend(true, {}, options);
+            }
+
+            if (!(newOptions instanceof Object)) {
+                throw new TypeError('options() options parameter should be an object');
+            }
+            $.extend(true, options, newOptions);
+            $.each(options, function (key, value) {
+                if (picker[key] !== undefined) {
+                    picker[key](value);
+                } else {
+                    throw new TypeError('option ' + key + ' is not recognized!');
+                }
+            });
+            return picker;
+        };
+
+        picker.date = function (newDate) {
+            ///<signature helpKeyword="$.fn.datetimepicker.date">
+            ///<summary>Returns the component's model current date, a moment object or null if not set.</summary>
+            ///<returns type="Moment">date.clone()</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
+            ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, Date, moment, null parameter.</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                if (unset) {
+                    return null;
+                }
+                return date.clone();
+            }
+
+            if (newDate !== null && typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
+                throw new TypeError('date() parameter must be one of [null, string, moment or Date]');
+            }
+
+            setValue(newDate === null ? null : parseInputDate(newDate));
+            return picker;
+        };
+
+        picker.format = function (newFormat) {
+            ///<summary>test su</summary>
+            ///<param name="newFormat">info about para</param>
+            ///<returns type="string|boolean">returns foo</returns>
+            if (arguments.length === 0) {
+                return options.format;
+            }
+
+            if ((typeof newFormat !== 'string') && ((typeof newFormat !== 'boolean') || (newFormat !== false))) {
+                throw new TypeError('format() expects a sting or boolean:false parameter ' + newFormat);
+            }
+
+            options.format = newFormat;
+            if (actualFormat) {
+                initFormatting(); // reinit formatting
+            }
+            return picker;
+        };
+
+        picker.timeZone = function (newZone) {
+            if (arguments.length === 0) {
+                return options.timeZone;
+            }
+
+            options.timeZone = newZone;
+
+            return picker;
+        };
+
+        picker.dayViewHeaderFormat = function (newFormat) {
+            if (arguments.length === 0) {
+                return options.dayViewHeaderFormat;
+            }
+
+            if (typeof newFormat !== 'string') {
+                throw new TypeError('dayViewHeaderFormat() expects a string parameter');
+            }
+
+            options.dayViewHeaderFormat = newFormat;
+            return picker;
+        };
+
+        picker.extraFormats = function (formats) {
+            if (arguments.length === 0) {
+                return options.extraFormats;
+            }
+
+            if (formats !== false && !(formats instanceof Array)) {
+                throw new TypeError('extraFormats() expects an array or false parameter');
+            }
+
+            options.extraFormats = formats;
+            if (parseFormats) {
+                initFormatting(); // reinit formatting
+            }
+            return picker;
+        };
+
+        picker.disabledDates = function (dates) {
+            ///<signature helpKeyword="$.fn.datetimepicker.disabledDates">
+            ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
+            ///<returns type="array">options.disabledDates</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+            ///options.enabledDates if such exist.</summary>
+            ///<param name="dates" locid="$.fn.datetimepicker.disabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                return (options.disabledDates ? $.extend({}, options.disabledDates) : options.disabledDates);
+            }
+
+            if (!dates) {
+                options.disabledDates = false;
+                update();
+                return picker;
+            }
+            if (!(dates instanceof Array)) {
+                throw new TypeError('disabledDates() expects an array parameter');
+            }
+            options.disabledDates = indexGivenDates(dates);
+            options.enabledDates = false;
+            update();
+            return picker;
+        };
+
+        picker.enabledDates = function (dates) {
+            ///<signature helpKeyword="$.fn.datetimepicker.enabledDates">
+            ///<summary>Returns an array with the currently set enabled dates on the component.</summary>
+            ///<returns type="array">options.enabledDates</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledDates if such exist.</summary>
+            ///<param name="dates" locid="$.fn.datetimepicker.enabledDates_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                return (options.enabledDates ? $.extend({}, options.enabledDates) : options.enabledDates);
+            }
+
+            if (!dates) {
+                options.enabledDates = false;
+                update();
+                return picker;
+            }
+            if (!(dates instanceof Array)) {
+                throw new TypeError('enabledDates() expects an array parameter');
+            }
+            options.enabledDates = indexGivenDates(dates);
+            options.disabledDates = false;
+            update();
+            return picker;
+        };
+
+        picker.daysOfWeekDisabled = function (daysOfWeekDisabled) {
+            if (arguments.length === 0) {
+                return options.daysOfWeekDisabled.splice(0);
+            }
+
+            if ((typeof daysOfWeekDisabled === 'boolean') && !daysOfWeekDisabled) {
+                options.daysOfWeekDisabled = false;
+                update();
+                return picker;
+            }
+
+            if (!(daysOfWeekDisabled instanceof Array)) {
+                throw new TypeError('daysOfWeekDisabled() expects an array parameter');
+            }
+            options.daysOfWeekDisabled = daysOfWeekDisabled.reduce(function (previousValue, currentValue) {
+                currentValue = parseInt(currentValue, 10);
+                if (currentValue > 6 || currentValue < 0 || isNaN(currentValue)) {
+                    return previousValue;
+                }
+                if (previousValue.indexOf(currentValue) === -1) {
+                    previousValue.push(currentValue);
+                }
+                return previousValue;
+            }, []).sort();
+            if (options.useCurrent && !options.keepInvalid) {
+                var tries = 0;
+                while (!isValid(date, 'd')) {
+                    date.add(1, 'd');
+                    if (tries === 7) {
+                        throw 'Tried 7 times to find a valid date';
+                    }
+                    tries++;
+                }
+                setValue(date);
+            }
+            update();
+            return picker;
+        };
+
+        picker.maxDate = function (maxDate) {
+            if (arguments.length === 0) {
+                return options.maxDate ? options.maxDate.clone() : options.maxDate;
+            }
+
+            if ((typeof maxDate === 'boolean') && maxDate === false) {
+                options.maxDate = false;
+                update();
+                return picker;
+            }
+
+            if (typeof maxDate === 'string') {
+                if (maxDate === 'now' || maxDate === 'moment') {
+                    maxDate = getMoment();
+                }
+            }
+
+            var parsedDate = parseInputDate(maxDate);
+
+            if (!parsedDate.isValid()) {
+                throw new TypeError('maxDate() Could not parse date parameter: ' + maxDate);
+            }
+            if (options.minDate && parsedDate.isBefore(options.minDate)) {
+                throw new TypeError('maxDate() date parameter is before options.minDate: ' + parsedDate.format(actualFormat));
+            }
+            options.maxDate = parsedDate;
+            if (options.useCurrent && !options.keepInvalid && date.isAfter(maxDate)) {
+                setValue(options.maxDate);
+            }
+            if (viewDate.isAfter(parsedDate)) {
+                viewDate = parsedDate.clone().subtract(options.stepping, 'm');
+            }
+            update();
+            return picker;
+        };
+
+        picker.minDate = function (minDate) {
+            if (arguments.length === 0) {
+                return options.minDate ? options.minDate.clone() : options.minDate;
+            }
+
+            if ((typeof minDate === 'boolean') && minDate === false) {
+                options.minDate = false;
+                update();
+                return picker;
+            }
+
+            if (typeof minDate === 'string') {
+                if (minDate === 'now' || minDate === 'moment') {
+                    minDate = getMoment();
+                }
+            }
+
+            var parsedDate = parseInputDate(minDate);
+
+            if (!parsedDate.isValid()) {
+                throw new TypeError('minDate() Could not parse date parameter: ' + minDate);
+            }
+            if (options.maxDate && parsedDate.isAfter(options.maxDate)) {
+                throw new TypeError('minDate() date parameter is after options.maxDate: ' + parsedDate.format(actualFormat));
+            }
+            options.minDate = parsedDate;
+            if (options.useCurrent && !options.keepInvalid && date.isBefore(minDate)) {
+                setValue(options.minDate);
+            }
+            if (viewDate.isBefore(parsedDate)) {
+                viewDate = parsedDate.clone().add(options.stepping, 'm');
+            }
+            update();
+            return picker;
+        };
+
+        picker.defaultDate = function (defaultDate) {
+            ///<signature helpKeyword="$.fn.datetimepicker.defaultDate">
+            ///<summary>Returns a moment with the options.defaultDate option configuration or false if not set</summary>
+            ///<returns type="Moment">date.clone()</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Will set the picker's inital date. If a boolean:false value is passed the options.defaultDate parameter is cleared.</summary>
+            ///<param name="defaultDate" locid="$.fn.datetimepicker.defaultDate_p:defaultDate">Takes a string, Date, moment, boolean:false</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                return options.defaultDate ? options.defaultDate.clone() : options.defaultDate;
+            }
+            if (!defaultDate) {
+                options.defaultDate = false;
+                return picker;
+            }
+
+            if (typeof defaultDate === 'string') {
+                if (defaultDate === 'now' || defaultDate === 'moment') {
+                    defaultDate = getMoment();
+                }
+            }
+
+            var parsedDate = parseInputDate(defaultDate);
+            if (!parsedDate.isValid()) {
+                throw new TypeError('defaultDate() Could not parse date parameter: ' + defaultDate);
+            }
+            if (!isValid(parsedDate)) {
+                throw new TypeError('defaultDate() date passed is invalid according to component setup validations');
+            }
+
+            options.defaultDate = parsedDate;
+
+            if ((options.defaultDate && options.inline) || input.val().trim() === '') {
+                setValue(options.defaultDate);
+            }
+            return picker;
+        };
+
+        picker.locale = function (locale) {
+            if (arguments.length === 0) {
+                return options.locale;
+            }
+
+            if (!moment.localeData(locale)) {
+                throw new TypeError('locale() locale ' + locale + ' is not loaded from moment locales!');
+            }
+
+            options.locale = locale;
+            date.locale(options.locale);
+            viewDate.locale(options.locale);
+
+            if (actualFormat) {
+                initFormatting(); // reinit formatting
+            }
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.stepping = function (stepping) {
+            if (arguments.length === 0) {
+                return options.stepping;
+            }
+
+            stepping = parseInt(stepping, 10);
+            if (isNaN(stepping) || stepping < 1) {
+                stepping = 1;
+            }
+            options.stepping = stepping;
+            return picker;
+        };
+
+        picker.useCurrent = function (useCurrent) {
+            var useCurrentOptions = ['year', 'month', 'day', 'hour', 'minute'];
+            if (arguments.length === 0) {
+                return options.useCurrent;
+            }
+
+            if ((typeof useCurrent !== 'boolean') && (typeof useCurrent !== 'string')) {
+                throw new TypeError('useCurrent() expects a boolean or string parameter');
+            }
+            if (typeof useCurrent === 'string' && useCurrentOptions.indexOf(useCurrent.toLowerCase()) === -1) {
+                throw new TypeError('useCurrent() expects a string parameter of ' + useCurrentOptions.join(', '));
+            }
+            options.useCurrent = useCurrent;
+            return picker;
+        };
+
+        picker.collapse = function (collapse) {
+            if (arguments.length === 0) {
+                return options.collapse;
+            }
+
+            if (typeof collapse !== 'boolean') {
+                throw new TypeError('collapse() expects a boolean parameter');
+            }
+            if (options.collapse === collapse) {
+                return picker;
+            }
+            options.collapse = collapse;
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.icons = function (icons) {
+            if (arguments.length === 0) {
+                return $.extend({}, options.icons);
+            }
+
+            if (!(icons instanceof Object)) {
+                throw new TypeError('icons() expects parameter to be an Object');
+            }
+            $.extend(options.icons, icons);
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.tooltips = function (tooltips) {
+            if (arguments.length === 0) {
+                return $.extend({}, options.tooltips);
+            }
+
+            if (!(tooltips instanceof Object)) {
+                throw new TypeError('tooltips() expects parameter to be an Object');
+            }
+            $.extend(options.tooltips, tooltips);
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.useStrict = function (useStrict) {
+            if (arguments.length === 0) {
+                return options.useStrict;
+            }
+
+            if (typeof useStrict !== 'boolean') {
+                throw new TypeError('useStrict() expects a boolean parameter');
+            }
+            options.useStrict = useStrict;
+            return picker;
+        };
+
+        picker.sideBySide = function (sideBySide) {
+            if (arguments.length === 0) {
+                return options.sideBySide;
+            }
+
+            if (typeof sideBySide !== 'boolean') {
+                throw new TypeError('sideBySide() expects a boolean parameter');
+            }
+            options.sideBySide = sideBySide;
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.viewMode = function (viewMode) {
+            if (arguments.length === 0) {
+                return options.viewMode;
+            }
+
+            if (typeof viewMode !== 'string') {
+                throw new TypeError('viewMode() expects a string parameter');
+            }
+
+            if (viewModes.indexOf(viewMode) === -1) {
+                throw new TypeError('viewMode() parameter must be one of (' + viewModes.join(', ') + ') value');
+            }
+
+            options.viewMode = viewMode;
+            currentViewMode = Math.max(viewModes.indexOf(viewMode), minViewModeNumber);
+
+            showMode();
+            return picker;
+        };
+
+        picker.toolbarPlacement = function (toolbarPlacement) {
+            if (arguments.length === 0) {
+                return options.toolbarPlacement;
+            }
+
+            if (typeof toolbarPlacement !== 'string') {
+                throw new TypeError('toolbarPlacement() expects a string parameter');
+            }
+            if (toolbarPlacements.indexOf(toolbarPlacement) === -1) {
+                throw new TypeError('toolbarPlacement() parameter must be one of (' + toolbarPlacements.join(', ') + ') value');
+            }
+            options.toolbarPlacement = toolbarPlacement;
+
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.widgetPositioning = function (widgetPositioning) {
+            if (arguments.length === 0) {
+                return $.extend({}, options.widgetPositioning);
+            }
+
+            if (({}).toString.call(widgetPositioning) !== '[object Object]') {
+                throw new TypeError('widgetPositioning() expects an object variable');
+            }
+            if (widgetPositioning.horizontal) {
+                if (typeof widgetPositioning.horizontal !== 'string') {
+                    throw new TypeError('widgetPositioning() horizontal variable must be a string');
+                }
+                widgetPositioning.horizontal = widgetPositioning.horizontal.toLowerCase();
+                if (horizontalModes.indexOf(widgetPositioning.horizontal) === -1) {
+                    throw new TypeError('widgetPositioning() expects horizontal parameter to be one of (' + horizontalModes.join(', ') + ')');
+                }
+                options.widgetPositioning.horizontal = widgetPositioning.horizontal;
+            }
+            if (widgetPositioning.vertical) {
+                if (typeof widgetPositioning.vertical !== 'string') {
+                    throw new TypeError('widgetPositioning() vertical variable must be a string');
+                }
+                widgetPositioning.vertical = widgetPositioning.vertical.toLowerCase();
+                if (verticalModes.indexOf(widgetPositioning.vertical) === -1) {
+                    throw new TypeError('widgetPositioning() expects vertical parameter to be one of (' + verticalModes.join(', ') + ')');
+                }
+                options.widgetPositioning.vertical = widgetPositioning.vertical;
+            }
+            update();
+            return picker;
+        };
+
+        picker.calendarWeeks = function (calendarWeeks) {
+            if (arguments.length === 0) {
+                return options.calendarWeeks;
+            }
+
+            if (typeof calendarWeeks !== 'boolean') {
+                throw new TypeError('calendarWeeks() expects parameter to be a boolean value');
+            }
+
+            options.calendarWeeks = calendarWeeks;
+            update();
+            return picker;
+        };
+
+        picker.showTodayButton = function (showTodayButton) {
+            if (arguments.length === 0) {
+                return options.showTodayButton;
+            }
+
+            if (typeof showTodayButton !== 'boolean') {
+                throw new TypeError('showTodayButton() expects a boolean parameter');
+            }
+
+            options.showTodayButton = showTodayButton;
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.showClear = function (showClear) {
+            if (arguments.length === 0) {
+                return options.showClear;
+            }
+
+            if (typeof showClear !== 'boolean') {
+                throw new TypeError('showClear() expects a boolean parameter');
+            }
+
+            options.showClear = showClear;
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.widgetParent = function (widgetParent) {
+            if (arguments.length === 0) {
+                return options.widgetParent;
+            }
+
+            if (typeof widgetParent === 'string') {
+                widgetParent = $(widgetParent);
+            }
+
+            if (widgetParent !== null && (typeof widgetParent !== 'string' && !(widgetParent instanceof $))) {
+                throw new TypeError('widgetParent() expects a string or a jQuery object parameter');
+            }
+
+            options.widgetParent = widgetParent;
+            if (widget) {
+                hide();
+                show();
+            }
+            return picker;
+        };
+
+        picker.keepOpen = function (keepOpen) {
+            if (arguments.length === 0) {
+                return options.keepOpen;
+            }
+
+            if (typeof keepOpen !== 'boolean') {
+                throw new TypeError('keepOpen() expects a boolean parameter');
+            }
+
+            options.keepOpen = keepOpen;
+            return picker;
+        };
+
+        picker.focusOnShow = function (focusOnShow) {
+            if (arguments.length === 0) {
+                return options.focusOnShow;
+            }
+
+            if (typeof focusOnShow !== 'boolean') {
+                throw new TypeError('focusOnShow() expects a boolean parameter');
+            }
+
+            options.focusOnShow = focusOnShow;
+            return picker;
+        };
+
+        picker.inline = function (inline) {
+            if (arguments.length === 0) {
+                return options.inline;
+            }
+
+            if (typeof inline !== 'boolean') {
+                throw new TypeError('inline() expects a boolean parameter');
+            }
+
+            options.inline = inline;
+            return picker;
+        };
+
+        picker.clear = function () {
+            clear();
+            return picker;
+        };
+
+        picker.keyBinds = function (keyBinds) {
+            options.keyBinds = keyBinds;
+            return picker;
+        };
+
+        picker.getMoment = function (d) {
+            return getMoment(d);
+        };
+
+        picker.debug = function (debug) {
+            if (typeof debug !== 'boolean') {
+                throw new TypeError('debug() expects a boolean parameter');
+            }
+
+            options.debug = debug;
+            return picker;
+        };
+
+        picker.allowInputToggle = function (allowInputToggle) {
+            if (arguments.length === 0) {
+                return options.allowInputToggle;
+            }
+
+            if (typeof allowInputToggle !== 'boolean') {
+                throw new TypeError('allowInputToggle() expects a boolean parameter');
+            }
+
+            options.allowInputToggle = allowInputToggle;
+            return picker;
+        };
+
+        picker.showClose = function (showClose) {
+            if (arguments.length === 0) {
+                return options.showClose;
+            }
+
+            if (typeof showClose !== 'boolean') {
+                throw new TypeError('showClose() expects a boolean parameter');
+            }
+
+            options.showClose = showClose;
+            return picker;
+        };
+
+        picker.keepInvalid = function (keepInvalid) {
+            if (arguments.length === 0) {
+                return options.keepInvalid;
+            }
+
+            if (typeof keepInvalid !== 'boolean') {
+                throw new TypeError('keepInvalid() expects a boolean parameter');
+            }
+            options.keepInvalid = keepInvalid;
+            return picker;
+        };
+
+        picker.datepickerInput = function (datepickerInput) {
+            if (arguments.length === 0) {
+                return options.datepickerInput;
+            }
+
+            if (typeof datepickerInput !== 'string') {
+                throw new TypeError('datepickerInput() expects a string parameter');
+            }
+
+            options.datepickerInput = datepickerInput;
+            return picker;
+        };
+
+        picker.parseInputDate = function (parseInputDate) {
+            if (arguments.length === 0) {
+                return options.parseInputDate;
+            }
+
+            if (typeof parseInputDate !== 'function') {
+                throw new TypeError('parseInputDate() sholud be as function');
+            }
+
+            options.parseInputDate = parseInputDate;
+
+            return picker;
+        };
+
+        picker.disabledTimeIntervals = function (disabledTimeIntervals) {
+            ///<signature helpKeyword="$.fn.datetimepicker.disabledTimeIntervals">
+            ///<summary>Returns an array with the currently set disabled dates on the component.</summary>
+            ///<returns type="array">options.disabledTimeIntervals</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+            ///options.enabledDates if such exist.</summary>
+            ///<param name="dates" locid="$.fn.datetimepicker.disabledTimeIntervals_p:dates">Takes an [ string or Date or moment ] of values and allows the user to select only from those days.</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                return (options.disabledTimeIntervals ? $.extend({}, options.disabledTimeIntervals) : options.disabledTimeIntervals);
+            }
+
+            if (!disabledTimeIntervals) {
+                options.disabledTimeIntervals = false;
+                update();
+                return picker;
+            }
+            if (!(disabledTimeIntervals instanceof Array)) {
+                throw new TypeError('disabledTimeIntervals() expects an array parameter');
+            }
+            options.disabledTimeIntervals = disabledTimeIntervals;
+            update();
+            return picker;
+        };
+
+        picker.disabledHours = function (hours) {
+            ///<signature helpKeyword="$.fn.datetimepicker.disabledHours">
+            ///<summary>Returns an array with the currently set disabled hours on the component.</summary>
+            ///<returns type="array">options.disabledHours</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of
+            ///options.enabledHours if such exist.</summary>
+            ///<param name="hours" locid="$.fn.datetimepicker.disabledHours_p:hours">Takes an [ int ] of values and disallows the user to select only from those hours.</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                return (options.disabledHours ? $.extend({}, options.disabledHours) : options.disabledHours);
+            }
+
+            if (!hours) {
+                options.disabledHours = false;
+                update();
+                return picker;
+            }
+            if (!(hours instanceof Array)) {
+                throw new TypeError('disabledHours() expects an array parameter');
+            }
+            options.disabledHours = indexGivenHours(hours);
+            options.enabledHours = false;
+            if (options.useCurrent && !options.keepInvalid) {
+                var tries = 0;
+                while (!isValid(date, 'h')) {
+                    date.add(1, 'h');
+                    if (tries === 24) {
+                        throw 'Tried 24 times to find a valid date';
+                    }
+                    tries++;
+                }
+                setValue(date);
+            }
+            update();
+            return picker;
+        };
+
+        picker.enabledHours = function (hours) {
+            ///<signature helpKeyword="$.fn.datetimepicker.enabledHours">
+            ///<summary>Returns an array with the currently set enabled hours on the component.</summary>
+            ///<returns type="array">options.enabledHours</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Setting this takes precedence over options.minDate, options.maxDate configuration. Also calling this function removes the configuration of options.disabledHours if such exist.</summary>
+            ///<param name="hours" locid="$.fn.datetimepicker.enabledHours_p:hours">Takes an [ int ] of values and allows the user to select only from those hours.</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                return (options.enabledHours ? $.extend({}, options.enabledHours) : options.enabledHours);
+            }
+
+            if (!hours) {
+                options.enabledHours = false;
+                update();
+                return picker;
+            }
+            if (!(hours instanceof Array)) {
+                throw new TypeError('enabledHours() expects an array parameter');
+            }
+            options.enabledHours = indexGivenHours(hours);
+            options.disabledHours = false;
+            if (options.useCurrent && !options.keepInvalid) {
+                var tries = 0;
+                while (!isValid(date, 'h')) {
+                    date.add(1, 'h');
+                    if (tries === 24) {
+                        throw 'Tried 24 times to find a valid date';
+                    }
+                    tries++;
+                }
+                setValue(date);
+            }
+            update();
+            return picker;
+        };
+
+        picker.viewDate = function (newDate) {
+            ///<signature helpKeyword="$.fn.datetimepicker.viewDate">
+            ///<summary>Returns the component's model current viewDate, a moment object or null if not set.</summary>
+            ///<returns type="Moment">viewDate.clone()</returns>
+            ///</signature>
+            ///<signature>
+            ///<summary>Sets the components model current moment to it. Passing a null value unsets the components model current moment. Parsing of the newDate parameter is made using moment library with the options.format and options.useStrict components configuration.</summary>
+            ///<param name="newDate" locid="$.fn.datetimepicker.date_p:newDate">Takes string, viewDate, moment, null parameter.</param>
+            ///</signature>
+            if (arguments.length === 0) {
+                return viewDate.clone();
+            }
+
+            if (!newDate) {
+                viewDate = date.clone();
+                return picker;
+            }
+
+            if (typeof newDate !== 'string' && !moment.isMoment(newDate) && !(newDate instanceof Date)) {
+                throw new TypeError('viewDate() parameter must be one of [string, moment or Date]');
+            }
+
+            viewDate = parseInputDate(newDate);
+            viewUpdate();
+            return picker;
+        };
+
+        // initializing element and component attributes
+        if (element.is('input')) {
+            input = element;
+        } else {
+            input = element.find(options.datepickerInput);
+            if (input.size() === 0) {
+                input = element.find('input');
+            } else if (!input.is('input')) {
+                throw new Error('CSS class "' + options.datepickerInput + '" cannot be applied to non input element');
+            }
+        }
+
+        if (element.hasClass('input-group')) {
+            // in case there is more then one 'input-group-addon' Issue #48
+            if (element.find('.datepickerbutton').size() === 0) {
+                component = element.find('.input-group-addon');
+            } else {
+                component = element.find('.datepickerbutton');
+            }
+        }
+
+        if (!options.inline && !input.is('input')) {
+            throw new Error('Could not initialize DateTimePicker without an input element');
+        }
+
+        // Set defaults for date here now instead of in var declaration
+        date = getMoment();
+        viewDate = date.clone();
+
+        $.extend(true, options, dataToOptions());
+
+        picker.options(options);
+
+        initFormatting();
+
+        attachDatePickerElementEvents();
+
+        if (input.prop('disabled')) {
+            picker.disable();
+        }
+        if (input.is('input') && input.val().trim().length !== 0) {
+            setValue(parseInputDate(input.val().trim()));
+        }
+        else if (options.defaultDate && input.attr('placeholder') === undefined) {
+            setValue(options.defaultDate);
+        }
+        if (options.inline) {
+            show();
+        }
+        return picker;
+    };
+
+    /********************************************************************************
+     *
+     * jQuery plugin constructor and defaults object
+     *
+     ********************************************************************************/
+
+    $.fn.datetimepicker = function (options) {
+        return this.each(function () {
+            var $this = $(this);
+            if (!$this.data('DateTimePicker')) {
+                // create a private copy of the defaults object
+                options = $.extend(true, {}, $.fn.datetimepicker.defaults, options);
+                $this.data('DateTimePicker', dateTimePicker($this, options));
+            }
+        });
+    };
+
+    $.fn.datetimepicker.defaults = {
+        timeZone: 'Etc/UTC',
+        format: false,
+        dayViewHeaderFormat: 'MMMM YYYY',
+        extraFormats: false,
+        stepping: 1,
+        minDate: false,
+        maxDate: false,
+        useCurrent: true,
+        collapse: true,
+        locale: moment.locale(),
+        defaultDate: false,
+        disabledDates: false,
+        enabledDates: false,
+        icons: {
+            time: 'glyphicon glyphicon-time',
+            date: 'glyphicon glyphicon-calendar',
+            up: 'glyphicon glyphicon-chevron-up',
+            down: 'glyphicon glyphicon-chevron-down',
+            previous: 'glyphicon glyphicon-chevron-left',
+            next: 'glyphicon glyphicon-chevron-right',
+            today: 'glyphicon glyphicon-screenshot',
+            clear: 'glyphicon glyphicon-trash',
+            close: 'glyphicon glyphicon-remove'
+        },
+        tooltips: {
+            today: 'Go to today',
+            clear: 'Clear selection',
+            close: 'Close the picker',
+            selectMonth: 'Select Month',
+            prevMonth: 'Previous Month',
+            nextMonth: 'Next Month',
+            selectYear: 'Select Year',
+            prevYear: 'Previous Year',
+            nextYear: 'Next Year',
+            selectDecade: 'Select Decade',
+            prevDecade: 'Previous Decade',
+            nextDecade: 'Next Decade',
+            prevCentury: 'Previous Century',
+            nextCentury: 'Next Century',
+            pickHour: 'Pick Hour',
+            incrementHour: 'Increment Hour',
+            decrementHour: 'Decrement Hour',
+            pickMinute: 'Pick Minute',
+            incrementMinute: 'Increment Minute',
+            decrementMinute: 'Decrement Minute',
+            pickSecond: 'Pick Second',
+            incrementSecond: 'Increment Second',
+            decrementSecond: 'Decrement Second',
+            togglePeriod: 'Toggle Period',
+            selectTime: 'Select Time'
+        },
+        useStrict: false,
+        sideBySide: false,
+        daysOfWeekDisabled: false,
+        calendarWeeks: false,
+        viewMode: 'days',
+        toolbarPlacement: 'default',
+        showTodayButton: false,
+        showClear: false,
+        showClose: false,
+        widgetPositioning: {
+            horizontal: 'auto',
+            vertical: 'auto'
+        },
+        widgetParent: null,
+        ignoreReadonly: false,
+        keepOpen: false,
+        focusOnShow: true,
+        inline: false,
+        keepInvalid: false,
+        datepickerInput: '.datepickerinput',
+        keyBinds: {
+            up: function (widget) {
+                if (!widget) {
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().subtract(7, 'd'));
+                } else {
+                    this.date(d.clone().add(this.stepping(), 'm'));
+                }
+            },
+            down: function (widget) {
+                if (!widget) {
+                    this.show();
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().add(7, 'd'));
+                } else {
+                    this.date(d.clone().subtract(this.stepping(), 'm'));
+                }
+            },
+            'control up': function (widget) {
+                if (!widget) {
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().subtract(1, 'y'));
+                } else {
+                    this.date(d.clone().add(1, 'h'));
+                }
+            },
+            'control down': function (widget) {
+                if (!widget) {
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().add(1, 'y'));
+                } else {
+                    this.date(d.clone().subtract(1, 'h'));
+                }
+            },
+            left: function (widget) {
+                if (!widget) {
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().subtract(1, 'd'));
+                }
+            },
+            right: function (widget) {
+                if (!widget) {
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().add(1, 'd'));
+                }
+            },
+            pageUp: function (widget) {
+                if (!widget) {
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().subtract(1, 'M'));
+                }
+            },
+            pageDown: function (widget) {
+                if (!widget) {
+                    return;
+                }
+                var d = this.date() || this.getMoment();
+                if (widget.find('.datepicker').is(':visible')) {
+                    this.date(d.clone().add(1, 'M'));
+                }
+            },
+            enter: function () {
+                this.hide();
+            },
+            escape: function () {
+                this.hide();
+            },
+            //tab: function (widget) { //this break the flow of the form. disabling for now
+            //    var toggle = widget.find('.picker-switch a[data-action="togglePicker"]');
+            //    if(toggle.length > 0) toggle.click();
+            //},
+            'control space': function (widget) {
+                if (widget.find('.timepicker').is(':visible')) {
+                    widget.find('.btn[data-action="togglePeriod"]').click();
+                }
+            },
+            t: function () {
+                this.date(this.getMoment());
+            },
+            'delete': function () {
+                this.clear();
+            }
+        },
+        debug: false,
+        allowInputToggle: false,
+        disabledTimeIntervals: false,
+        disabledHours: false,
+        enabledHours: false,
+        viewDate: false
+    };
+}));
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js
new file mode 100644
index 0000000..db3d085
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js
@@ -0,0 +1,9 @@
+/*! version : 4.17.37
+ =========================================================
+ bootstrap-datetimejs
+ https://github.com/Eonasdan/bootstrap-datetimepicker
+ Copyright (c) 2015 Jonathan Peterson
+ =========================================================
+ */
+!function(a){"use strict";if("function"==typeof define&&define.amd)define(["jquery","moment"],a);else if("object"==typeof exports)a(require("jquery"),require("moment"));else{if("undefined"==typeof jQuery)throw"bootstrap-datetimepicker requires jQuery to be loaded first";if("undefined"==typeof moment)throw"bootstrap-datetimepicker requires Moment.js to be loaded first";a(jQuery,moment)}}(function(a,b){"use strict";if(!b)throw new Error("bootstrap-datetimepicker requires Moment.js to be lo [...]
+if("function"!=typeof a)throw new TypeError("parseInputDate() sholud be as function");return d.parseInputDate=a,l},l.disabledTimeIntervals=function(b){if(0===arguments.length)return d.disabledTimeIntervals?a.extend({},d.disabledTimeIntervals):d.disabledTimeIntervals;if(!b)return d.disabledTimeIntervals=!1,$(),l;if(!(b instanceof Array))throw new TypeError("disabledTimeIntervals() expects an array parameter");return d.disabledTimeIntervals=b,$(),l},l.disabledHours=function(b){if(0===argum [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css
new file mode 100644
index 0000000..d688ea6
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css
@@ -0,0 +1,7681 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+/*
+ * theme: standard
+ * agent: standard
+ */
+/* box -------------------------------------------------------------- */
+.tobago-box-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+.tobago-flexLayout {
+  display: -webkit-flex;
+  /* needed e.g. for Safari 8.0.2 */
+  display: -ms-flexbox;
+  /* needed for IE 10 */
+  display: -webkit-box;
+  display: flex;
+  min-width: 0;
+  /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+          flex-direction: column;
+  -webkit-flex-direction: column;
+  -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  -webkit-box-align: baseline;
+  -webkit-align-items: baseline;
+      -ms-flex-align: baseline;
+          align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  -webkit-box-align: center;
+  -webkit-align-items: center;
+      -ms-flex-align: center;
+          align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  -webkit-box-align: end;
+  -webkit-align-items: flex-end;
+      -ms-flex-align: end;
+          align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  -webkit-box-align: start;
+  -webkit-align-items: flex-start;
+      -ms-flex-align: start;
+          align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  -webkit-box-align: stretch;
+  -webkit-align-items: stretch;
+      -ms-flex-align: stretch;
+          align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  -webkit-box-pack: center;
+  -webkit-justify-content: center;
+      -ms-flex-pack: center;
+          justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  -webkit-box-pack: start;
+  -webkit-justify-content: flex-start;
+      -ms-flex-pack: start;
+          justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd {
+  -webkit-box-pack: end;
+  -webkit-justify-content: flex-end;
+      -ms-flex-pack: end;
+          justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween {
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround {
+  -webkit-justify-content: space-around;
+      -ms-flex-pack: distribute;
+          justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+  box-shadow: 0 0 5px 5px rgba(200, 200, 200, 0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+.tobago-gridLayout {
+  width: 100%;
+  height: 100%;
+  /*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+  border-spacing: 0;
+  border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+  vertical-align: top;
+  padding: 0;
+  border-left: 5px solid transparent;
+  border-top: 5px solid transparent;
+  height: 100%;
+  /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+  border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+  border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+.tobago-header {
+  margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+  margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+.tobago-image-markup-disabled {
+  -webkit-filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+          filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal;
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: -webkit-gradient(linear, left top, left bottom, from(#f5f5f5), to(#e8e8e8));
+  background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: -o-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500;
+  /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+.tobago-selectManyShuttle {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 0 0%;
+      -ms-flex: 1 0 0%;
+          flex: 1 0 0%;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  -webkit-flex-shrink: 0;
+      -ms-flex-negative: 0;
+          flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-orient: vertical;
+  -webkit-box-direction: normal;
+  -webkit-flex-direction: column;
+      -ms-flex-direction: column;
+          flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important;
+  /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+
+.tobago-sheet-paging-markup-right {
+  float: right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  -webkit-box-flex: 1;
+  -webkit-flex: 1 1 auto;
+      -ms-flex: 1 1 auto;
+          flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important;
+  /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+          box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+          box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+  padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+  background-color: #0097CF;
+  color: #FFFFFF;
+  cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+.tobago-tab {
+  display: -webkit-box;
+  display: -webkit-flex;
+  display: -ms-flexbox;
+  display: flex;
+  -webkit-box-pack: justify;
+  -webkit-justify-content: space-between;
+      -ms-flex-pack: justify;
+          justify-content: space-between;
+  -webkit-align-content: center;
+      -ms-flex-line-pack: center;
+          align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}
+
+.form-horizontal .control-label {
+  margin-top: 10px;
+  margin-bottom: 5px;
+}
+
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content: "*";
+  color: red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
+
+/*! normalize.css v4.2.0 | MIT License | github.com/necolas/normalize.css */
+html {
+  font-family: sans-serif;
+  line-height: 1.15;
+  -ms-text-size-adjust: 100%;
+  -webkit-text-size-adjust: 100%;
+}
+
+body {
+  margin: 0;
+}
+
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+main,
+menu,
+nav,
+section,
+summary {
+  display: block;
+}
+
+audio,
+canvas,
+progress,
+video {
+  display: inline-block;
+}
+
+audio:not([controls]) {
+  display: none;
+  height: 0;
+}
+
+progress {
+  vertical-align: baseline;
+}
+
+template,
+[hidden] {
+  display: none;
+}
+
+a {
+  background-color: transparent;
+  -webkit-text-decoration-skip: objects;
+}
+
+a:active,
+a:hover {
+  outline-width: 0;
+}
+
+abbr[title] {
+  border-bottom: none;
+  text-decoration: underline;
+  text-decoration: underline dotted;
+}
+
+b,
+strong {
+  font-weight: inherit;
+}
+
+b,
+strong {
+  font-weight: bolder;
+}
+
+dfn {
+  font-style: italic;
+}
+
+h1 {
+  font-size: 2em;
+  margin: 0.67em 0;
+}
+
+mark {
+  background-color: #ff0;
+  color: #000;
+}
+
+small {
+  font-size: 80%;
+}
+
+sub,
+sup {
+  font-size: 75%;
+  line-height: 0;
+  position: relative;
+  vertical-align: baseline;
+}
+
+sub {
+  bottom: -0.25em;
+}
+
+sup {
+  top: -0.5em;
+}
+
+img {
+  border-style: none;
+}
+
+svg:not(:root) {
+  overflow: hidden;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: monospace, monospace;
+  font-size: 1em;
+}
+
+figure {
+  margin: 1em 40px;
+}
+
+hr {
+  -webkit-box-sizing: content-box;
+          box-sizing: content-box;
+  height: 0;
+  overflow: visible;
+}
+
+button,
+input,
+optgroup,
+select,
+textarea {
+  font: inherit;
+  margin: 0;
+}
+
+optgroup {
+  font-weight: bold;
+}
+
+button,
+input {
+  overflow: visible;
+}
+
+button,
+select {
+  text-transform: none;
+}
+
+button,
+html [type="button"],
+[type="reset"],
+[type="submit"] {
+  -webkit-appearance: button;
+}
+
+button::-moz-focus-inner,
+[type="button"]::-moz-focus-inner,
+[type="reset"]::-moz-focus-inner,
+[type="submit"]::-moz-focus-inner {
+  border-style: none;
+  padding: 0;
+}
+
+button:-moz-focusring,
+[type="button"]:-moz-focusring,
+[type="reset"]:-moz-focusring,
+[type="submit"]:-moz-focusring {
+  outline: 1px dotted ButtonText;
+}
+
+fieldset {
+  border: 1px solid #c0c0c0;
+  margin: 0 2px;
+  padding: 0.35em 0.625em 0.75em;
+}
+
+legend {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  color: inherit;
+  display: table;
+  max-width: 100%;
+  padding: 0;
+  white-space: normal;
+}
+
+textarea {
+  overflow: auto;
+}
+
+[type="checkbox"],
+[type="radio"] {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+  padding: 0;
+}
+
+[type="number"]::-webkit-inner-spin-button,
+[type="number"]::-webkit-outer-spin-button {
+  height: auto;
+}
+
+[type="search"] {
+  -webkit-appearance: textfield;
+  outline-offset: -2px;
+}
+
+[type="search"]::-webkit-search-cancel-button,
+[type="search"]::-webkit-search-decoration {
+  -webkit-appearance: none;
+}
+
+::-webkit-input-placeholder {
+  color: inherit;
+  opacity: 0.54;
+}
+
+::-webkit-file-upload-button {
+  -webkit-appearance: button;
+  font: inherit;
+}
+
+@media print {
+  *,
+  *::before,
+  *::after,
+  *::first-letter,
+  p::first-line,
+  div::first-line,
+  blockquote::first-line,
+  li::first-line {
+    text-shadow: none !important;
+    -webkit-box-shadow: none !important;
+            box-shadow: none !important;
+  }
+  a,
+  a:visited {
+    text-decoration: underline;
+  }
+  abbr[title]::after {
+    content: " (" attr(title) ")";
+  }
+  pre {
+    white-space: pre-wrap !important;
+  }
+  pre,
+  blockquote {
+    border: 1px solid #999;
+    page-break-inside: avoid;
+  }
+  thead {
+    display: table-header-group;
+  }
+  tr,
+  img {
+    page-break-inside: avoid;
+  }
+  p,
+  h2,
+  h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2,
+  h3 {
+    page-break-after: avoid;
+  }
+  .navbar {
+    display: none;
+  }
+  .btn > .caret,
+  .dropup > .btn > .caret {
+    border-top-color: #000 !important;
+  }
+  .tag {
+    border: 1px solid #000;
+  }
+  .table {
+    border-collapse: collapse !important;
+  }
+  .table td,
+  .table th {
+    background-color: #fff !important;
+  }
+  .table-bordered th,
+  .table-bordered td {
+    border: 1px solid #ddd !important;
+  }
+}
+
+html {
+  -webkit-box-sizing: border-box;
+          box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+  -webkit-box-sizing: inherit;
+          box-sizing: inherit;
+}
+
+@-ms-viewport {
+  width: device-width;
+}
+
+html {
+  font-size: 16px;
+  -ms-overflow-style: scrollbar;
+  -webkit-tap-highlight-color: transparent;
+}
+
+body {
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-size: 1rem;
+  line-height: 1.5;
+  color: #373a3c;
+  background-color: #fff;
+}
+
+[tabindex="-1"]:focus {
+  outline: none !important;
+}
+
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 0;
+  margin-bottom: .5rem;
+}
+
+p {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+abbr[title],
+abbr[data-original-title] {
+  cursor: help;
+  border-bottom: 1px dotted #818a91;
+}
+
+address {
+  margin-bottom: 1rem;
+  font-style: normal;
+  line-height: inherit;
+}
+
+ol,
+ul,
+dl {
+  margin-top: 0;
+  margin-bottom: 1rem;
+}
+
+ol ol,
+ul ul,
+ol ul,
+ul ol {
+  margin-bottom: 0;
+}
+
+dt {
+  font-weight: bold;
+}
+
+dd {
+  margin-bottom: .5rem;
+  margin-left: 0;
+}
+
+blockquote {
+  margin: 0 0 1rem;
+}
+
+a {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+a:focus, a:hover {
+  color: #014c8c;
+  text-decoration: underline;
+}
+
+a:focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+a:not([href]):not([tabindex]) {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus, a:not([href]):not([tabindex]):hover {
+  color: inherit;
+  text-decoration: none;
+}
+
+a:not([href]):not([tabindex]):focus {
+  outline: none;
+}
+
+pre {
+  margin-top: 0;
+  margin-bottom: 1rem;
+  overflow: auto;
+}
+
+figure {
+  margin: 0 0 1rem;
+}
+
+img {
+  vertical-align: middle;
+}
+
+[role="button"] {
+  cursor: pointer;
+}
+
+a,
+area,
+button,
+[role="button"],
+input,
+label,
+select,
+summary,
+textarea {
+  -ms-touch-action: manipulation;
+      touch-action: manipulation;
+}
+
+table {
+  border-collapse: collapse;
+  background-color: transparent;
+}
+
+caption {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  color: #818a91;
+  text-align: left;
+  caption-side: bottom;
+}
+
+th {
+  text-align: left;
+}
+
+label {
+  display: inline-block;
+  margin-bottom: .5rem;
+}
+
+button:focus {
+  outline: 1px dotted;
+  outline: 5px auto -webkit-focus-ring-color;
+}
+
+input,
+button,
+select,
+textarea {
+  line-height: inherit;
+}
+
+input[type="radio"]:disabled,
+input[type="checkbox"]:disabled {
+  cursor: not-allowed;
+}
+
+input[type="date"],
+input[type="time"],
+input[type="datetime-local"],
+input[type="month"] {
+  -webkit-appearance: listbox;
+}
+
+textarea {
+  resize: vertical;
+}
+
+fieldset {
+  min-width: 0;
+  padding: 0;
+  margin: 0;
+  border: 0;
+}
+
+legend {
+  display: block;
+  width: 100%;
+  padding: 0;
+  margin-bottom: .5rem;
+  font-size: 1.5rem;
+  line-height: inherit;
+}
+
+input[type="search"] {
+  -webkit-appearance: none;
+}
+
+output {
+  display: inline-block;
+}
+
+[hidden] {
+  display: none !important;
+}
+
+h1, h2, h3, h4, h5, h6,
+.h1, .h2, .h3, .h4, .h5, .h6 {
+  margin-bottom: 0.5rem;
+  font-family: inherit;
+  font-weight: 500;
+  line-height: 1.1;
+  color: inherit;
+}
+
+h1, .h1 {
+  font-size: 2.5rem;
+}
+
+h2, .h2 {
+  font-size: 2rem;
+}
+
+h3, .h3 {
+  font-size: 1.75rem;
+}
+
+h4, .h4 {
+  font-size: 1.5rem;
+}
+
+h5, .h5 {
+  font-size: 1.25rem;
+}
+
+h6, .h6 {
+  font-size: 1rem;
+}
+
+.lead {
+  font-size: 1.25rem;
+  font-weight: 300;
+}
+
+.display-1 {
+  font-size: 6rem;
+  font-weight: 300;
+}
+
+.display-2 {
+  font-size: 5.5rem;
+  font-weight: 300;
+}
+
+.display-3 {
+  font-size: 4.5rem;
+  font-weight: 300;
+}
+
+.display-4 {
+  font-size: 3.5rem;
+  font-weight: 300;
+}
+
+hr {
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border: 0;
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+small,
+.small {
+  font-size: 80%;
+  font-weight: normal;
+}
+
+mark,
+.mark {
+  padding: 0.2em;
+  background-color: #fcf8e3;
+}
+
+.list-unstyled {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-inline-item {
+  display: inline-block;
+}
+
+.list-inline-item:not(:last-child) {
+  margin-right: 5px;
+}
+
+.initialism {
+  font-size: 90%;
+  text-transform: uppercase;
+}
+
+.blockquote {
+  padding: 0.5rem 1rem;
+  margin-bottom: 1rem;
+  font-size: 1.25rem;
+  border-left: 0.25rem solid #eceeef;
+}
+
+.blockquote-footer {
+  display: block;
+  font-size: 80%;
+  color: #818a91;
+}
+
+.blockquote-footer::before {
+  content: "\2014 \00A0";
+}
+
+.blockquote-reverse {
+  padding-right: 1rem;
+  padding-left: 0;
+  text-align: right;
+  border-right: 0.25rem solid #eceeef;
+  border-left: 0;
+}
+
+.blockquote-reverse .blockquote-footer::before {
+  content: "";
+}
+
+.blockquote-reverse .blockquote-footer::after {
+  content: "\00A0 \2014";
+}
+
+dl.row > dd + dt {
+  clear: left;
+}
+
+.img-fluid, .carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  max-width: 100%;
+  height: auto;
+}
+
+.img-thumbnail {
+  padding: 0.25rem;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  -webkit-transition: all .2s ease-in-out;
+  -o-transition: all .2s ease-in-out;
+  transition: all .2s ease-in-out;
+  max-width: 100%;
+  height: auto;
+}
+
+.figure {
+  display: inline-block;
+}
+
+.figure-img {
+  margin-bottom: 0.5rem;
+  line-height: 1;
+}
+
+.figure-caption {
+  font-size: 90%;
+  color: #818a91;
+}
+
+code,
+kbd,
+pre,
+samp {
+  font-family: Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
+}
+
+code {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #bd4147;
+  background-color: #f7f7f9;
+  border-radius: 0.25rem;
+}
+
+kbd {
+  padding: 0.2rem 0.4rem;
+  font-size: 90%;
+  color: #fff;
+  background-color: #333;
+  border-radius: 0.2rem;
+}
+
+kbd kbd {
+  padding: 0;
+  font-size: 100%;
+  font-weight: bold;
+}
+
+pre {
+  display: block;
+  margin-top: 0;
+  margin-bottom: 1rem;
+  font-size: 90%;
+  color: #373a3c;
+}
+
+pre code {
+  padding: 0;
+  font-size: inherit;
+  color: inherit;
+  background-color: transparent;
+  border-radius: 0;
+}
+
+.pre-scrollable {
+  max-height: 340px;
+  overflow-y: scroll;
+}
+
+.container {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .container {
+    width: 540px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 768px) {
+  .container {
+    width: 720px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 992px) {
+  .container {
+    width: 960px;
+    max-width: 100%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .container {
+    width: 1140px;
+    max-width: 100%;
+  }
+}
+
+.container-fluid {
+  margin-left: auto;
+  margin-right: auto;
+  padding-left: 15px;
+  padding-right: 15px;
+}
+
+.container-fluid::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.row {
+  margin-right: -15px;
+  margin-left: -15px;
+}
+
+.row::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .row {
+    margin-right: -15px;
+    margin-left: -15px;
+  }
+}
+
+.col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg [...]
+  position: relative;
+  min-height: 1px;
+  padding-right: 15px;
+  padding-left: 15px;
+}
+
+@media (min-width: 576px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xs, .col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12, .col-sm, .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12, .col-md, .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12, .col-lg, .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col- [...]
+    padding-right: 15px;
+    padding-left: 15px;
+  }
+}
+
+.col-xs-1 {
+  float: left;
+  width: 8.333333%;
+}
+
+.col-xs-2 {
+  float: left;
+  width: 16.666667%;
+}
+
+.col-xs-3 {
+  float: left;
+  width: 25%;
+}
+
+.col-xs-4 {
+  float: left;
+  width: 33.333333%;
+}
+
+.col-xs-5 {
+  float: left;
+  width: 41.666667%;
+}
+
+.col-xs-6 {
+  float: left;
+  width: 50%;
+}
+
+.col-xs-7 {
+  float: left;
+  width: 58.333333%;
+}
+
+.col-xs-8 {
+  float: left;
+  width: 66.666667%;
+}
+
+.col-xs-9 {
+  float: left;
+  width: 75%;
+}
+
+.col-xs-10 {
+  float: left;
+  width: 83.333333%;
+}
+
+.col-xs-11 {
+  float: left;
+  width: 91.666667%;
+}
+
+.col-xs-12 {
+  float: left;
+  width: 100%;
+}
+
+.pull-xs-0 {
+  right: auto;
+}
+
+.pull-xs-1 {
+  right: 8.333333%;
+}
+
+.pull-xs-2 {
+  right: 16.666667%;
+}
+
+.pull-xs-3 {
+  right: 25%;
+}
+
+.pull-xs-4 {
+  right: 33.333333%;
+}
+
+.pull-xs-5 {
+  right: 41.666667%;
+}
+
+.pull-xs-6 {
+  right: 50%;
+}
+
+.pull-xs-7 {
+  right: 58.333333%;
+}
+
+.pull-xs-8 {
+  right: 66.666667%;
+}
+
+.pull-xs-9 {
+  right: 75%;
+}
+
+.pull-xs-10 {
+  right: 83.333333%;
+}
+
+.pull-xs-11 {
+  right: 91.666667%;
+}
+
+.pull-xs-12 {
+  right: 100%;
+}
+
+.push-xs-0 {
+  left: auto;
+}
+
+.push-xs-1 {
+  left: 8.333333%;
+}
+
+.push-xs-2 {
+  left: 16.666667%;
+}
+
+.push-xs-3 {
+  left: 25%;
+}
+
+.push-xs-4 {
+  left: 33.333333%;
+}
+
+.push-xs-5 {
+  left: 41.666667%;
+}
+
+.push-xs-6 {
+  left: 50%;
+}
+
+.push-xs-7 {
+  left: 58.333333%;
+}
+
+.push-xs-8 {
+  left: 66.666667%;
+}
+
+.push-xs-9 {
+  left: 75%;
+}
+
+.push-xs-10 {
+  left: 83.333333%;
+}
+
+.push-xs-11 {
+  left: 91.666667%;
+}
+
+.push-xs-12 {
+  left: 100%;
+}
+
+.offset-xs-1 {
+  margin-left: 8.333333%;
+}
+
+.offset-xs-2 {
+  margin-left: 16.666667%;
+}
+
+.offset-xs-3 {
+  margin-left: 25%;
+}
+
+.offset-xs-4 {
+  margin-left: 33.333333%;
+}
+
+.offset-xs-5 {
+  margin-left: 41.666667%;
+}
+
+.offset-xs-6 {
+  margin-left: 50%;
+}
+
+.offset-xs-7 {
+  margin-left: 58.333333%;
+}
+
+.offset-xs-8 {
+  margin-left: 66.666667%;
+}
+
+.offset-xs-9 {
+  margin-left: 75%;
+}
+
+.offset-xs-10 {
+  margin-left: 83.333333%;
+}
+
+.offset-xs-11 {
+  margin-left: 91.666667%;
+}
+
+@media (min-width: 576px) {
+  .col-sm-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-sm-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-sm-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-sm-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-sm-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-sm-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-sm-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-sm-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-sm-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-sm-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-sm-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-sm-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-sm-0 {
+    right: auto;
+  }
+  .pull-sm-1 {
+    right: 8.333333%;
+  }
+  .pull-sm-2 {
+    right: 16.666667%;
+  }
+  .pull-sm-3 {
+    right: 25%;
+  }
+  .pull-sm-4 {
+    right: 33.333333%;
+  }
+  .pull-sm-5 {
+    right: 41.666667%;
+  }
+  .pull-sm-6 {
+    right: 50%;
+  }
+  .pull-sm-7 {
+    right: 58.333333%;
+  }
+  .pull-sm-8 {
+    right: 66.666667%;
+  }
+  .pull-sm-9 {
+    right: 75%;
+  }
+  .pull-sm-10 {
+    right: 83.333333%;
+  }
+  .pull-sm-11 {
+    right: 91.666667%;
+  }
+  .pull-sm-12 {
+    right: 100%;
+  }
+  .push-sm-0 {
+    left: auto;
+  }
+  .push-sm-1 {
+    left: 8.333333%;
+  }
+  .push-sm-2 {
+    left: 16.666667%;
+  }
+  .push-sm-3 {
+    left: 25%;
+  }
+  .push-sm-4 {
+    left: 33.333333%;
+  }
+  .push-sm-5 {
+    left: 41.666667%;
+  }
+  .push-sm-6 {
+    left: 50%;
+  }
+  .push-sm-7 {
+    left: 58.333333%;
+  }
+  .push-sm-8 {
+    left: 66.666667%;
+  }
+  .push-sm-9 {
+    left: 75%;
+  }
+  .push-sm-10 {
+    left: 83.333333%;
+  }
+  .push-sm-11 {
+    left: 91.666667%;
+  }
+  .push-sm-12 {
+    left: 100%;
+  }
+  .offset-sm-0 {
+    margin-left: 0%;
+  }
+  .offset-sm-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-sm-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-sm-3 {
+    margin-left: 25%;
+  }
+  .offset-sm-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-sm-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-sm-6 {
+    margin-left: 50%;
+  }
+  .offset-sm-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-sm-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-sm-9 {
+    margin-left: 75%;
+  }
+  .offset-sm-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-sm-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 768px) {
+  .col-md-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-md-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-md-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-md-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-md-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-md-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-md-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-md-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-md-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-md-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-md-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-md-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-md-0 {
+    right: auto;
+  }
+  .pull-md-1 {
+    right: 8.333333%;
+  }
+  .pull-md-2 {
+    right: 16.666667%;
+  }
+  .pull-md-3 {
+    right: 25%;
+  }
+  .pull-md-4 {
+    right: 33.333333%;
+  }
+  .pull-md-5 {
+    right: 41.666667%;
+  }
+  .pull-md-6 {
+    right: 50%;
+  }
+  .pull-md-7 {
+    right: 58.333333%;
+  }
+  .pull-md-8 {
+    right: 66.666667%;
+  }
+  .pull-md-9 {
+    right: 75%;
+  }
+  .pull-md-10 {
+    right: 83.333333%;
+  }
+  .pull-md-11 {
+    right: 91.666667%;
+  }
+  .pull-md-12 {
+    right: 100%;
+  }
+  .push-md-0 {
+    left: auto;
+  }
+  .push-md-1 {
+    left: 8.333333%;
+  }
+  .push-md-2 {
+    left: 16.666667%;
+  }
+  .push-md-3 {
+    left: 25%;
+  }
+  .push-md-4 {
+    left: 33.333333%;
+  }
+  .push-md-5 {
+    left: 41.666667%;
+  }
+  .push-md-6 {
+    left: 50%;
+  }
+  .push-md-7 {
+    left: 58.333333%;
+  }
+  .push-md-8 {
+    left: 66.666667%;
+  }
+  .push-md-9 {
+    left: 75%;
+  }
+  .push-md-10 {
+    left: 83.333333%;
+  }
+  .push-md-11 {
+    left: 91.666667%;
+  }
+  .push-md-12 {
+    left: 100%;
+  }
+  .offset-md-0 {
+    margin-left: 0%;
+  }
+  .offset-md-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-md-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-md-3 {
+    margin-left: 25%;
+  }
+  .offset-md-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-md-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-md-6 {
+    margin-left: 50%;
+  }
+  .offset-md-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-md-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-md-9 {
+    margin-left: 75%;
+  }
+  .offset-md-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-md-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 992px) {
+  .col-lg-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-lg-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-lg-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-lg-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-lg-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-lg-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-lg-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-lg-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-lg-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-lg-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-lg-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-lg-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-lg-0 {
+    right: auto;
+  }
+  .pull-lg-1 {
+    right: 8.333333%;
+  }
+  .pull-lg-2 {
+    right: 16.666667%;
+  }
+  .pull-lg-3 {
+    right: 25%;
+  }
+  .pull-lg-4 {
+    right: 33.333333%;
+  }
+  .pull-lg-5 {
+    right: 41.666667%;
+  }
+  .pull-lg-6 {
+    right: 50%;
+  }
+  .pull-lg-7 {
+    right: 58.333333%;
+  }
+  .pull-lg-8 {
+    right: 66.666667%;
+  }
+  .pull-lg-9 {
+    right: 75%;
+  }
+  .pull-lg-10 {
+    right: 83.333333%;
+  }
+  .pull-lg-11 {
+    right: 91.666667%;
+  }
+  .pull-lg-12 {
+    right: 100%;
+  }
+  .push-lg-0 {
+    left: auto;
+  }
+  .push-lg-1 {
+    left: 8.333333%;
+  }
+  .push-lg-2 {
+    left: 16.666667%;
+  }
+  .push-lg-3 {
+    left: 25%;
+  }
+  .push-lg-4 {
+    left: 33.333333%;
+  }
+  .push-lg-5 {
+    left: 41.666667%;
+  }
+  .push-lg-6 {
+    left: 50%;
+  }
+  .push-lg-7 {
+    left: 58.333333%;
+  }
+  .push-lg-8 {
+    left: 66.666667%;
+  }
+  .push-lg-9 {
+    left: 75%;
+  }
+  .push-lg-10 {
+    left: 83.333333%;
+  }
+  .push-lg-11 {
+    left: 91.666667%;
+  }
+  .push-lg-12 {
+    left: 100%;
+  }
+  .offset-lg-0 {
+    margin-left: 0%;
+  }
+  .offset-lg-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-lg-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-lg-3 {
+    margin-left: 25%;
+  }
+  .offset-lg-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-lg-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-lg-6 {
+    margin-left: 50%;
+  }
+  .offset-lg-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-lg-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-lg-9 {
+    margin-left: 75%;
+  }
+  .offset-lg-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-lg-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+@media (min-width: 1200px) {
+  .col-xl-1 {
+    float: left;
+    width: 8.333333%;
+  }
+  .col-xl-2 {
+    float: left;
+    width: 16.666667%;
+  }
+  .col-xl-3 {
+    float: left;
+    width: 25%;
+  }
+  .col-xl-4 {
+    float: left;
+    width: 33.333333%;
+  }
+  .col-xl-5 {
+    float: left;
+    width: 41.666667%;
+  }
+  .col-xl-6 {
+    float: left;
+    width: 50%;
+  }
+  .col-xl-7 {
+    float: left;
+    width: 58.333333%;
+  }
+  .col-xl-8 {
+    float: left;
+    width: 66.666667%;
+  }
+  .col-xl-9 {
+    float: left;
+    width: 75%;
+  }
+  .col-xl-10 {
+    float: left;
+    width: 83.333333%;
+  }
+  .col-xl-11 {
+    float: left;
+    width: 91.666667%;
+  }
+  .col-xl-12 {
+    float: left;
+    width: 100%;
+  }
+  .pull-xl-0 {
+    right: auto;
+  }
+  .pull-xl-1 {
+    right: 8.333333%;
+  }
+  .pull-xl-2 {
+    right: 16.666667%;
+  }
+  .pull-xl-3 {
+    right: 25%;
+  }
+  .pull-xl-4 {
+    right: 33.333333%;
+  }
+  .pull-xl-5 {
+    right: 41.666667%;
+  }
+  .pull-xl-6 {
+    right: 50%;
+  }
+  .pull-xl-7 {
+    right: 58.333333%;
+  }
+  .pull-xl-8 {
+    right: 66.666667%;
+  }
+  .pull-xl-9 {
+    right: 75%;
+  }
+  .pull-xl-10 {
+    right: 83.333333%;
+  }
+  .pull-xl-11 {
+    right: 91.666667%;
+  }
+  .pull-xl-12 {
+    right: 100%;
+  }
+  .push-xl-0 {
+    left: auto;
+  }
+  .push-xl-1 {
+    left: 8.333333%;
+  }
+  .push-xl-2 {
+    left: 16.666667%;
+  }
+  .push-xl-3 {
+    left: 25%;
+  }
+  .push-xl-4 {
+    left: 33.333333%;
+  }
+  .push-xl-5 {
+    left: 41.666667%;
+  }
+  .push-xl-6 {
+    left: 50%;
+  }
+  .push-xl-7 {
+    left: 58.333333%;
+  }
+  .push-xl-8 {
+    left: 66.666667%;
+  }
+  .push-xl-9 {
+    left: 75%;
+  }
+  .push-xl-10 {
+    left: 83.333333%;
+  }
+  .push-xl-11 {
+    left: 91.666667%;
+  }
+  .push-xl-12 {
+    left: 100%;
+  }
+  .offset-xl-0 {
+    margin-left: 0%;
+  }
+  .offset-xl-1 {
+    margin-left: 8.333333%;
+  }
+  .offset-xl-2 {
+    margin-left: 16.666667%;
+  }
+  .offset-xl-3 {
+    margin-left: 25%;
+  }
+  .offset-xl-4 {
+    margin-left: 33.333333%;
+  }
+  .offset-xl-5 {
+    margin-left: 41.666667%;
+  }
+  .offset-xl-6 {
+    margin-left: 50%;
+  }
+  .offset-xl-7 {
+    margin-left: 58.333333%;
+  }
+  .offset-xl-8 {
+    margin-left: 66.666667%;
+  }
+  .offset-xl-9 {
+    margin-left: 75%;
+  }
+  .offset-xl-10 {
+    margin-left: 83.333333%;
+  }
+  .offset-xl-11 {
+    margin-left: 91.666667%;
+  }
+}
+
+.table {
+  width: 100%;
+  max-width: 100%;
+  margin-bottom: 1rem;
+}
+
+.table th,
+.table td {
+  padding: 0.75rem;
+  vertical-align: top;
+  border-top: 1px solid #eceeef;
+}
+
+.table thead th {
+  vertical-align: bottom;
+  border-bottom: 2px solid #eceeef;
+}
+
+.table tbody + tbody {
+  border-top: 2px solid #eceeef;
+}
+
+.table .table {
+  background-color: #fff;
+}
+
+.table-sm th,
+.table-sm td {
+  padding: 0.3rem;
+}
+
+.table-bordered {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered th,
+.table-bordered td {
+  border: 1px solid #eceeef;
+}
+
+.table-bordered thead th,
+.table-bordered thead td {
+  border-bottom-width: 2px;
+}
+
+.table-striped tbody tr:nth-of-type(odd) {
+  background-color: rgba(0, 0, 0, 0.05);
+}
+
+.table-hover tbody tr:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-active,
+.table-active > th,
+.table-active > td {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-hover .table-active:hover > td,
+.table-hover .table-active:hover > th {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.table-success,
+.table-success > th,
+.table-success > td {
+  background-color: #dff0d8;
+}
+
+.table-hover .table-success:hover {
+  background-color: #d0e9c6;
+}
+
+.table-hover .table-success:hover > td,
+.table-hover .table-success:hover > th {
+  background-color: #d0e9c6;
+}
+
+.table-info,
+.table-info > th,
+.table-info > td {
+  background-color: #d9edf7;
+}
+
+.table-hover .table-info:hover {
+  background-color: #c4e3f3;
+}
+
+.table-hover .table-info:hover > td,
+.table-hover .table-info:hover > th {
+  background-color: #c4e3f3;
+}
+
+.table-warning,
+.table-warning > th,
+.table-warning > td {
+  background-color: #fcf8e3;
+}
+
+.table-hover .table-warning:hover {
+  background-color: #faf2cc;
+}
+
+.table-hover .table-warning:hover > td,
+.table-hover .table-warning:hover > th {
+  background-color: #faf2cc;
+}
+
+.table-danger,
+.table-danger > th,
+.table-danger > td {
+  background-color: #f2dede;
+}
+
+.table-hover .table-danger:hover {
+  background-color: #ebcccc;
+}
+
+.table-hover .table-danger:hover > td,
+.table-hover .table-danger:hover > th {
+  background-color: #ebcccc;
+}
+
+.thead-inverse th {
+  color: #fff;
+  background-color: #373a3c;
+}
+
+.thead-default th {
+  color: #55595c;
+  background-color: #eceeef;
+}
+
+.table-inverse {
+  color: #eceeef;
+  background-color: #373a3c;
+}
+
+.table-inverse th,
+.table-inverse td,
+.table-inverse thead th {
+  border-color: #55595c;
+}
+
+.table-inverse.table-bordered {
+  border: 0;
+}
+
+.table-responsive {
+  display: block;
+  width: 100%;
+  min-height: 0%;
+  overflow-x: auto;
+}
+
+.table-reflow thead {
+  float: left;
+}
+
+.table-reflow tbody {
+  display: block;
+  white-space: nowrap;
+}
+
+.table-reflow th,
+.table-reflow td {
+  border-top: 1px solid #eceeef;
+  border-left: 1px solid #eceeef;
+}
+
+.table-reflow th:last-child,
+.table-reflow td:last-child {
+  border-right: 1px solid #eceeef;
+}
+
+.table-reflow thead:last-child tr:last-child th,
+.table-reflow thead:last-child tr:last-child td,
+.table-reflow tbody:last-child tr:last-child th,
+.table-reflow tbody:last-child tr:last-child td,
+.table-reflow tfoot:last-child tr:last-child th,
+.table-reflow tfoot:last-child tr:last-child td {
+  border-bottom: 1px solid #eceeef;
+}
+
+.table-reflow tr {
+  float: left;
+}
+
+.table-reflow tr th,
+.table-reflow tr td {
+  display: block !important;
+  border: 1px solid #eceeef;
+}
+
+.form-control {
+  display: block;
+  width: 100%;
+  padding: 0.5rem 0.75rem;
+  font-size: 1rem;
+  line-height: 1.25;
+  color: #55595c;
+  background-color: #fff;
+  background-image: none;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.form-control::-ms-expand {
+  background-color: transparent;
+  border: 0;
+}
+
+.form-control:focus {
+  color: #55595c;
+  background-color: #fff;
+  border-color: #66afe9;
+  outline: none;
+}
+
+.form-control::-webkit-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::-moz-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:-ms-input-placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control::placeholder {
+  color: #999;
+  opacity: 1;
+}
+
+.form-control:disabled, .form-control[readonly] {
+  background-color: #eceeef;
+  opacity: 1;
+}
+
+.form-control:disabled {
+  cursor: not-allowed;
+}
+
+select.form-control:not([size]):not([multiple]) {
+  height: calc(2.5rem - 2px);
+}
+
+select.form-control:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.form-control-file,
+.form-control-range {
+  display: block;
+}
+
+.col-form-label {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+}
+
+.col-form-label-lg {
+  padding-top: 0.75rem;
+  padding-bottom: 0.75rem;
+  font-size: 1.25rem;
+}
+
+.col-form-label-sm {
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  font-size: 0.875rem;
+}
+
+.col-form-legend {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+}
+
+.form-control-static {
+  padding-top: 0.5rem;
+  padding-bottom: 0.5rem;
+  line-height: 1.25;
+  border: solid transparent;
+  border-width: 1px 0;
+}
+
+.form-control-static.form-control-sm, .input-group-sm > .form-control-static.form-control,
+.input-group-sm > .form-control-static.input-group-addon,
+.input-group-sm > .input-group-btn > .form-control-static.btn, .form-control-static.form-control-lg, .input-group-lg > .form-control-static.form-control,
+.input-group-lg > .form-control-static.input-group-addon,
+.input-group-lg > .input-group-btn > .form-control-static.btn {
+  padding-right: 0;
+  padding-left: 0;
+}
+
+.form-control-sm, .input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+select.form-control-sm:not([size]):not([multiple]), .input-group-sm > select.form-control:not([size]):not([multiple]),
+.input-group-sm > select.input-group-addon:not([size]):not([multiple]),
+.input-group-sm > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 1.8125rem;
+}
+
+.form-control-lg, .input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+select.form-control-lg:not([size]):not([multiple]), .input-group-lg > select.form-control:not([size]):not([multiple]),
+.input-group-lg > select.input-group-addon:not([size]):not([multiple]),
+.input-group-lg > .input-group-btn > select.btn:not([size]):not([multiple]) {
+  height: 3.166667rem;
+}
+
+.form-group {
+  margin-bottom: 1rem;
+}
+
+.form-text {
+  display: block;
+  margin-top: 0.25rem;
+}
+
+.form-check {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+}
+
+.form-check + .form-check {
+  margin-top: -.25rem;
+}
+
+.form-check.disabled .form-check-label {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-check-label {
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  cursor: pointer;
+}
+
+.form-check-input {
+  position: absolute;
+  margin-top: .25rem;
+  margin-left: -1.25rem;
+}
+
+.form-check-input:only-child {
+  position: static;
+}
+
+.form-check-inline {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.25rem;
+  margin-bottom: 0;
+  vertical-align: middle;
+  cursor: pointer;
+}
+
+.form-check-inline + .form-check-inline {
+  margin-left: .75rem;
+}
+
+.form-check-inline.disabled {
+  color: #818a91;
+  cursor: not-allowed;
+}
+
+.form-control-feedback {
+  margin-top: 0.25rem;
+}
+
+.form-control-success,
+.form-control-warning,
+.form-control-danger {
+  padding-right: 2.25rem;
+  background-repeat: no-repeat;
+  background-position: center right 0.625rem;
+  -webkit-background-size: 1.25rem 1.25rem;
+          background-size: 1.25rem 1.25rem;
+}
+
+.has-success .form-control-feedback,
+.has-success .form-control-label,
+.has-success .form-check-label,
+.has-success .form-check-inline,
+.has-success .custom-control {
+  color: #5cb85c;
+}
+
+.has-success .form-control {
+  border-color: #5cb85c;
+}
+
+.has-success .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #a3d7a3;
+}
+
+.has-success .input-group-addon {
+  color: #5cb85c;
+  border-color: #5cb85c;
+  background-color: #eaf6ea;
+}
+
+.has-success .form-control-success {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#5cb85c' d='M2.3 6.73L.6 4.53c-.4-1.04.46-1.4 1.1-.8l1.1 1.4 3.4-3.8c.6-.63 1.6-.27 1.2.7l-4 4.6c-.43.5-.8.4-1.1.1z'/%3E%3C/svg%3E");
+}
+
+.has-warning .form-control-feedback,
+.has-warning .form-control-label,
+.has-warning .form-check-label,
+.has-warning .form-check-inline,
+.has-warning .custom-control {
+  color: #f0ad4e;
+}
+
+.has-warning .form-control {
+  border-color: #f0ad4e;
+}
+
+.has-warning .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #f8d9ac;
+}
+
+.has-warning .input-group-addon {
+  color: #f0ad4e;
+  border-color: #f0ad4e;
+  background-color: white;
+}
+
+.has-warning .form-control-warning {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#f0ad4e' d='M4.4 5.324h-.8v-2.46h.8zm0 1.42h-.8V5.89h.8zM3.76.63L.04 7.075c-.115.2.016.425.26.426h7.397c.242 0 .372-.226.258-.426C6.726 4.924 5.47 2.79 4.253.63c-.113-.174-.39-.174-.494 0z'/%3E%3C/svg%3E");
+}
+
+.has-danger .form-control-feedback,
+.has-danger .form-control-label,
+.has-danger .form-check-label,
+.has-danger .form-check-inline,
+.has-danger .custom-control {
+  color: #d9534f;
+}
+
+.has-danger .form-control {
+  border-color: #d9534f;
+}
+
+.has-danger .form-control:focus {
+  -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+          box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #eba5a3;
+}
+
+.has-danger .input-group-addon {
+  color: #d9534f;
+  border-color: #d9534f;
+  background-color: #fdf7f7;
+}
+
+.has-danger .form-control-danger {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='#d9534f' viewBox='-2 -2 7 7'%3E%3Cpath stroke='%23d9534f' d='M0 0l3 3m0-3L0 3'/%3E%3Ccircle r='.5'/%3E%3Ccircle cx='3' r='.5'/%3E%3Ccircle cy='3' r='.5'/%3E%3Ccircle cx='3' cy='3' r='.5'/%3E%3C/svg%3E");
+}
+
+@media (min-width: 576px) {
+  .form-inline .form-group {
+    display: inline-block;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-control {
+    display: inline-block;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .form-control-static {
+    display: inline-block;
+  }
+  .form-inline .input-group {
+    display: inline-table;
+    width: auto;
+    vertical-align: middle;
+  }
+  .form-inline .input-group .input-group-addon,
+  .form-inline .input-group .input-group-btn,
+  .form-inline .input-group .form-control {
+    width: auto;
+  }
+  .form-inline .input-group > .form-control {
+    width: 100%;
+  }
+  .form-inline .form-control-label {
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check {
+    display: inline-block;
+    margin-top: 0;
+    margin-bottom: 0;
+    vertical-align: middle;
+  }
+  .form-inline .form-check-label {
+    padding-left: 0;
+  }
+  .form-inline .form-check-input {
+    position: relative;
+    margin-left: 0;
+  }
+  .form-inline .has-feedback .form-control-feedback {
+    top: 0;
+  }
+}
+
+.btn {
+  display: inline-block;
+  font-weight: normal;
+  line-height: 1.25;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: middle;
+  cursor: pointer;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  border: 1px solid transparent;
+  padding: 0.5rem 1rem;
+  font-size: 1rem;
+  border-radius: 0.25rem;
+}
+
+.btn:focus, .btn.focus, .btn:active:focus, .btn:active.focus, .btn.active:focus, .btn.active.focus {
+  outline: 5px auto -webkit-focus-ring-color;
+  outline-offset: -2px;
+}
+
+.btn:focus, .btn:hover {
+  text-decoration: none;
+}
+
+.btn.focus {
+  text-decoration: none;
+}
+
+.btn:active, .btn.active {
+  background-image: none;
+  outline: 0;
+}
+
+.btn.disabled, .btn:disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+a.btn.disabled,
+fieldset[disabled] a.btn {
+  pointer-events: none;
+}
+
+.btn-primary {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary:hover {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:focus, .btn-primary.focus {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+}
+
+.btn-primary:active, .btn-primary.active,
+.open > .btn-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #025aa5;
+  border-color: #01549b;
+  background-image: none;
+}
+
+.btn-primary:active:hover, .btn-primary:active:focus, .btn-primary:active.focus, .btn-primary.active:hover, .btn-primary.active:focus, .btn-primary.active.focus,
+.open > .btn-primary.dropdown-toggle:hover,
+.open > .btn-primary.dropdown-toggle:focus,
+.open > .btn-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-primary.disabled:focus, .btn-primary.disabled.focus, .btn-primary:disabled:focus, .btn-primary:disabled.focus {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-primary.disabled:hover, .btn-primary:disabled:hover {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-secondary {
+  color: #373a3c;
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary:hover {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:focus, .btn-secondary.focus {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+}
+
+.btn-secondary:active, .btn-secondary.active,
+.open > .btn-secondary.dropdown-toggle {
+  color: #373a3c;
+  background-color: #e6e6e6;
+  border-color: #adadad;
+  background-image: none;
+}
+
+.btn-secondary:active:hover, .btn-secondary:active:focus, .btn-secondary:active.focus, .btn-secondary.active:hover, .btn-secondary.active:focus, .btn-secondary.active.focus,
+.open > .btn-secondary.dropdown-toggle:hover,
+.open > .btn-secondary.dropdown-toggle:focus,
+.open > .btn-secondary.dropdown-toggle.focus {
+  color: #373a3c;
+  background-color: #d4d4d4;
+  border-color: #8c8c8c;
+}
+
+.btn-secondary.disabled:focus, .btn-secondary.disabled.focus, .btn-secondary:disabled:focus, .btn-secondary:disabled.focus {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-secondary.disabled:hover, .btn-secondary:disabled:hover {
+  background-color: #fff;
+  border-color: #ccc;
+}
+
+.btn-info {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info:hover {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:focus, .btn-info.focus {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+}
+
+.btn-info:active, .btn-info.active,
+.open > .btn-info.dropdown-toggle {
+  color: #fff;
+  background-color: #31b0d5;
+  border-color: #2aabd2;
+  background-image: none;
+}
+
+.btn-info:active:hover, .btn-info:active:focus, .btn-info:active.focus, .btn-info.active:hover, .btn-info.active:focus, .btn-info.active.focus,
+.open > .btn-info.dropdown-toggle:hover,
+.open > .btn-info.dropdown-toggle:focus,
+.open > .btn-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-info.disabled:focus, .btn-info.disabled.focus, .btn-info:disabled:focus, .btn-info:disabled.focus {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-info.disabled:hover, .btn-info:disabled:hover {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-success {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success:hover {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:focus, .btn-success.focus {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+}
+
+.btn-success:active, .btn-success.active,
+.open > .btn-success.dropdown-toggle {
+  color: #fff;
+  background-color: #449d44;
+  border-color: #419641;
+  background-image: none;
+}
+
+.btn-success:active:hover, .btn-success:active:focus, .btn-success:active.focus, .btn-success.active:hover, .btn-success.active:focus, .btn-success.active.focus,
+.open > .btn-success.dropdown-toggle:hover,
+.open > .btn-success.dropdown-toggle:focus,
+.open > .btn-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-success.disabled:focus, .btn-success.disabled.focus, .btn-success:disabled:focus, .btn-success:disabled.focus {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-success.disabled:hover, .btn-success:disabled:hover {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-warning {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning:hover {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:focus, .btn-warning.focus {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+}
+
+.btn-warning:active, .btn-warning.active,
+.open > .btn-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #ec971f;
+  border-color: #eb9316;
+  background-image: none;
+}
+
+.btn-warning:active:hover, .btn-warning:active:focus, .btn-warning:active.focus, .btn-warning.active:hover, .btn-warning.active:focus, .btn-warning.active.focus,
+.open > .btn-warning.dropdown-toggle:hover,
+.open > .btn-warning.dropdown-toggle:focus,
+.open > .btn-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-warning.disabled:focus, .btn-warning.disabled.focus, .btn-warning:disabled:focus, .btn-warning:disabled.focus {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-warning.disabled:hover, .btn-warning:disabled:hover {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-danger {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger:hover {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:focus, .btn-danger.focus {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+}
+
+.btn-danger:active, .btn-danger.active,
+.open > .btn-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #c9302c;
+  border-color: #c12e2a;
+  background-image: none;
+}
+
+.btn-danger:active:hover, .btn-danger:active:focus, .btn-danger:active.focus, .btn-danger.active:hover, .btn-danger.active:focus, .btn-danger.active.focus,
+.open > .btn-danger.dropdown-toggle:hover,
+.open > .btn-danger.dropdown-toggle:focus,
+.open > .btn-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-danger.disabled:focus, .btn-danger.disabled.focus, .btn-danger:disabled:focus, .btn-danger:disabled.focus {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-danger.disabled:hover, .btn-danger:disabled:hover {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-primary {
+  color: #0275d8;
+  background-image: none;
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:hover {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:focus, .btn-outline-primary.focus {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active, .btn-outline-primary.active,
+.open > .btn-outline-primary.dropdown-toggle {
+  color: #fff;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.btn-outline-primary:active:hover, .btn-outline-primary:active:focus, .btn-outline-primary:active.focus, .btn-outline-primary.active:hover, .btn-outline-primary.active:focus, .btn-outline-primary.active.focus,
+.open > .btn-outline-primary.dropdown-toggle:hover,
+.open > .btn-outline-primary.dropdown-toggle:focus,
+.open > .btn-outline-primary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #014682;
+  border-color: #01315a;
+}
+
+.btn-outline-primary.disabled:focus, .btn-outline-primary.disabled.focus, .btn-outline-primary:disabled:focus, .btn-outline-primary:disabled.focus {
+  border-color: #43a7fd;
+}
+
+.btn-outline-primary.disabled:hover, .btn-outline-primary:disabled:hover {
+  border-color: #43a7fd;
+}
+
+.btn-outline-secondary {
+  color: #ccc;
+  background-image: none;
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:hover {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:focus, .btn-outline-secondary.focus {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active, .btn-outline-secondary.active,
+.open > .btn-outline-secondary.dropdown-toggle {
+  color: #fff;
+  background-color: #ccc;
+  border-color: #ccc;
+}
+
+.btn-outline-secondary:active:hover, .btn-outline-secondary:active:focus, .btn-outline-secondary:active.focus, .btn-outline-secondary.active:hover, .btn-outline-secondary.active:focus, .btn-outline-secondary.active.focus,
+.open > .btn-outline-secondary.dropdown-toggle:hover,
+.open > .btn-outline-secondary.dropdown-toggle:focus,
+.open > .btn-outline-secondary.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #a1a1a1;
+  border-color: #8c8c8c;
+}
+
+.btn-outline-secondary.disabled:focus, .btn-outline-secondary.disabled.focus, .btn-outline-secondary:disabled:focus, .btn-outline-secondary:disabled.focus {
+  border-color: white;
+}
+
+.btn-outline-secondary.disabled:hover, .btn-outline-secondary:disabled:hover {
+  border-color: white;
+}
+
+.btn-outline-info {
+  color: #5bc0de;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:hover {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:focus, .btn-outline-info.focus {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active, .btn-outline-info.active,
+.open > .btn-outline-info.dropdown-toggle {
+  color: #fff;
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.btn-outline-info:active:hover, .btn-outline-info:active:focus, .btn-outline-info:active.focus, .btn-outline-info.active:hover, .btn-outline-info.active:focus, .btn-outline-info.active.focus,
+.open > .btn-outline-info.dropdown-toggle:hover,
+.open > .btn-outline-info.dropdown-toggle:focus,
+.open > .btn-outline-info.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #269abc;
+  border-color: #1f7e9a;
+}
+
+.btn-outline-info.disabled:focus, .btn-outline-info.disabled.focus, .btn-outline-info:disabled:focus, .btn-outline-info:disabled.focus {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-info.disabled:hover, .btn-outline-info:disabled:hover {
+  border-color: #b0e1ef;
+}
+
+.btn-outline-success {
+  color: #5cb85c;
+  background-image: none;
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:hover {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:focus, .btn-outline-success.focus {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active, .btn-outline-success.active,
+.open > .btn-outline-success.dropdown-toggle {
+  color: #fff;
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.btn-outline-success:active:hover, .btn-outline-success:active:focus, .btn-outline-success:active.focus, .btn-outline-success.active:hover, .btn-outline-success.active:focus, .btn-outline-success.active.focus,
+.open > .btn-outline-success.dropdown-toggle:hover,
+.open > .btn-outline-success.dropdown-toggle:focus,
+.open > .btn-outline-success.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #398439;
+  border-color: #2d672d;
+}
+
+.btn-outline-success.disabled:focus, .btn-outline-success.disabled.focus, .btn-outline-success:disabled:focus, .btn-outline-success:disabled.focus {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-success.disabled:hover, .btn-outline-success:disabled:hover {
+  border-color: #a3d7a3;
+}
+
+.btn-outline-warning {
+  color: #f0ad4e;
+  background-image: none;
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:hover {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:focus, .btn-outline-warning.focus {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active, .btn-outline-warning.active,
+.open > .btn-outline-warning.dropdown-toggle {
+  color: #fff;
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.btn-outline-warning:active:hover, .btn-outline-warning:active:focus, .btn-outline-warning:active.focus, .btn-outline-warning.active:hover, .btn-outline-warning.active:focus, .btn-outline-warning.active.focus,
+.open > .btn-outline-warning.dropdown-toggle:hover,
+.open > .btn-outline-warning.dropdown-toggle:focus,
+.open > .btn-outline-warning.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #d58512;
+  border-color: #b06d0f;
+}
+
+.btn-outline-warning.disabled:focus, .btn-outline-warning.disabled.focus, .btn-outline-warning:disabled:focus, .btn-outline-warning:disabled.focus {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-warning.disabled:hover, .btn-outline-warning:disabled:hover {
+  border-color: #f8d9ac;
+}
+
+.btn-outline-danger {
+  color: #d9534f;
+  background-image: none;
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:hover {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:focus, .btn-outline-danger.focus {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active, .btn-outline-danger.active,
+.open > .btn-outline-danger.dropdown-toggle {
+  color: #fff;
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.btn-outline-danger:active:hover, .btn-outline-danger:active:focus, .btn-outline-danger:active.focus, .btn-outline-danger.active:hover, .btn-outline-danger.active:focus, .btn-outline-danger.active.focus,
+.open > .btn-outline-danger.dropdown-toggle:hover,
+.open > .btn-outline-danger.dropdown-toggle:focus,
+.open > .btn-outline-danger.dropdown-toggle.focus {
+  color: #fff;
+  background-color: #ac2925;
+  border-color: #8b211e;
+}
+
+.btn-outline-danger.disabled:focus, .btn-outline-danger.disabled.focus, .btn-outline-danger:disabled:focus, .btn-outline-danger:disabled.focus {
+  border-color: #eba5a3;
+}
+
+.btn-outline-danger.disabled:hover, .btn-outline-danger:disabled:hover {
+  border-color: #eba5a3;
+}
+
+.btn-link {
+  font-weight: normal;
+  color: #0275d8;
+  border-radius: 0;
+}
+
+.btn-link, .btn-link:active, .btn-link.active, .btn-link:disabled {
+  background-color: transparent;
+}
+
+.btn-link, .btn-link:focus, .btn-link:active {
+  border-color: transparent;
+}
+
+.btn-link:hover {
+  border-color: transparent;
+}
+
+.btn-link:focus, .btn-link:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+}
+
+.btn-link:disabled:focus, .btn-link:disabled:hover {
+  color: #818a91;
+  text-decoration: none;
+}
+
+.btn-lg, .btn-group-lg > .btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.btn-sm, .btn-group-sm > .btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.btn-block {
+  display: block;
+  width: 100%;
+}
+
+.btn-block + .btn-block {
+  margin-top: 0.5rem;
+}
+
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+  width: 100%;
+}
+
+.fade {
+  opacity: 0;
+  -webkit-transition: opacity .15s linear;
+  -o-transition: opacity .15s linear;
+  transition: opacity .15s linear;
+}
+
+.fade.in {
+  opacity: 1;
+}
+
+.collapse {
+  display: none;
+}
+
+.collapse.in {
+  display: block;
+}
+
+tr.collapse.in {
+  display: table-row;
+}
+
+tbody.collapse.in {
+  display: table-row-group;
+}
+
+.collapsing {
+  position: relative;
+  height: 0;
+  overflow: hidden;
+  -webkit-transition-timing-function: ease;
+       -o-transition-timing-function: ease;
+          transition-timing-function: ease;
+  -webkit-transition-duration: .35s;
+       -o-transition-duration: .35s;
+          transition-duration: .35s;
+  -webkit-transition-property: height;
+  -o-transition-property: height;
+  transition-property: height;
+}
+
+.dropup,
+.dropdown {
+  position: relative;
+}
+
+.dropdown-toggle::after {
+  display: inline-block;
+  width: 0;
+  height: 0;
+  margin-left: 0.3em;
+  vertical-align: middle;
+  content: "";
+  border-top: 0.3em solid;
+  border-right: 0.3em solid transparent;
+  border-left: 0.3em solid transparent;
+}
+
+.dropdown-toggle:focus {
+  outline: 0;
+}
+
+.dropup .dropdown-toggle::after {
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropdown-menu {
+  position: absolute;
+  top: 100%;
+  left: 0;
+  z-index: 1000;
+  display: none;
+  float: left;
+  min-width: 10rem;
+  padding: 0.5rem 0;
+  margin: 0.125rem 0 0;
+  font-size: 1rem;
+  color: #373a3c;
+  text-align: left;
+  list-style: none;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.dropdown-divider {
+  height: 1px;
+  margin: 0.5rem 0;
+  overflow: hidden;
+  background-color: #e5e5e5;
+}
+
+.dropdown-item {
+  display: block;
+  width: 100%;
+  padding: 3px 1.5rem;
+  clear: both;
+  font-weight: normal;
+  color: #373a3c;
+  text-align: inherit;
+  white-space: nowrap;
+  background: none;
+  border: 0;
+}
+
+.dropdown-item:focus, .dropdown-item:hover {
+  color: #2b2d2f;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.dropdown-item.active, .dropdown-item.active:focus, .dropdown-item.active:hover {
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  outline: 0;
+}
+
+.dropdown-item.disabled, .dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  color: #818a91;
+}
+
+.dropdown-item.disabled:focus, .dropdown-item.disabled:hover {
+  text-decoration: none;
+  cursor: not-allowed;
+  background-color: transparent;
+  background-image: none;
+  filter: "progid:DXImageTransform.Microsoft.gradient(enabled = false)";
+}
+
+.open > .dropdown-menu {
+  display: block;
+}
+
+.open > a {
+  outline: 0;
+}
+
+.dropdown-menu-right {
+  right: 0;
+  left: auto;
+}
+
+.dropdown-menu-left {
+  right: auto;
+  left: 0;
+}
+
+.dropdown-header {
+  display: block;
+  padding: 0.5rem 1.5rem;
+  margin-bottom: 0;
+  font-size: 0.875rem;
+  color: #818a91;
+  white-space: nowrap;
+}
+
+.dropdown-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 990;
+}
+
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+  content: "";
+  border-top: 0;
+  border-bottom: 0.3em solid;
+}
+
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+  top: auto;
+  bottom: 100%;
+  margin-bottom: 0.125rem;
+}
+
+.btn-group,
+.btn-group-vertical {
+  position: relative;
+  display: inline-block;
+  vertical-align: middle;
+}
+
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+  position: relative;
+  float: left;
+  margin-bottom: 0;
+}
+
+.btn-group > .btn:focus, .btn-group > .btn:active, .btn-group > .btn.active,
+.btn-group-vertical > .btn:focus,
+.btn-group-vertical > .btn:active,
+.btn-group-vertical > .btn.active {
+  z-index: 2;
+}
+
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover {
+  z-index: 2;
+}
+
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+  margin-left: -1px;
+}
+
+.btn-toolbar {
+  margin-left: -0.5rem;
+}
+
+.btn-toolbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+  float: left;
+}
+
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+  margin-left: 0.5rem;
+}
+
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+  border-radius: 0;
+}
+
+.btn-group > .btn:first-child {
+  margin-left: 0;
+}
+
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group > .btn-group {
+  float: left;
+}
+
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+  outline: 0;
+}
+
+.btn + .dropdown-toggle-split {
+  padding-right: 0.75rem;
+  padding-left: 0.75rem;
+}
+
+.btn + .dropdown-toggle-split::after {
+  margin-left: 0;
+}
+
+.btn-sm + .dropdown-toggle-split, .btn-group-sm > .btn + .dropdown-toggle-split {
+  padding-right: 0.375rem;
+  padding-left: 0.375rem;
+}
+
+.btn-lg + .dropdown-toggle-split, .btn-group-lg > .btn + .dropdown-toggle-split {
+  padding-right: 1.125rem;
+  padding-left: 1.125rem;
+}
+
+.btn .caret {
+  margin-left: 0;
+}
+
+.btn-lg .caret, .btn-group-lg > .btn .caret {
+  border-width: 0.3em 0.3em 0;
+  border-bottom-width: 0;
+}
+
+.dropup .btn-lg .caret, .dropup .btn-group-lg > .btn .caret {
+  border-width: 0 0.3em 0.3em;
+}
+
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+  display: block;
+  float: none;
+  width: 100%;
+  max-width: 100%;
+}
+
+.btn-group-vertical > .btn-group::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.btn-group-vertical > .btn-group > .btn {
+  float: none;
+}
+
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+  margin-top: -1px;
+  margin-left: 0;
+}
+
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+  border-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+}
+
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+  position: absolute;
+  clip: rect(0, 0, 0, 0);
+  pointer-events: none;
+}
+
+.input-group {
+  position: relative;
+  width: 100%;
+  display: table;
+  border-collapse: separate;
+}
+
+.input-group .form-control {
+  position: relative;
+  z-index: 2;
+  float: left;
+  width: 100%;
+  margin-bottom: 0;
+}
+
+.input-group .form-control:focus, .input-group .form-control:active, .input-group .form-control:hover {
+  z-index: 3;
+}
+
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+  display: table-cell;
+}
+
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+  border-radius: 0;
+}
+
+.input-group-addon,
+.input-group-btn {
+  width: 1%;
+  white-space: nowrap;
+  vertical-align: middle;
+}
+
+.input-group-addon {
+  padding: 0.5rem 0.75rem;
+  margin-bottom: 0;
+  font-size: 1rem;
+  font-weight: normal;
+  line-height: 1.25;
+  color: #55595c;
+  text-align: center;
+  background-color: #eceeef;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+}
+
+.input-group-addon.form-control-sm,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .input-group-addon.btn {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.875rem;
+  border-radius: 0.2rem;
+}
+
+.input-group-addon.form-control-lg,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .input-group-addon.btn {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+  border-radius: 0.3rem;
+}
+
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+  margin-top: 0;
+}
+
+.input-group .form-control:not(:last-child),
+.input-group-addon:not(:last-child),
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group > .btn,
+.input-group-btn:not(:last-child) > .dropdown-toggle,
+.input-group-btn:not(:first-child) > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:not(:first-child) > .btn-group:not(:last-child) > .btn {
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+
+.input-group-addon:not(:last-child) {
+  border-right: 0;
+}
+
+.input-group .form-control:not(:first-child),
+.input-group-addon:not(:first-child),
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group > .btn,
+.input-group-btn:not(:first-child) > .dropdown-toggle,
+.input-group-btn:not(:last-child) > .btn:not(:first-child),
+.input-group-btn:not(:last-child) > .btn-group:not(:first-child) > .btn {
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.form-control + .input-group-addon:not(:first-child) {
+  border-left: 0;
+}
+
+.input-group-btn {
+  position: relative;
+  font-size: 0;
+  white-space: nowrap;
+}
+
+.input-group-btn > .btn {
+  position: relative;
+}
+
+.input-group-btn > .btn + .btn {
+  margin-left: -1px;
+}
+
+.input-group-btn > .btn:focus, .input-group-btn > .btn:active, .input-group-btn > .btn:hover {
+  z-index: 3;
+}
+
+.input-group-btn:not(:last-child) > .btn,
+.input-group-btn:not(:last-child) > .btn-group {
+  margin-right: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn,
+.input-group-btn:not(:first-child) > .btn-group {
+  z-index: 2;
+  margin-left: -1px;
+}
+
+.input-group-btn:not(:first-child) > .btn:focus, .input-group-btn:not(:first-child) > .btn:active, .input-group-btn:not(:first-child) > .btn:hover,
+.input-group-btn:not(:first-child) > .btn-group:focus,
+.input-group-btn:not(:first-child) > .btn-group:active,
+.input-group-btn:not(:first-child) > .btn-group:hover {
+  z-index: 3;
+}
+
+.custom-control {
+  position: relative;
+  display: inline-block;
+  padding-left: 1.5rem;
+  cursor: pointer;
+}
+
+.custom-control + .custom-control {
+  margin-left: 1rem;
+}
+
+.custom-control-input {
+  position: absolute;
+  z-index: -1;
+  opacity: 0;
+}
+
+.custom-control-input:checked ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #0074d9;
+}
+
+.custom-control-input:focus ~ .custom-control-indicator {
+  -webkit-box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+          box-shadow: 0 0 0 0.075rem #fff, 0 0 0 0.2rem #0074d9;
+}
+
+.custom-control-input:active ~ .custom-control-indicator {
+  color: #fff;
+  background-color: #84c6ff;
+}
+
+.custom-control-input:disabled ~ .custom-control-indicator {
+  cursor: not-allowed;
+  background-color: #eee;
+}
+
+.custom-control-input:disabled ~ .custom-control-description {
+  color: #767676;
+  cursor: not-allowed;
+}
+
+.custom-control-indicator {
+  position: absolute;
+  top: .25rem;
+  left: 0;
+  display: block;
+  width: 1rem;
+  height: 1rem;
+  pointer-events: none;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #ddd;
+  background-repeat: no-repeat;
+  background-position: center center;
+  -webkit-background-size: 50% 50%;
+          background-size: 50% 50%;
+}
+
+.custom-checkbox .custom-control-indicator {
+  border-radius: 0.25rem;
+}
+
+.custom-checkbox .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 8'%3E%3Cpath fill='#fff' d='M6.564.75l-3.59 3.612-1.538-1.55L0 4.26 2.974 7.25 8 2.193z'/%3E%3C/svg%3E");
+}
+
+.custom-checkbox .custom-control-input:indeterminate ~ .custom-control-indicator {
+  background-color: #0074d9;
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 4'%3E%3Cpath stroke='#fff' d='M0 2h4'/%3E%3C/svg%3E");
+}
+
+.custom-radio .custom-control-indicator {
+  border-radius: 50%;
+}
+
+.custom-radio .custom-control-input:checked ~ .custom-control-indicator {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-4 -4 8 8'%3E%3Ccircle r='3' fill='#fff'/%3E%3C/svg%3E");
+}
+
+.custom-controls-stacked .custom-control {
+  float: left;
+  clear: left;
+}
+
+.custom-controls-stacked .custom-control + .custom-control {
+  margin-left: 0;
+}
+
+.custom-select {
+  display: inline-block;
+  max-width: 100%;
+  height: calc(2.5rem - 2px);
+  padding: 0.375rem 1.75rem 0.375rem 0.75rem;
+  padding-right: 0.75rem \9;
+  color: #55595c;
+  vertical-align: middle;
+  background: #fff url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 4 5'%3E%3Cpath fill='#333' d='M2 0L0 2h4zm0 5L0 3h4z'/%3E%3C/svg%3E") no-repeat right 0.75rem center;
+  background-image: none \9;
+  -webkit-background-size: 8px 10px;
+          background-size: 8px 10px;
+  border: 1px solid rgba(0, 0, 0, 0.15);
+  border-radius: 0.25rem;
+  -moz-appearance: none;
+  -webkit-appearance: none;
+}
+
+.custom-select:focus {
+  border-color: #51a7e8;
+  outline: none;
+}
+
+.custom-select:focus::-ms-value {
+  color: #55595c;
+  background-color: #fff;
+}
+
+.custom-select:disabled {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.custom-select::-ms-expand {
+  opacity: 0;
+}
+
+.custom-select-sm {
+  padding-top: 0.375rem;
+  padding-bottom: 0.375rem;
+  font-size: 75%;
+}
+
+.custom-file {
+  position: relative;
+  display: inline-block;
+  max-width: 100%;
+  height: 2.5rem;
+  cursor: pointer;
+}
+
+.custom-file-input {
+  min-width: 14rem;
+  max-width: 100%;
+  margin: 0;
+  filter: alpha(opacity=0);
+  opacity: 0;
+}
+
+.custom-file-control {
+  position: absolute;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 5;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  -webkit-user-select: none;
+     -moz-user-select: none;
+      -ms-user-select: none;
+          user-select: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+}
+
+.custom-file-control:lang(en)::after {
+  content: "Choose file...";
+}
+
+.custom-file-control::before {
+  position: absolute;
+  top: -1px;
+  right: -1px;
+  bottom: -1px;
+  z-index: 6;
+  display: block;
+  height: 2.5rem;
+  padding: 0.5rem 1rem;
+  line-height: 1.5;
+  color: #555;
+  background-color: #eee;
+  border: 1px solid #ddd;
+  border-radius: 0 0.25rem 0.25rem 0;
+}
+
+.custom-file-control:lang(en)::before {
+  content: "Browse";
+}
+
+.nav {
+  padding-left: 0;
+  margin-bottom: 0;
+  list-style: none;
+}
+
+.nav-link {
+  display: inline-block;
+}
+
+.nav-link:focus, .nav-link:hover {
+  text-decoration: none;
+}
+
+.nav-link.disabled {
+  color: #818a91;
+}
+
+.nav-link.disabled, .nav-link.disabled:focus, .nav-link.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: transparent;
+}
+
+.nav-inline .nav-item {
+  display: inline-block;
+}
+
+.nav-inline .nav-item + .nav-item,
+.nav-inline .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.nav-tabs {
+  border-bottom: 1px solid #ddd;
+}
+
+.nav-tabs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-tabs .nav-item {
+  float: left;
+  margin-bottom: -1px;
+}
+
+.nav-tabs .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-tabs .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border: 1px solid transparent;
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.nav-tabs .nav-link:focus, .nav-tabs .nav-link:hover {
+  border-color: #eceeef #eceeef #ddd;
+}
+
+.nav-tabs .nav-link.disabled, .nav-tabs .nav-link.disabled:focus, .nav-tabs .nav-link.disabled:hover {
+  color: #818a91;
+  background-color: transparent;
+  border-color: transparent;
+}
+
+.nav-tabs .nav-link.active, .nav-tabs .nav-link.active:focus, .nav-tabs .nav-link.active:hover,
+.nav-tabs .nav-item.open .nav-link,
+.nav-tabs .nav-item.open .nav-link:focus,
+.nav-tabs .nav-item.open .nav-link:hover {
+  color: #55595c;
+  background-color: #fff;
+  border-color: #ddd #ddd transparent;
+}
+
+.nav-tabs .dropdown-menu {
+  margin-top: -1px;
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+}
+
+.nav-pills::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.nav-pills .nav-item {
+  float: left;
+}
+
+.nav-pills .nav-item + .nav-item {
+  margin-left: 0.2rem;
+}
+
+.nav-pills .nav-link {
+  display: block;
+  padding: 0.5em 1em;
+  border-radius: 0.25rem;
+}
+
+.nav-pills .nav-link.active, .nav-pills .nav-link.active:focus, .nav-pills .nav-link.active:hover,
+.nav-pills .nav-item.open .nav-link,
+.nav-pills .nav-item.open .nav-link:focus,
+.nav-pills .nav-item.open .nav-link:hover {
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+}
+
+.nav-stacked .nav-item {
+  display: block;
+  float: none;
+}
+
+.nav-stacked .nav-item + .nav-item {
+  margin-top: 0.2rem;
+  margin-left: 0;
+}
+
+.tab-content > .tab-pane {
+  display: none;
+}
+
+.tab-content > .active {
+  display: block;
+}
+
+.navbar {
+  position: relative;
+  padding: 0.5rem 1rem;
+}
+
+.navbar::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (min-width: 576px) {
+  .navbar {
+    border-radius: 0.25rem;
+  }
+}
+
+.navbar-full {
+  z-index: 1000;
+}
+
+@media (min-width: 576px) {
+  .navbar-full {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+  position: fixed;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+@media (min-width: 576px) {
+  .navbar-fixed-top,
+  .navbar-fixed-bottom {
+    border-radius: 0;
+  }
+}
+
+.navbar-fixed-top {
+  top: 0;
+}
+
+.navbar-fixed-bottom {
+  bottom: 0;
+}
+
+.navbar-sticky-top {
+  position: -webkit-sticky;
+  position: sticky;
+  top: 0;
+  z-index: 1030;
+  width: 100%;
+}
+
+@media (min-width: 576px) {
+  .navbar-sticky-top {
+    border-radius: 0;
+  }
+}
+
+.navbar-brand {
+  float: left;
+  padding-top: 0.25rem;
+  padding-bottom: 0.25rem;
+  margin-right: 1rem;
+  font-size: 1.25rem;
+  line-height: inherit;
+}
+
+.navbar-brand:focus, .navbar-brand:hover {
+  text-decoration: none;
+}
+
+.navbar-divider {
+  float: left;
+  width: 1px;
+  padding-top: 0.425rem;
+  padding-bottom: 0.425rem;
+  margin-right: 1rem;
+  margin-left: 1rem;
+  overflow: hidden;
+}
+
+.navbar-divider::before {
+  content: "\00a0";
+}
+
+.navbar-text {
+  display: inline-block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-toggler {
+  width: 2.5em;
+  height: 2em;
+  padding: 0.5rem 0.75rem;
+  font-size: 1.25rem;
+  line-height: 1;
+  background: transparent no-repeat center center;
+  -webkit-background-size: 24px 24px;
+          background-size: 24px 24px;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.navbar-toggler:focus, .navbar-toggler:hover {
+  text-decoration: none;
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-xs .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-xs .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-sm .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-sm .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-md .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-md .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block;
+  }
+}
+
+.navbar-toggleable-lg::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 1199px) {
+  .navbar-toggleable-lg .navbar-brand {
+    display: block;
+    float: none;
+    margin-top: .5rem;
+    margin-right: 0;
+  }
+  .navbar-toggleable-lg .navbar-nav {
+    margin-top: .5rem;
+    margin-bottom: .5rem;
+  }
+  .navbar-toggleable-lg .navbar-nav .dropdown-menu {
+    position: static;
+    float: none;
+  }
+}
+
+@media (min-width: 1200px) {
+  .navbar-toggleable-lg {
+    display: block;
+  }
+}
+
+.navbar-toggleable-xl {
+  display: block;
+}
+
+.navbar-toggleable-xl::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.navbar-toggleable-xl .navbar-brand {
+  display: block;
+  float: none;
+  margin-top: .5rem;
+  margin-right: 0;
+}
+
+.navbar-toggleable-xl .navbar-nav {
+  margin-top: .5rem;
+  margin-bottom: .5rem;
+}
+
+.navbar-toggleable-xl .navbar-nav .dropdown-menu {
+  position: static;
+  float: none;
+}
+
+.navbar-nav .nav-item {
+  float: left;
+}
+
+.navbar-nav .nav-link {
+  display: block;
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+}
+
+.navbar-nav .nav-link + .nav-link {
+  margin-left: 1rem;
+}
+
+.navbar-nav .nav-item + .nav-item {
+  margin-left: 1rem;
+}
+
+.navbar-light .navbar-brand,
+.navbar-light .navbar-toggler {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-brand:focus, .navbar-light .navbar-brand:hover,
+.navbar-light .navbar-toggler:focus,
+.navbar-light .navbar-toggler:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-nav .nav-link {
+  color: rgba(0, 0, 0, 0.5);
+}
+
+.navbar-light .navbar-nav .nav-link:focus, .navbar-light .navbar-nav .nav-link:hover {
+  color: rgba(0, 0, 0, 0.7);
+}
+
+.navbar-light .navbar-nav .open > .nav-link, .navbar-light .navbar-nav .open > .nav-link:focus, .navbar-light .navbar-nav .open > .nav-link:hover,
+.navbar-light .navbar-nav .active > .nav-link,
+.navbar-light .navbar-nav .active > .nav-link:focus,
+.navbar-light .navbar-nav .active > .nav-link:hover,
+.navbar-light .navbar-nav .nav-link.open,
+.navbar-light .navbar-nav .nav-link.open:focus,
+.navbar-light .navbar-nav .nav-link.open:hover,
+.navbar-light .navbar-nav .nav-link.active,
+.navbar-light .navbar-nav .nav-link.active:focus,
+.navbar-light .navbar-nav .nav-link.active:hover {
+  color: rgba(0, 0, 0, 0.9);
+}
+
+.navbar-light .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(0, 0, 0, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(0, 0, 0, 0.1);
+}
+
+.navbar-light .navbar-divider {
+  background-color: rgba(0, 0, 0, 0.075);
+}
+
+.navbar-dark .navbar-brand,
+.navbar-dark .navbar-toggler {
+  color: white;
+}
+
+.navbar-dark .navbar-brand:focus, .navbar-dark .navbar-brand:hover,
+.navbar-dark .navbar-toggler:focus,
+.navbar-dark .navbar-toggler:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-nav .nav-link {
+  color: rgba(255, 255, 255, 0.5);
+}
+
+.navbar-dark .navbar-nav .nav-link:focus, .navbar-dark .navbar-nav .nav-link:hover {
+  color: rgba(255, 255, 255, 0.75);
+}
+
+.navbar-dark .navbar-nav .open > .nav-link, .navbar-dark .navbar-nav .open > .nav-link:focus, .navbar-dark .navbar-nav .open > .nav-link:hover,
+.navbar-dark .navbar-nav .active > .nav-link,
+.navbar-dark .navbar-nav .active > .nav-link:focus,
+.navbar-dark .navbar-nav .active > .nav-link:hover,
+.navbar-dark .navbar-nav .nav-link.open,
+.navbar-dark .navbar-nav .nav-link.open:focus,
+.navbar-dark .navbar-nav .nav-link.open:hover,
+.navbar-dark .navbar-nav .nav-link.active,
+.navbar-dark .navbar-nav .nav-link.active:focus,
+.navbar-dark .navbar-nav .nav-link.active:hover {
+  color: white;
+}
+
+.navbar-dark .navbar-toggler {
+  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg viewBox='0 0 32 32' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath stroke='rgba(255, 255, 255, 0.5)' stroke-width='2' stroke-linecap='round' stroke-miterlimit='10' d='M4 8h24M4 16h24M4 24h24'/%3E%3C/svg%3E");
+  border-color: rgba(255, 255, 255, 0.1);
+}
+
+.navbar-dark .navbar-divider {
+  background-color: rgba(255, 255, 255, 0.075);
+}
+
+.navbar-toggleable-xs::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 575px) {
+  .navbar-toggleable-xs .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .navbar-toggleable-xs {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-sm::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 767px) {
+  .navbar-toggleable-sm .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 768px) {
+  .navbar-toggleable-sm {
+    display: block !important;
+  }
+}
+
+.navbar-toggleable-md::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+@media (max-width: 991px) {
+  .navbar-toggleable-md .navbar-nav .nav-item {
+    float: none;
+    margin-left: 0;
+  }
+}
+
+@media (min-width: 992px) {
+  .navbar-toggleable-md {
+    display: block !important;
+  }
+}
+
+.card {
+  position: relative;
+  display: block;
+  margin-bottom: 0.75rem;
+  background-color: #fff;
+  border-radius: 0.25rem;
+  border: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-block {
+  padding: 1.25rem;
+}
+
+.card-block::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-title {
+  margin-bottom: 0.75rem;
+}
+
+.card-subtitle {
+  margin-top: -0.375rem;
+  margin-bottom: 0;
+}
+
+.card-text:last-child {
+  margin-bottom: 0;
+}
+
+.card-link:hover {
+  text-decoration: none;
+}
+
+.card-link + .card-link {
+  margin-left: 1.25rem;
+}
+
+.card > .list-group:first-child .list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.card > .list-group:last-child .list-group-item:last-child {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.card-header {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 0;
+  background-color: #f5f5f5;
+  border-bottom: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-header:first-child {
+  border-radius: calc(0.25rem - 1px) calc(0.25rem - 1px) 0 0;
+}
+
+.card-footer {
+  padding: 0.75rem 1.25rem;
+  background-color: #f5f5f5;
+  border-top: 1px solid rgba(0, 0, 0, 0.125);
+}
+
+.card-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.card-footer:last-child {
+  border-radius: 0 0 calc(0.25rem - 1px) calc(0.25rem - 1px);
+}
+
+.card-header-tabs {
+  margin-right: -0.625rem;
+  margin-bottom: -0.75rem;
+  margin-left: -0.625rem;
+  border-bottom: 0;
+}
+
+.card-header-pills {
+  margin-right: -0.625rem;
+  margin-left: -0.625rem;
+}
+
+.card-primary {
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.card-primary .card-header,
+.card-primary .card-footer {
+  background-color: transparent;
+}
+
+.card-success {
+  background-color: #5cb85c;
+  border-color: #5cb85c;
+}
+
+.card-success .card-header,
+.card-success .card-footer {
+  background-color: transparent;
+}
+
+.card-info {
+  background-color: #5bc0de;
+  border-color: #5bc0de;
+}
+
+.card-info .card-header,
+.card-info .card-footer {
+  background-color: transparent;
+}
+
+.card-warning {
+  background-color: #f0ad4e;
+  border-color: #f0ad4e;
+}
+
+.card-warning .card-header,
+.card-warning .card-footer {
+  background-color: transparent;
+}
+
+.card-danger {
+  background-color: #d9534f;
+  border-color: #d9534f;
+}
+
+.card-danger .card-header,
+.card-danger .card-footer {
+  background-color: transparent;
+}
+
+.card-outline-primary {
+  background-color: transparent;
+  border-color: #0275d8;
+}
+
+.card-outline-secondary {
+  background-color: transparent;
+  border-color: #ccc;
+}
+
+.card-outline-info {
+  background-color: transparent;
+  border-color: #5bc0de;
+}
+
+.card-outline-success {
+  background-color: transparent;
+  border-color: #5cb85c;
+}
+
+.card-outline-warning {
+  background-color: transparent;
+  border-color: #f0ad4e;
+}
+
+.card-outline-danger {
+  background-color: transparent;
+  border-color: #d9534f;
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer {
+  border-color: rgba(255, 255, 255, 0.2);
+}
+
+.card-inverse .card-header,
+.card-inverse .card-footer,
+.card-inverse .card-title,
+.card-inverse .card-blockquote {
+  color: #fff;
+}
+
+.card-inverse .card-link,
+.card-inverse .card-text,
+.card-inverse .card-subtitle,
+.card-inverse .card-blockquote .blockquote-footer {
+  color: rgba(255, 255, 255, 0.65);
+}
+
+.card-inverse .card-link:focus, .card-inverse .card-link:hover {
+  color: #fff;
+}
+
+.card-blockquote {
+  padding: 0;
+  margin-bottom: 0;
+  border-left: 0;
+}
+
+.card-img {
+  border-radius: calc(0.25rem - 1px);
+}
+
+.card-img-overlay {
+  position: absolute;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  padding: 1.25rem;
+}
+
+.card-img-top {
+  border-top-right-radius: calc(0.25rem - 1px);
+  border-top-left-radius: calc(0.25rem - 1px);
+}
+
+.card-img-bottom {
+  border-bottom-right-radius: calc(0.25rem - 1px);
+  border-bottom-left-radius: calc(0.25rem - 1px);
+}
+
+@media (min-width: 576px) {
+  .card-deck {
+    display: table;
+    width: 100%;
+    margin-bottom: 0.75rem;
+    table-layout: fixed;
+    border-spacing: 1.25rem 0;
+  }
+  .card-deck .card {
+    display: table-cell;
+    margin-bottom: 0;
+    vertical-align: top;
+  }
+  .card-deck-wrapper {
+    margin-right: -1.25rem;
+    margin-left: -1.25rem;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-group {
+    display: table;
+    width: 100%;
+    table-layout: fixed;
+  }
+  .card-group .card {
+    display: table-cell;
+    vertical-align: top;
+  }
+  .card-group .card + .card {
+    margin-left: 0;
+    border-left: 0;
+  }
+  .card-group .card:first-child {
+    border-bottom-right-radius: 0;
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-top {
+    border-top-right-radius: 0;
+  }
+  .card-group .card:first-child .card-img-bottom {
+    border-bottom-right-radius: 0;
+  }
+  .card-group .card:last-child {
+    border-bottom-left-radius: 0;
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-top {
+    border-top-left-radius: 0;
+  }
+  .card-group .card:last-child .card-img-bottom {
+    border-bottom-left-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) {
+    border-radius: 0;
+  }
+  .card-group .card:not(:first-child):not(:last-child) .card-img-top,
+  .card-group .card:not(:first-child):not(:last-child) .card-img-bottom {
+    border-radius: 0;
+  }
+}
+
+@media (min-width: 576px) {
+  .card-columns {
+    -webkit-column-count: 3;
+       -moz-column-count: 3;
+            column-count: 3;
+    -webkit-column-gap: 1.25rem;
+       -moz-column-gap: 1.25rem;
+            column-gap: 1.25rem;
+  }
+  .card-columns .card {
+    display: inline-block;
+    width: 100%;
+  }
+}
+
+.breadcrumb {
+  padding: 0.75rem 1rem;
+  margin-bottom: 1rem;
+  list-style: none;
+  background-color: #eceeef;
+  border-radius: 0.25rem;
+}
+
+.breadcrumb::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.breadcrumb-item {
+  float: left;
+}
+
+.breadcrumb-item + .breadcrumb-item::before {
+  display: inline-block;
+  padding-right: 0.5rem;
+  padding-left: 0.5rem;
+  color: #818a91;
+  content: "/";
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: underline;
+}
+
+.breadcrumb-item + .breadcrumb-item:hover::before {
+  text-decoration: none;
+}
+
+.breadcrumb-item.active {
+  color: #818a91;
+}
+
+.pagination {
+  display: inline-block;
+  padding-left: 0;
+  margin-top: 1rem;
+  margin-bottom: 1rem;
+  border-radius: 0.25rem;
+}
+
+.page-item {
+  display: inline;
+}
+
+.page-item:first-child .page-link {
+  margin-left: 0;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.page-item:last-child .page-link {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.page-item.active .page-link, .page-item.active .page-link:focus, .page-item.active .page-link:hover {
+  z-index: 2;
+  color: #fff;
+  cursor: default;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.page-item.disabled .page-link, .page-item.disabled .page-link:focus, .page-item.disabled .page-link:hover {
+  color: #818a91;
+  pointer-events: none;
+  cursor: not-allowed;
+  background-color: #fff;
+  border-color: #ddd;
+}
+
+.page-link {
+  position: relative;
+  float: left;
+  padding: 0.5rem 0.75rem;
+  margin-left: -1px;
+  color: #0275d8;
+  text-decoration: none;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.page-link:focus, .page-link:hover {
+  color: #014c8c;
+  background-color: #eceeef;
+  border-color: #ddd;
+}
+
+.pagination-lg .page-link {
+  padding: 0.75rem 1.5rem;
+  font-size: 1.25rem;
+}
+
+.pagination-lg .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.3rem;
+  border-top-left-radius: 0.3rem;
+}
+
+.pagination-lg .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.3rem;
+  border-top-right-radius: 0.3rem;
+}
+
+.pagination-sm .page-link {
+  padding: 0.275rem 0.75rem;
+  font-size: 0.875rem;
+}
+
+.pagination-sm .page-item:first-child .page-link {
+  border-bottom-left-radius: 0.2rem;
+  border-top-left-radius: 0.2rem;
+}
+
+.pagination-sm .page-item:last-child .page-link {
+  border-bottom-right-radius: 0.2rem;
+  border-top-right-radius: 0.2rem;
+}
+
+.tag {
+  display: inline-block;
+  padding: 0.25em 0.4em;
+  font-size: 75%;
+  font-weight: bold;
+  line-height: 1;
+  color: #fff;
+  text-align: center;
+  white-space: nowrap;
+  vertical-align: baseline;
+  border-radius: 0.25rem;
+}
+
+.tag:empty {
+  display: none;
+}
+
+.btn .tag {
+  position: relative;
+  top: -1px;
+}
+
+a.tag:focus, a.tag:hover {
+  color: #fff;
+  text-decoration: none;
+  cursor: pointer;
+}
+
+.tag-pill {
+  padding-right: 0.6em;
+  padding-left: 0.6em;
+  border-radius: 10rem;
+}
+
+.tag-default {
+  background-color: #818a91;
+}
+
+.tag-default[href]:focus, .tag-default[href]:hover {
+  background-color: #687077;
+}
+
+.tag-primary {
+  background-color: #0275d8;
+}
+
+.tag-primary[href]:focus, .tag-primary[href]:hover {
+  background-color: #025aa5;
+}
+
+.tag-success {
+  background-color: #5cb85c;
+}
+
+.tag-success[href]:focus, .tag-success[href]:hover {
+  background-color: #449d44;
+}
+
+.tag-info {
+  background-color: #5bc0de;
+}
+
+.tag-info[href]:focus, .tag-info[href]:hover {
+  background-color: #31b0d5;
+}
+
+.tag-warning {
+  background-color: #f0ad4e;
+}
+
+.tag-warning[href]:focus, .tag-warning[href]:hover {
+  background-color: #ec971f;
+}
+
+.tag-danger {
+  background-color: #d9534f;
+}
+
+.tag-danger[href]:focus, .tag-danger[href]:hover {
+  background-color: #c9302c;
+}
+
+.jumbotron {
+  padding: 2rem 1rem;
+  margin-bottom: 2rem;
+  background-color: #eceeef;
+  border-radius: 0.3rem;
+}
+
+@media (min-width: 576px) {
+  .jumbotron {
+    padding: 4rem 2rem;
+  }
+}
+
+.jumbotron-hr {
+  border-top-color: #d0d5d8;
+}
+
+.jumbotron-fluid {
+  padding-right: 0;
+  padding-left: 0;
+  border-radius: 0;
+}
+
+.alert {
+  padding: 0.75rem 1.25rem;
+  margin-bottom: 1rem;
+  border: 1px solid transparent;
+  border-radius: 0.25rem;
+}
+
+.alert-heading {
+  color: inherit;
+}
+
+.alert-link {
+  font-weight: bold;
+}
+
+.alert-dismissible {
+  padding-right: 2.5rem;
+}
+
+.alert-dismissible .close {
+  position: relative;
+  top: -.125rem;
+  right: -1.25rem;
+  color: inherit;
+}
+
+.alert-success {
+  background-color: #dff0d8;
+  border-color: #d0e9c6;
+  color: #3c763d;
+}
+
+.alert-success hr {
+  border-top-color: #c1e2b3;
+}
+
+.alert-success .alert-link {
+  color: #2b542c;
+}
+
+.alert-info {
+  background-color: #d9edf7;
+  border-color: #bcdff1;
+  color: #31708f;
+}
+
+.alert-info hr {
+  border-top-color: #a6d5ec;
+}
+
+.alert-info .alert-link {
+  color: #245269;
+}
+
+.alert-warning {
+  background-color: #fcf8e3;
+  border-color: #faf2cc;
+  color: #8a6d3b;
+}
+
+.alert-warning hr {
+  border-top-color: #f7ecb5;
+}
+
+.alert-warning .alert-link {
+  color: #66512c;
+}
+
+.alert-danger {
+  background-color: #f2dede;
+  border-color: #ebcccc;
+  color: #a94442;
+}
+
+.alert-danger hr {
+  border-top-color: #e4b9b9;
+}
+
+.alert-danger .alert-link {
+  color: #843534;
+}
+
+@-webkit-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@-o-keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+@keyframes progress-bar-stripes {
+  from {
+    background-position: 1rem 0;
+  }
+  to {
+    background-position: 0 0;
+  }
+}
+
+.progress {
+  display: block;
+  width: 100%;
+  height: 1rem;
+  margin-bottom: 1rem;
+}
+
+.progress[value] {
+  background-color: #eee;
+  border: 0;
+  -webkit-appearance: none;
+     -moz-appearance: none;
+          appearance: none;
+  border-radius: 0.25rem;
+}
+
+.progress[value]::-ms-fill {
+  background-color: #0074d9;
+  border: 0;
+}
+
+.progress[value]::-moz-progress-bar {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-value {
+  background-color: #0074d9;
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.progress[value="100"]::-moz-progress-bar {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value="100"]::-webkit-progress-value {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.progress[value]::-webkit-progress-bar {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+base::-moz-progress-bar,
+.progress[value] {
+  background-color: #eee;
+  border-radius: 0.25rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress {
+    background-color: #eee;
+    border-radius: 0.25rem;
+  }
+  .progress-bar {
+    display: inline-block;
+    height: 1rem;
+    text-indent: -999rem;
+    background-color: #0074d9;
+    border-bottom-left-radius: 0.25rem;
+    border-top-left-radius: 0.25rem;
+  }
+  .progress[width="100%"] {
+    border-bottom-right-radius: 0.25rem;
+    border-top-right-radius: 0.25rem;
+  }
+}
+
+.progress-striped[value]::-webkit-progress-value {
+  background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  -webkit-background-size: 1rem 1rem;
+          background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-moz-progress-bar {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+.progress-striped[value]::-ms-fill {
+  background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+  background-size: 1rem 1rem;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-bar-striped {
+    background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+    -webkit-background-size: 1rem 1rem;
+            background-size: 1rem 1rem;
+  }
+}
+
+.progress-animated[value]::-webkit-progress-value {
+  -webkit-animation: progress-bar-stripes 2s linear infinite;
+          animation: progress-bar-stripes 2s linear infinite;
+}
+
+.progress-animated[value]::-moz-progress-bar {
+  animation: progress-bar-stripes 2s linear infinite;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-animated .progress-bar-striped {
+    -webkit-animation: progress-bar-stripes 2s linear infinite;
+         -o-animation: progress-bar-stripes 2s linear infinite;
+            animation: progress-bar-stripes 2s linear infinite;
+  }
+}
+
+.progress-success[value]::-webkit-progress-value {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-moz-progress-bar {
+  background-color: #5cb85c;
+}
+
+.progress-success[value]::-ms-fill {
+  background-color: #5cb85c;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-success .progress-bar {
+    background-color: #5cb85c;
+  }
+}
+
+.progress-info[value]::-webkit-progress-value {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-moz-progress-bar {
+  background-color: #5bc0de;
+}
+
+.progress-info[value]::-ms-fill {
+  background-color: #5bc0de;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-info .progress-bar {
+    background-color: #5bc0de;
+  }
+}
+
+.progress-warning[value]::-webkit-progress-value {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-moz-progress-bar {
+  background-color: #f0ad4e;
+}
+
+.progress-warning[value]::-ms-fill {
+  background-color: #f0ad4e;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-warning .progress-bar {
+    background-color: #f0ad4e;
+  }
+}
+
+.progress-danger[value]::-webkit-progress-value {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-moz-progress-bar {
+  background-color: #d9534f;
+}
+
+.progress-danger[value]::-ms-fill {
+  background-color: #d9534f;
+}
+
+@media screen and (min-width: 0\0) {
+  .progress-danger .progress-bar {
+    background-color: #d9534f;
+  }
+}
+
+.media,
+.media-body {
+  overflow: hidden;
+}
+
+.media-body {
+  width: 10000px;
+}
+
+.media-left,
+.media-right,
+.media-body {
+  display: table-cell;
+  vertical-align: top;
+}
+
+.media-middle {
+  vertical-align: middle;
+}
+
+.media-bottom {
+  vertical-align: bottom;
+}
+
+.media-object {
+  display: block;
+}
+
+.media-object.img-thumbnail {
+  max-width: none;
+}
+
+.media-right {
+  padding-left: 10px;
+}
+
+.media-left {
+  padding-right: 10px;
+}
+
+.media-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.media-list {
+  padding-left: 0;
+  list-style: none;
+}
+
+.list-group {
+  padding-left: 0;
+  margin-bottom: 0;
+}
+
+.list-group-item {
+  position: relative;
+  display: block;
+  padding: 0.75rem 1.25rem;
+  margin-bottom: -1px;
+  background-color: #fff;
+  border: 1px solid #ddd;
+}
+
+.list-group-item:first-child {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.list-group-item:last-child {
+  margin-bottom: 0;
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.list-group-item.disabled, .list-group-item.disabled:focus, .list-group-item.disabled:hover {
+  color: #818a91;
+  cursor: not-allowed;
+  background-color: #eceeef;
+}
+
+.list-group-item.disabled .list-group-item-heading, .list-group-item.disabled:focus .list-group-item-heading, .list-group-item.disabled:hover .list-group-item-heading {
+  color: inherit;
+}
+
+.list-group-item.disabled .list-group-item-text, .list-group-item.disabled:focus .list-group-item-text, .list-group-item.disabled:hover .list-group-item-text {
+  color: #818a91;
+}
+
+.list-group-item.active, .list-group-item.active:focus, .list-group-item.active:hover {
+  z-index: 2;
+  color: #fff;
+  text-decoration: none;
+  background-color: #0275d8;
+  border-color: #0275d8;
+}
+
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small, .list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > .small, .list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > .small {
+  color: inherit;
+}
+
+.list-group-item.active .list-group-item-text, .list-group-item.active:focus .list-group-item-text, .list-group-item.active:hover .list-group-item-text {
+  color: #a8d6fe;
+}
+
+.list-group-flush .list-group-item {
+  border-right: 0;
+  border-left: 0;
+  border-radius: 0;
+}
+
+.list-group-item-action {
+  width: 100%;
+  color: #555;
+  text-align: inherit;
+}
+
+.list-group-item-action .list-group-item-heading {
+  color: #333;
+}
+
+.list-group-item-action:focus, .list-group-item-action:hover {
+  color: #555;
+  text-decoration: none;
+  background-color: #f5f5f5;
+}
+
+.list-group-item-success {
+  color: #3c763d;
+  background-color: #dff0d8;
+}
+
+a.list-group-item-success,
+button.list-group-item-success {
+  color: #3c763d;
+}
+
+a.list-group-item-success .list-group-item-heading,
+button.list-group-item-success .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-success:focus, a.list-group-item-success:hover,
+button.list-group-item-success:focus,
+button.list-group-item-success:hover {
+  color: #3c763d;
+  background-color: #d0e9c6;
+}
+
+a.list-group-item-success.active, a.list-group-item-success.active:focus, a.list-group-item-success.active:hover,
+button.list-group-item-success.active,
+button.list-group-item-success.active:focus,
+button.list-group-item-success.active:hover {
+  color: #fff;
+  background-color: #3c763d;
+  border-color: #3c763d;
+}
+
+.list-group-item-info {
+  color: #31708f;
+  background-color: #d9edf7;
+}
+
+a.list-group-item-info,
+button.list-group-item-info {
+  color: #31708f;
+}
+
+a.list-group-item-info .list-group-item-heading,
+button.list-group-item-info .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-info:focus, a.list-group-item-info:hover,
+button.list-group-item-info:focus,
+button.list-group-item-info:hover {
+  color: #31708f;
+  background-color: #c4e3f3;
+}
+
+a.list-group-item-info.active, a.list-group-item-info.active:focus, a.list-group-item-info.active:hover,
+button.list-group-item-info.active,
+button.list-group-item-info.active:focus,
+button.list-group-item-info.active:hover {
+  color: #fff;
+  background-color: #31708f;
+  border-color: #31708f;
+}
+
+.list-group-item-warning {
+  color: #8a6d3b;
+  background-color: #fcf8e3;
+}
+
+a.list-group-item-warning,
+button.list-group-item-warning {
+  color: #8a6d3b;
+}
+
+a.list-group-item-warning .list-group-item-heading,
+button.list-group-item-warning .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-warning:focus, a.list-group-item-warning:hover,
+button.list-group-item-warning:focus,
+button.list-group-item-warning:hover {
+  color: #8a6d3b;
+  background-color: #faf2cc;
+}
+
+a.list-group-item-warning.active, a.list-group-item-warning.active:focus, a.list-group-item-warning.active:hover,
+button.list-group-item-warning.active,
+button.list-group-item-warning.active:focus,
+button.list-group-item-warning.active:hover {
+  color: #fff;
+  background-color: #8a6d3b;
+  border-color: #8a6d3b;
+}
+
+.list-group-item-danger {
+  color: #a94442;
+  background-color: #f2dede;
+}
+
+a.list-group-item-danger,
+button.list-group-item-danger {
+  color: #a94442;
+}
+
+a.list-group-item-danger .list-group-item-heading,
+button.list-group-item-danger .list-group-item-heading {
+  color: inherit;
+}
+
+a.list-group-item-danger:focus, a.list-group-item-danger:hover,
+button.list-group-item-danger:focus,
+button.list-group-item-danger:hover {
+  color: #a94442;
+  background-color: #ebcccc;
+}
+
+a.list-group-item-danger.active, a.list-group-item-danger.active:focus, a.list-group-item-danger.active:hover,
+button.list-group-item-danger.active,
+button.list-group-item-danger.active:focus,
+button.list-group-item-danger.active:hover {
+  color: #fff;
+  background-color: #a94442;
+  border-color: #a94442;
+}
+
+.list-group-item-heading {
+  margin-top: 0;
+  margin-bottom: 5px;
+}
+
+.list-group-item-text {
+  margin-bottom: 0;
+  line-height: 1.3;
+}
+
+.embed-responsive {
+  position: relative;
+  display: block;
+  height: 0;
+  padding: 0;
+  overflow: hidden;
+}
+
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  border: 0;
+}
+
+.embed-responsive-21by9 {
+  padding-bottom: 42.857143%;
+}
+
+.embed-responsive-16by9 {
+  padding-bottom: 56.25%;
+}
+
+.embed-responsive-4by3 {
+  padding-bottom: 75%;
+}
+
+.embed-responsive-1by1 {
+  padding-bottom: 100%;
+}
+
+.close {
+  float: right;
+  font-size: 1.5rem;
+  font-weight: bold;
+  line-height: 1;
+  color: #000;
+  text-shadow: 0 1px 0 #fff;
+  opacity: .2;
+}
+
+.close:focus, .close:hover {
+  color: #000;
+  text-decoration: none;
+  cursor: pointer;
+  opacity: .5;
+}
+
+button.close {
+  padding: 0;
+  cursor: pointer;
+  background: transparent;
+  border: 0;
+  -webkit-appearance: none;
+}
+
+.modal-open {
+  overflow: hidden;
+}
+
+.modal {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1050;
+  display: none;
+  overflow: hidden;
+  outline: 0;
+}
+
+.modal.fade .modal-dialog {
+  -webkit-transition: -webkit-transform .3s ease-out;
+  transition: -webkit-transform .3s ease-out;
+  -o-transition: -o-transform .3s ease-out;
+  transition: transform .3s ease-out;
+  transition: transform .3s ease-out, -webkit-transform .3s ease-out, -o-transform .3s ease-out;
+  -webkit-transform: translate(0, -25%);
+      -ms-transform: translate(0, -25%);
+       -o-transform: translate(0, -25%);
+          transform: translate(0, -25%);
+}
+
+.modal.in .modal-dialog {
+  -webkit-transform: translate(0, 0);
+      -ms-transform: translate(0, 0);
+       -o-transform: translate(0, 0);
+          transform: translate(0, 0);
+}
+
+.modal-open .modal {
+  overflow-x: hidden;
+  overflow-y: auto;
+}
+
+.modal-dialog {
+  position: relative;
+  width: auto;
+  margin: 10px;
+}
+
+.modal-content {
+  position: relative;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+  outline: 0;
+}
+
+.modal-backdrop {
+  position: fixed;
+  top: 0;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 1040;
+  background-color: #000;
+}
+
+.modal-backdrop.fade {
+  opacity: 0;
+}
+
+.modal-backdrop.in {
+  opacity: 0.5;
+}
+
+.modal-header {
+  padding: 15px;
+  border-bottom: 1px solid #e5e5e5;
+}
+
+.modal-header::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-header .close {
+  margin-top: -2px;
+}
+
+.modal-title {
+  margin: 0;
+  line-height: 1.5;
+}
+
+.modal-body {
+  position: relative;
+  padding: 15px;
+}
+
+.modal-footer {
+  padding: 15px;
+  text-align: right;
+  border-top: 1px solid #e5e5e5;
+}
+
+.modal-footer::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.modal-scrollbar-measure {
+  position: absolute;
+  top: -9999px;
+  width: 50px;
+  height: 50px;
+  overflow: scroll;
+}
+
+@media (min-width: 576px) {
+  .modal-dialog {
+    max-width: 600px;
+    margin: 30px auto;
+  }
+  .modal-sm {
+    max-width: 300px;
+  }
+}
+
+@media (min-width: 992px) {
+  .modal-lg {
+    max-width: 900px;
+  }
+}
+
+.tooltip {
+  position: absolute;
+  z-index: 1070;
+  display: block;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  opacity: 0;
+}
+
+.tooltip.in {
+  opacity: 0.9;
+}
+
+.tooltip.tooltip-top, .tooltip.bs-tether-element-attached-bottom {
+  padding: 5px 0;
+  margin-top: -3px;
+}
+
+.tooltip.tooltip-top .tooltip-inner::before, .tooltip.bs-tether-element-attached-bottom .tooltip-inner::before {
+  bottom: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 5px 5px 0;
+  border-top-color: #000;
+}
+
+.tooltip.tooltip-right, .tooltip.bs-tether-element-attached-left {
+  padding: 0 5px;
+  margin-left: 3px;
+}
+
+.tooltip.tooltip-right .tooltip-inner::before, .tooltip.bs-tether-element-attached-left .tooltip-inner::before {
+  top: 50%;
+  left: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 5px 5px 0;
+  border-right-color: #000;
+}
+
+.tooltip.tooltip-bottom, .tooltip.bs-tether-element-attached-top {
+  padding: 5px 0;
+  margin-top: 3px;
+}
+
+.tooltip.tooltip-bottom .tooltip-inner::before, .tooltip.bs-tether-element-attached-top .tooltip-inner::before {
+  top: 0;
+  left: 50%;
+  margin-left: -5px;
+  content: "";
+  border-width: 0 5px 5px;
+  border-bottom-color: #000;
+}
+
+.tooltip.tooltip-left, .tooltip.bs-tether-element-attached-right {
+  padding: 0 5px;
+  margin-left: -3px;
+}
+
+.tooltip.tooltip-left .tooltip-inner::before, .tooltip.bs-tether-element-attached-right .tooltip-inner::before {
+  top: 50%;
+  right: 0;
+  margin-top: -5px;
+  content: "";
+  border-width: 5px 0 5px 5px;
+  border-left-color: #000;
+}
+
+.tooltip-inner {
+  max-width: 200px;
+  padding: 3px 8px;
+  color: #fff;
+  text-align: center;
+  background-color: #000;
+  border-radius: 0.25rem;
+}
+
+.tooltip-inner::before {
+  position: absolute;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover {
+  position: absolute;
+  top: 0;
+  left: 0;
+  z-index: 1060;
+  display: block;
+  max-width: 276px;
+  padding: 1px;
+  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
+  font-style: normal;
+  font-weight: normal;
+  letter-spacing: normal;
+  line-break: auto;
+  line-height: 1.5;
+  text-align: left;
+  text-align: start;
+  text-decoration: none;
+  text-shadow: none;
+  text-transform: none;
+  white-space: normal;
+  word-break: normal;
+  word-spacing: normal;
+  font-size: 0.875rem;
+  word-wrap: break-word;
+  background-color: #fff;
+  -webkit-background-clip: padding-box;
+          background-clip: padding-box;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 0.3rem;
+}
+
+.popover.popover-top, .popover.bs-tether-element-attached-bottom {
+  margin-top: -10px;
+}
+
+.popover.popover-top::before, .popover.popover-top::after, .popover.bs-tether-element-attached-bottom::before, .popover.bs-tether-element-attached-bottom::after {
+  left: 50%;
+  border-bottom-width: 0;
+}
+
+.popover.popover-top::before, .popover.bs-tether-element-attached-bottom::before {
+  bottom: -11px;
+  margin-left: -11px;
+  border-top-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-top::after, .popover.bs-tether-element-attached-bottom::after {
+  bottom: -10px;
+  margin-left: -10px;
+  border-top-color: #fff;
+}
+
+.popover.popover-right, .popover.bs-tether-element-attached-left {
+  margin-left: 10px;
+}
+
+.popover.popover-right::before, .popover.popover-right::after, .popover.bs-tether-element-attached-left::before, .popover.bs-tether-element-attached-left::after {
+  top: 50%;
+  border-left-width: 0;
+}
+
+.popover.popover-right::before, .popover.bs-tether-element-attached-left::before {
+  left: -11px;
+  margin-top: -11px;
+  border-right-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-right::after, .popover.bs-tether-element-attached-left::after {
+  left: -10px;
+  margin-top: -10px;
+  border-right-color: #fff;
+}
+
+.popover.popover-bottom, .popover.bs-tether-element-attached-top {
+  margin-top: 10px;
+}
+
+.popover.popover-bottom::before, .popover.popover-bottom::after, .popover.bs-tether-element-attached-top::before, .popover.bs-tether-element-attached-top::after {
+  left: 50%;
+  border-top-width: 0;
+}
+
+.popover.popover-bottom::before, .popover.bs-tether-element-attached-top::before {
+  top: -11px;
+  margin-left: -11px;
+  border-bottom-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-bottom::after, .popover.bs-tether-element-attached-top::after {
+  top: -10px;
+  margin-left: -10px;
+  border-bottom-color: #f7f7f7;
+}
+
+.popover.popover-bottom .popover-title::before, .popover.bs-tether-element-attached-top .popover-title::before {
+  position: absolute;
+  top: 0;
+  left: 50%;
+  display: block;
+  width: 20px;
+  margin-left: -10px;
+  content: "";
+  border-bottom: 1px solid #f7f7f7;
+}
+
+.popover.popover-left, .popover.bs-tether-element-attached-right {
+  margin-left: -10px;
+}
+
+.popover.popover-left::before, .popover.popover-left::after, .popover.bs-tether-element-attached-right::before, .popover.bs-tether-element-attached-right::after {
+  top: 50%;
+  border-right-width: 0;
+}
+
+.popover.popover-left::before, .popover.bs-tether-element-attached-right::before {
+  right: -11px;
+  margin-top: -11px;
+  border-left-color: rgba(0, 0, 0, 0.25);
+}
+
+.popover.popover-left::after, .popover.bs-tether-element-attached-right::after {
+  right: -10px;
+  margin-top: -10px;
+  border-left-color: #fff;
+}
+
+.popover-title {
+  padding: 8px 14px;
+  margin: 0;
+  font-size: 1rem;
+  background-color: #f7f7f7;
+  border-bottom: 1px solid #ebebeb;
+  border-radius: 0.2375rem 0.2375rem 0 0;
+}
+
+.popover-title:empty {
+  display: none;
+}
+
+.popover-content {
+  padding: 9px 14px;
+}
+
+.popover::before,
+.popover::after {
+  position: absolute;
+  display: block;
+  width: 0;
+  height: 0;
+  border-color: transparent;
+  border-style: solid;
+}
+
+.popover::before {
+  content: "";
+  border-width: 11px;
+}
+
+.popover::after {
+  content: "";
+  border-width: 10px;
+}
+
+.carousel {
+  position: relative;
+}
+
+.carousel-inner {
+  position: relative;
+  width: 100%;
+  overflow: hidden;
+}
+
+.carousel-inner > .carousel-item {
+  position: relative;
+  display: none;
+  -webkit-transition: .6s ease-in-out left;
+  -o-transition: .6s ease-in-out left;
+  transition: .6s ease-in-out left;
+}
+
+.carousel-inner > .carousel-item > img,
+.carousel-inner > .carousel-item > a > img {
+  line-height: 1;
+}
+
+@media all and (transform-3d), (-webkit-transform-3d) {
+  .carousel-inner > .carousel-item {
+    -webkit-transition: -webkit-transform .6s ease-in-out;
+    transition: -webkit-transform .6s ease-in-out;
+    -o-transition: -o-transform .6s ease-in-out;
+    transition: transform .6s ease-in-out;
+    transition: transform .6s ease-in-out, -webkit-transform .6s ease-in-out, -o-transform .6s ease-in-out;
+    -webkit-backface-visibility: hidden;
+            backface-visibility: hidden;
+    -webkit-perspective: 1000px;
+            perspective: 1000px;
+  }
+  .carousel-inner > .carousel-item.next, .carousel-inner > .carousel-item.active.right {
+    left: 0;
+    -webkit-transform: translate3d(100%, 0, 0);
+            transform: translate3d(100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.prev, .carousel-inner > .carousel-item.active.left {
+    left: 0;
+    -webkit-transform: translate3d(-100%, 0, 0);
+            transform: translate3d(-100%, 0, 0);
+  }
+  .carousel-inner > .carousel-item.next.left, .carousel-inner > .carousel-item.prev.right, .carousel-inner > .carousel-item.active {
+    left: 0;
+    -webkit-transform: translate3d(0, 0, 0);
+            transform: translate3d(0, 0, 0);
+  }
+}
+
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  display: block;
+}
+
+.carousel-inner > .active {
+  left: 0;
+}
+
+.carousel-inner > .next,
+.carousel-inner > .prev {
+  position: absolute;
+  top: 0;
+  width: 100%;
+}
+
+.carousel-inner > .next {
+  left: 100%;
+}
+
+.carousel-inner > .prev {
+  left: -100%;
+}
+
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+  left: 0;
+}
+
+.carousel-inner > .active.left {
+  left: -100%;
+}
+
+.carousel-inner > .active.right {
+  left: 100%;
+}
+
+.carousel-control {
+  position: absolute;
+  top: 0;
+  bottom: 0;
+  left: 0;
+  width: 15%;
+  font-size: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+  opacity: 0.5;
+}
+
+.carousel-control.left {
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+
+.carousel-control.right {
+  right: 0;
+  left: auto;
+  background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));
+  background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+  background-repeat: repeat-x;
+  filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+
+.carousel-control:focus, .carousel-control:hover {
+  color: #fff;
+  text-decoration: none;
+  outline: 0;
+  opacity: .9;
+}
+
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+  position: absolute;
+  top: 50%;
+  z-index: 5;
+  display: inline-block;
+  width: 20px;
+  height: 20px;
+  margin-top: -10px;
+  font-family: serif;
+  line-height: 1;
+}
+
+.carousel-control .icon-prev {
+  left: 50%;
+  margin-left: -10px;
+}
+
+.carousel-control .icon-next {
+  right: 50%;
+  margin-right: -10px;
+}
+
+.carousel-control .icon-prev::before {
+  content: "\2039";
+}
+
+.carousel-control .icon-next::before {
+  content: "\203a";
+}
+
+.carousel-indicators {
+  position: absolute;
+  bottom: 10px;
+  left: 50%;
+  z-index: 15;
+  width: 60%;
+  padding-left: 0;
+  margin-left: -30%;
+  text-align: center;
+  list-style: none;
+}
+
+.carousel-indicators li {
+  display: inline-block;
+  width: 10px;
+  height: 10px;
+  margin: 1px;
+  text-indent: -999px;
+  cursor: pointer;
+  background-color: transparent;
+  border: 1px solid #fff;
+  border-radius: 10px;
+}
+
+.carousel-indicators .active {
+  width: 12px;
+  height: 12px;
+  margin: 0;
+  background-color: #fff;
+}
+
+.carousel-caption {
+  position: absolute;
+  right: 15%;
+  bottom: 20px;
+  left: 15%;
+  z-index: 10;
+  padding-top: 20px;
+  padding-bottom: 20px;
+  color: #fff;
+  text-align: center;
+  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+
+.carousel-caption .btn {
+  text-shadow: none;
+}
+
+@media (min-width: 576px) {
+  .carousel-control .icon-prev,
+  .carousel-control .icon-next {
+    width: 30px;
+    height: 30px;
+    margin-top: -15px;
+    font-size: 30px;
+  }
+  .carousel-control .icon-prev {
+    margin-left: -15px;
+  }
+  .carousel-control .icon-next {
+    margin-right: -15px;
+  }
+  .carousel-caption {
+    right: 20%;
+    left: 20%;
+    padding-bottom: 30px;
+  }
+  .carousel-indicators {
+    bottom: 20px;
+  }
+}
+
+.align-baseline {
+  vertical-align: baseline !important;
+}
+
+.align-top {
+  vertical-align: top !important;
+}
+
+.align-middle {
+  vertical-align: middle !important;
+}
+
+.align-bottom {
+  vertical-align: bottom !important;
+}
+
+.align-text-bottom {
+  vertical-align: text-bottom !important;
+}
+
+.align-text-top {
+  vertical-align: text-top !important;
+}
+
+.bg-faded {
+  background-color: #f7f7f9;
+}
+
+.bg-primary {
+  background-color: #0275d8 !important;
+}
+
+a.bg-primary:focus, a.bg-primary:hover {
+  background-color: #025aa5 !important;
+}
+
+.bg-success {
+  background-color: #5cb85c !important;
+}
+
+a.bg-success:focus, a.bg-success:hover {
+  background-color: #449d44 !important;
+}
+
+.bg-info {
+  background-color: #5bc0de !important;
+}
+
+a.bg-info:focus, a.bg-info:hover {
+  background-color: #31b0d5 !important;
+}
+
+.bg-warning {
+  background-color: #f0ad4e !important;
+}
+
+a.bg-warning:focus, a.bg-warning:hover {
+  background-color: #ec971f !important;
+}
+
+.bg-danger {
+  background-color: #d9534f !important;
+}
+
+a.bg-danger:focus, a.bg-danger:hover {
+  background-color: #c9302c !important;
+}
+
+.bg-inverse {
+  background-color: #373a3c !important;
+}
+
+a.bg-inverse:focus, a.bg-inverse:hover {
+  background-color: #1f2021 !important;
+}
+
+.rounded {
+  border-radius: 0.25rem;
+}
+
+.rounded-top {
+  border-top-right-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-right {
+  border-bottom-right-radius: 0.25rem;
+  border-top-right-radius: 0.25rem;
+}
+
+.rounded-bottom {
+  border-bottom-right-radius: 0.25rem;
+  border-bottom-left-radius: 0.25rem;
+}
+
+.rounded-left {
+  border-bottom-left-radius: 0.25rem;
+  border-top-left-radius: 0.25rem;
+}
+
+.rounded-circle {
+  border-radius: 50%;
+}
+
+.clearfix::after {
+  content: "";
+  display: table;
+  clear: both;
+}
+
+.d-block {
+  display: block !important;
+}
+
+.d-inline-block {
+  display: inline-block !important;
+}
+
+.d-inline {
+  display: inline !important;
+}
+
+.float-xs-left {
+  float: left !important;
+}
+
+.float-xs-right {
+  float: right !important;
+}
+
+.float-xs-none {
+  float: none !important;
+}
+
+@media (min-width: 576px) {
+  .float-sm-left {
+    float: left !important;
+  }
+  .float-sm-right {
+    float: right !important;
+  }
+  .float-sm-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .float-md-left {
+    float: left !important;
+  }
+  .float-md-right {
+    float: right !important;
+  }
+  .float-md-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .float-lg-left {
+    float: left !important;
+  }
+  .float-lg-right {
+    float: right !important;
+  }
+  .float-lg-none {
+    float: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .float-xl-left {
+    float: left !important;
+  }
+  .float-xl-right {
+    float: right !important;
+  }
+  .float-xl-none {
+    float: none !important;
+  }
+}
+
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+
+.sr-only-focusable:active, .sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
+
+.w-100 {
+  width: 100% !important;
+}
+
+.h-100 {
+  height: 100% !important;
+}
+
+.mx-auto {
+  margin-right: auto !important;
+  margin-left: auto !important;
+}
+
+.m-0 {
+  margin: 0 0 !important;
+}
+
+.mt-0 {
+  margin-top: 0 !important;
+}
+
+.mr-0 {
+  margin-right: 0 !important;
+}
+
+.mb-0 {
+  margin-bottom: 0 !important;
+}
+
+.ml-0 {
+  margin-left: 0 !important;
+}
+
+.mx-0 {
+  margin-right: 0 !important;
+  margin-left: 0 !important;
+}
+
+.my-0 {
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+
+.m-1 {
+  margin: 1rem 1rem !important;
+}
+
+.mt-1 {
+  margin-top: 1rem !important;
+}
+
+.mr-1 {
+  margin-right: 1rem !important;
+}
+
+.mb-1 {
+  margin-bottom: 1rem !important;
+}
+
+.ml-1 {
+  margin-left: 1rem !important;
+}
+
+.mx-1 {
+  margin-right: 1rem !important;
+  margin-left: 1rem !important;
+}
+
+.my-1 {
+  margin-top: 1rem !important;
+  margin-bottom: 1rem !important;
+}
+
+.m-2 {
+  margin: 1.5rem 1.5rem !important;
+}
+
+.mt-2 {
+  margin-top: 1.5rem !important;
+}
+
+.mr-2 {
+  margin-right: 1.5rem !important;
+}
+
+.mb-2 {
+  margin-bottom: 1.5rem !important;
+}
+
+.ml-2 {
+  margin-left: 1.5rem !important;
+}
+
+.mx-2 {
+  margin-right: 1.5rem !important;
+  margin-left: 1.5rem !important;
+}
+
+.my-2 {
+  margin-top: 1.5rem !important;
+  margin-bottom: 1.5rem !important;
+}
+
+.m-3 {
+  margin: 3rem 3rem !important;
+}
+
+.mt-3 {
+  margin-top: 3rem !important;
+}
+
+.mr-3 {
+  margin-right: 3rem !important;
+}
+
+.mb-3 {
+  margin-bottom: 3rem !important;
+}
+
+.ml-3 {
+  margin-left: 3rem !important;
+}
+
+.mx-3 {
+  margin-right: 3rem !important;
+  margin-left: 3rem !important;
+}
+
+.my-3 {
+  margin-top: 3rem !important;
+  margin-bottom: 3rem !important;
+}
+
+.p-0 {
+  padding: 0 0 !important;
+}
+
+.pt-0 {
+  padding-top: 0 !important;
+}
+
+.pr-0 {
+  padding-right: 0 !important;
+}
+
+.pb-0 {
+  padding-bottom: 0 !important;
+}
+
+.pl-0 {
+  padding-left: 0 !important;
+}
+
+.px-0 {
+  padding-right: 0 !important;
+  padding-left: 0 !important;
+}
+
+.py-0 {
+  padding-top: 0 !important;
+  padding-bottom: 0 !important;
+}
+
+.p-1 {
+  padding: 1rem 1rem !important;
+}
+
+.pt-1 {
+  padding-top: 1rem !important;
+}
+
+.pr-1 {
+  padding-right: 1rem !important;
+}
+
+.pb-1 {
+  padding-bottom: 1rem !important;
+}
+
+.pl-1 {
+  padding-left: 1rem !important;
+}
+
+.px-1 {
+  padding-right: 1rem !important;
+  padding-left: 1rem !important;
+}
+
+.py-1 {
+  padding-top: 1rem !important;
+  padding-bottom: 1rem !important;
+}
+
+.p-2 {
+  padding: 1.5rem 1.5rem !important;
+}
+
+.pt-2 {
+  padding-top: 1.5rem !important;
+}
+
+.pr-2 {
+  padding-right: 1.5rem !important;
+}
+
+.pb-2 {
+  padding-bottom: 1.5rem !important;
+}
+
+.pl-2 {
+  padding-left: 1.5rem !important;
+}
+
+.px-2 {
+  padding-right: 1.5rem !important;
+  padding-left: 1.5rem !important;
+}
+
+.py-2 {
+  padding-top: 1.5rem !important;
+  padding-bottom: 1.5rem !important;
+}
+
+.p-3 {
+  padding: 3rem 3rem !important;
+}
+
+.pt-3 {
+  padding-top: 3rem !important;
+}
+
+.pr-3 {
+  padding-right: 3rem !important;
+}
+
+.pb-3 {
+  padding-bottom: 3rem !important;
+}
+
+.pl-3 {
+  padding-left: 3rem !important;
+}
+
+.px-3 {
+  padding-right: 3rem !important;
+  padding-left: 3rem !important;
+}
+
+.py-3 {
+  padding-top: 3rem !important;
+  padding-bottom: 3rem !important;
+}
+
+.pos-f-t {
+  position: fixed;
+  top: 0;
+  right: 0;
+  left: 0;
+  z-index: 1030;
+}
+
+.text-justify {
+  text-align: justify !important;
+}
+
+.text-nowrap {
+  white-space: nowrap !important;
+}
+
+.text-truncate {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
+}
+
+.text-xs-left {
+  text-align: left !important;
+}
+
+.text-xs-right {
+  text-align: right !important;
+}
+
+.text-xs-center {
+  text-align: center !important;
+}
+
+@media (min-width: 576px) {
+  .text-sm-left {
+    text-align: left !important;
+  }
+  .text-sm-right {
+    text-align: right !important;
+  }
+  .text-sm-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .text-md-left {
+    text-align: left !important;
+  }
+  .text-md-right {
+    text-align: right !important;
+  }
+  .text-md-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .text-lg-left {
+    text-align: left !important;
+  }
+  .text-lg-right {
+    text-align: right !important;
+  }
+  .text-lg-center {
+    text-align: center !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .text-xl-left {
+    text-align: left !important;
+  }
+  .text-xl-right {
+    text-align: right !important;
+  }
+  .text-xl-center {
+    text-align: center !important;
+  }
+}
+
+.text-lowercase {
+  text-transform: lowercase !important;
+}
+
+.text-uppercase {
+  text-transform: uppercase !important;
+}
+
+.text-capitalize {
+  text-transform: capitalize !important;
+}
+
+.font-weight-normal {
+  font-weight: normal;
+}
+
+.font-weight-bold {
+  font-weight: bold;
+}
+
+.font-italic {
+  font-style: italic;
+}
+
+.text-white {
+  color: #fff !important;
+}
+
+.text-muted {
+  color: #818a91 !important;
+}
+
+a.text-muted:focus, a.text-muted:hover {
+  color: #687077 !important;
+}
+
+.text-primary {
+  color: #0275d8 !important;
+}
+
+a.text-primary:focus, a.text-primary:hover {
+  color: #025aa5 !important;
+}
+
+.text-success {
+  color: #5cb85c !important;
+}
+
+a.text-success:focus, a.text-success:hover {
+  color: #449d44 !important;
+}
+
+.text-info {
+  color: #5bc0de !important;
+}
+
+a.text-info:focus, a.text-info:hover {
+  color: #31b0d5 !important;
+}
+
+.text-warning {
+  color: #f0ad4e !important;
+}
+
+a.text-warning:focus, a.text-warning:hover {
+  color: #ec971f !important;
+}
+
+.text-danger {
+  color: #d9534f !important;
+}
+
+a.text-danger:focus, a.text-danger:hover {
+  color: #c9302c !important;
+}
+
+.text-gray-dark {
+  color: #373a3c !important;
+}
+
+a.text-gray-dark:focus, a.text-gray-dark:hover {
+  color: #1f2021 !important;
+}
+
+.text-hide {
+  font: 0/0 a;
+  color: transparent;
+  text-shadow: none;
+  background-color: transparent;
+  border: 0;
+}
+
+.invisible {
+  visibility: hidden !important;
+}
+
+.hidden-xs-up {
+  display: none !important;
+}
+
+@media (max-width: 575px) {
+  .hidden-xs-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 576px) {
+  .hidden-sm-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 767px) {
+  .hidden-sm-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 768px) {
+  .hidden-md-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 991px) {
+  .hidden-md-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 992px) {
+  .hidden-lg-up {
+    display: none !important;
+  }
+}
+
+@media (max-width: 1199px) {
+  .hidden-lg-down {
+    display: none !important;
+  }
+}
+
+@media (min-width: 1200px) {
+  .hidden-xl-up {
+    display: none !important;
+  }
+}
+
+.hidden-xl-down {
+  display: none !important;
+}
+
+.visible-print-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-block {
+    display: block !important;
+  }
+}
+
+.visible-print-inline {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline {
+    display: inline !important;
+  }
+}
+
+.visible-print-inline-block {
+  display: none !important;
+}
+
+@media print {
+  .visible-print-inline-block {
+    display: inline-block !important;
+  }
+}
+
+@media print {
+  .hidden-print {
+    display: none !important;
+  }
+}
+/*# sourceMappingURL=bootstrap.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
new file mode 100644
index 0000000..02701a5
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/bootstrap.scss","../../scss/_custom.scss","../../scss/_tobago.scss","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_hover.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
new file mode 100644
index 0000000..5553f7e
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2016 The Bootstrap Authors
+ * Copyright 2011-2016 Twitter, Inc.
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */.tobago-box-header{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-webkit-justify-content:space-between;-ms-flex-pack:justify;justify-content:space-between;-webkit-align-content:center;-ms-flex-line-pack:center;align-content:center}.tobago-button>img{margin-top:-1px;margin-bottom:-1px}.tobago-collapsed.tobago-box .card-block,.tobago-collapsed.tobago-panel,.tobago-collapsed.tobago-section .tobago-section-content{display:none}.tobago-d [...]
+/*# sourceMappingURL=bootstrap.min.css.map */
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
new file mode 100644
index 0000000..12af8fc
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../../scss/_tobago.scss","dist/css/bootstrap.css","../../scss/_normalize.scss","bootstrap.css","../../scss/_print.scss","../../scss/_reboot.scss","../../scss/_variables.scss","../../scss/mixins/_tab-focus.scss","../../scss/_type.scss","../../scss/mixins/_lists.scss","../../scss/_images.scss","../../scss/mixins/_image.scss","../../scss/mixins/_border-radius.scss","../../scss/_code.scss","../../scss/_grid.scss","../../scss/mixins/_grid.scss","../../scss/mixins/_cle [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js
new file mode 100644
index 0000000..0a37e60
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js
@@ -0,0 +1,3430 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+
+if (typeof jQuery === 'undefined') {
+  throw new Error('Bootstrap\'s JavaScript requires jQuery')
+}
+
++function ($) {
+  var version = $.fn.jquery.split(' ')[0].split('.')
+  if ((version[0] < 2 && version[1] < 9) || (version[0] == 1 && version[1] == 9 && version[2] < 1) || (version[0] >= 4)) {
+    throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0')
+  }
+}(jQuery);
+
+
++function () {
+
+var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
+
+var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) [...]
+
+function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): util.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Util = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Private TransitionEnd Helpers
+   * ------------------------------------------------------------------------
+   */
+
+  var transition = false;
+
+  var MAX_UID = 1000000;
+
+  var TransitionEndEvent = {
+    WebkitTransition: 'webkitTransitionEnd',
+    MozTransition: 'transitionend',
+    OTransition: 'oTransitionEnd otransitionend',
+    transition: 'transitionend'
+  };
+
+  // shoutout AngusCroll (https://goo.gl/pxwQGp)
+  function toType(obj) {
+    return {}.toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
+  }
+
+  function isElement(obj) {
+    return (obj[0] || obj).nodeType;
+  }
+
+  function getSpecialTransitionEndEvent() {
+    return {
+      bindType: transition.end,
+      delegateType: transition.end,
+      handle: function handle(event) {
+        if ($(event.target).is(this)) {
+          return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params
+        }
+        return undefined;
+      }
+    };
+  }
+
+  function transitionEndTest() {
+    if (window.QUnit) {
+      return false;
+    }
+
+    var el = document.createElement('bootstrap');
+
+    for (var name in TransitionEndEvent) {
+      if (el.style[name] !== undefined) {
+        return { end: TransitionEndEvent[name] };
+      }
+    }
+
+    return false;
+  }
+
+  function transitionEndEmulator(duration) {
+    var _this = this;
+
+    var called = false;
+
+    $(this).one(Util.TRANSITION_END, function () {
+      called = true;
+    });
+
+    setTimeout(function () {
+      if (!called) {
+        Util.triggerTransitionEnd(_this);
+      }
+    }, duration);
+
+    return this;
+  }
+
+  function setTransitionEndSupport() {
+    transition = transitionEndTest();
+
+    $.fn.emulateTransitionEnd = transitionEndEmulator;
+
+    if (Util.supportsTransitionEnd()) {
+      $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent();
+    }
+  }
+
+  /**
+   * --------------------------------------------------------------------------
+   * Public Util Api
+   * --------------------------------------------------------------------------
+   */
+
+  var Util = {
+
+    TRANSITION_END: 'bsTransitionEnd',
+
+    getUID: function getUID(prefix) {
+      do {
+        /* eslint-disable no-bitwise */
+        prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here
+        /* eslint-enable no-bitwise */
+      } while (document.getElementById(prefix));
+      return prefix;
+    },
+    getSelectorFromElement: function getSelectorFromElement(element) {
+      var selector = element.getAttribute('data-target');
+
+      if (!selector) {
+        selector = element.getAttribute('href') || '';
+        selector = /^#[a-z]/i.test(selector) ? selector : null;
+      }
+
+      return selector;
+    },
+    reflow: function reflow(element) {
+      new Function('bs', 'return bs')(element.offsetHeight);
+    },
+    triggerTransitionEnd: function triggerTransitionEnd(element) {
+      $(element).trigger(transition.end);
+    },
+    supportsTransitionEnd: function supportsTransitionEnd() {
+      return Boolean(transition);
+    },
+    typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) {
+      for (var property in configTypes) {
+        if (configTypes.hasOwnProperty(property)) {
+          var expectedTypes = configTypes[property];
+          var value = config[property];
+          var valueType = void 0;
+
+          if (value && isElement(value)) {
+            valueType = 'element';
+          } else {
+            valueType = toType(value);
+          }
+
+          if (!new RegExp(expectedTypes).test(valueType)) {
+            throw new Error(componentName.toUpperCase() + ': ' + ('Option "' + property + '" provided type "' + valueType + '" ') + ('but expected type "' + expectedTypes + '".'));
+          }
+        }
+      }
+    }
+  };
+
+  setTransitionEndSupport();
+
+  return Util;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): alert.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Alert = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'alert';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.alert';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Selector = {
+    DISMISS: '[data-dismiss="alert"]'
+  };
+
+  var Event = {
+    CLOSE: 'close' + EVENT_KEY,
+    CLOSED: 'closed' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    ALERT: 'alert',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Alert = function () {
+    function Alert(element) {
+      _classCallCheck(this, Alert);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Alert.prototype.close = function close(element) {
+      element = element || this._element;
+
+      var rootElement = this._getRootElement(element);
+      var customEvent = this._triggerCloseEvent(rootElement);
+
+      if (customEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._removeElement(rootElement);
+    };
+
+    Alert.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Alert.prototype._getRootElement = function _getRootElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      var parent = false;
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      if (!parent) {
+        parent = $(element).closest('.' + ClassName.ALERT)[0];
+      }
+
+      return parent;
+    };
+
+    Alert.prototype._triggerCloseEvent = function _triggerCloseEvent(element) {
+      var closeEvent = $.Event(Event.CLOSE);
+
+      $(element).trigger(closeEvent);
+      return closeEvent;
+    };
+
+    Alert.prototype._removeElement = function _removeElement(element) {
+      $(element).removeClass(ClassName.IN);
+
+      if (!Util.supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) {
+        this._destroyElement(element);
+        return;
+      }
+
+      $(element).one(Util.TRANSITION_END, $.proxy(this._destroyElement, this, element)).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Alert.prototype._destroyElement = function _destroyElement(element) {
+      $(element).detach().trigger(Event.CLOSED).remove();
+    };
+
+    // static
+
+    Alert._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $element = $(this);
+        var data = $element.data(DATA_KEY);
+
+        if (!data) {
+          data = new Alert(this);
+          $element.data(DATA_KEY, data);
+        }
+
+        if (config === 'close') {
+          data[config](this);
+        }
+      });
+    };
+
+    Alert._handleDismiss = function _handleDismiss(alertInstance) {
+      return function (event) {
+        if (event) {
+          event.preventDefault();
+        }
+
+        alertInstance.close(this);
+      };
+    };
+
+    _createClass(Alert, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Alert;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert()));
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Alert._jQueryInterface;
+  $.fn[NAME].Constructor = Alert;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Alert._jQueryInterface;
+  };
+
+  return Alert;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): button.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Button = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'button';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.button';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var ClassName = {
+    ACTIVE: 'active',
+    BUTTON: 'btn',
+    FOCUS: 'focus'
+  };
+
+  var Selector = {
+    DATA_TOGGLE_CARROT: '[data-toggle^="button"]',
+    DATA_TOGGLE: '[data-toggle="buttons"]',
+    INPUT: 'input',
+    ACTIVE: '.active',
+    BUTTON: '.btn'
+  };
+
+  var Event = {
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    FOCUS_BLUR_DATA_API: 'focus' + EVENT_KEY + DATA_API_KEY + ' ' + ('blur' + EVENT_KEY + DATA_API_KEY)
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Button = function () {
+    function Button(element) {
+      _classCallCheck(this, Button);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Button.prototype.toggle = function toggle() {
+      var triggerChangeEvent = true;
+      var rootElement = $(this._element).closest(Selector.DATA_TOGGLE)[0];
+
+      if (rootElement) {
+        var input = $(this._element).find(Selector.INPUT)[0];
+
+        if (input) {
+          if (input.type === 'radio') {
+            if (input.checked && $(this._element).hasClass(ClassName.ACTIVE)) {
+              triggerChangeEvent = false;
+            } else {
+              var activeElement = $(rootElement).find(Selector.ACTIVE)[0];
+
+              if (activeElement) {
+                $(activeElement).removeClass(ClassName.ACTIVE);
+              }
+            }
+          }
+
+          if (triggerChangeEvent) {
+            input.checked = !$(this._element).hasClass(ClassName.ACTIVE);
+            $(this._element).trigger('change');
+          }
+
+          input.focus();
+        }
+      } else {
+        this._element.setAttribute('aria-pressed', !$(this._element).hasClass(ClassName.ACTIVE));
+      }
+
+      if (triggerChangeEvent) {
+        $(this._element).toggleClass(ClassName.ACTIVE);
+      }
+    };
+
+    Button.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // static
+
+    Button._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          data = new Button(this);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (config === 'toggle') {
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Button, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Button;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    event.preventDefault();
+
+    var button = event.target;
+
+    if (!$(button).hasClass(ClassName.BUTTON)) {
+      button = $(button).closest(Selector.BUTTON);
+    }
+
+    Button._jQueryInterface.call($(button), 'toggle');
+  }).on(Event.FOCUS_BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, function (event) {
+    var button = $(event.target).closest(Selector.BUTTON)[0];
+    $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type));
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Button._jQueryInterface;
+  $.fn[NAME].Constructor = Button;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Button._jQueryInterface;
+  };
+
+  return Button;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): carousel.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Carousel = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'carousel';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.carousel';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+  var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key
+  var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key
+
+  var Default = {
+    interval: 5000,
+    keyboard: true,
+    slide: false,
+    pause: 'hover',
+    wrap: true
+  };
+
+  var DefaultType = {
+    interval: '(number|boolean)',
+    keyboard: 'boolean',
+    slide: '(boolean|string)',
+    pause: '(string|boolean)',
+    wrap: 'boolean'
+  };
+
+  var Direction = {
+    NEXT: 'next',
+    PREVIOUS: 'prev'
+  };
+
+  var Event = {
+    SLIDE: 'slide' + EVENT_KEY,
+    SLID: 'slid' + EVENT_KEY,
+    KEYDOWN: 'keydown' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    CAROUSEL: 'carousel',
+    ACTIVE: 'active',
+    SLIDE: 'slide',
+    RIGHT: 'right',
+    LEFT: 'left',
+    ITEM: 'carousel-item'
+  };
+
+  var Selector = {
+    ACTIVE: '.active',
+    ACTIVE_ITEM: '.active.carousel-item',
+    ITEM: '.carousel-item',
+    NEXT_PREV: '.next, .prev',
+    INDICATORS: '.carousel-indicators',
+    DATA_SLIDE: '[data-slide], [data-slide-to]',
+    DATA_RIDE: '[data-ride="carousel"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Carousel = function () {
+    function Carousel(element, config) {
+      _classCallCheck(this, Carousel);
+
+      this._items = null;
+      this._interval = null;
+      this._activeElement = null;
+
+      this._isPaused = false;
+      this._isSliding = false;
+
+      this._config = this._getConfig(config);
+      this._element = $(element)[0];
+      this._indicatorsElement = $(this._element).find(Selector.INDICATORS)[0];
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Carousel.prototype.next = function next() {
+      if (!this._isSliding) {
+        this._slide(Direction.NEXT);
+      }
+    };
+
+    Carousel.prototype.nextWhenVisible = function nextWhenVisible() {
+      // Don't call next when the page isn't visible
+      if (!document.hidden) {
+        this.next();
+      }
+    };
+
+    Carousel.prototype.prev = function prev() {
+      if (!this._isSliding) {
+        this._slide(Direction.PREVIOUS);
+      }
+    };
+
+    Carousel.prototype.pause = function pause(event) {
+      if (!event) {
+        this._isPaused = true;
+      }
+
+      if ($(this._element).find(Selector.NEXT_PREV)[0] && Util.supportsTransitionEnd()) {
+        Util.triggerTransitionEnd(this._element);
+        this.cycle(true);
+      }
+
+      clearInterval(this._interval);
+      this._interval = null;
+    };
+
+    Carousel.prototype.cycle = function cycle(event) {
+      if (!event) {
+        this._isPaused = false;
+      }
+
+      if (this._interval) {
+        clearInterval(this._interval);
+        this._interval = null;
+      }
+
+      if (this._config.interval && !this._isPaused) {
+        this._interval = setInterval($.proxy(document.visibilityState ? this.nextWhenVisible : this.next, this), this._config.interval);
+      }
+    };
+
+    Carousel.prototype.to = function to(index) {
+      var _this2 = this;
+
+      this._activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+
+      var activeIndex = this._getItemIndex(this._activeElement);
+
+      if (index > this._items.length - 1 || index < 0) {
+        return;
+      }
+
+      if (this._isSliding) {
+        $(this._element).one(Event.SLID, function () {
+          return _this2.to(index);
+        });
+        return;
+      }
+
+      if (activeIndex === index) {
+        this.pause();
+        this.cycle();
+        return;
+      }
+
+      var direction = index > activeIndex ? Direction.NEXT : Direction.PREVIOUS;
+
+      this._slide(direction, this._items[index]);
+    };
+
+    Carousel.prototype.dispose = function dispose() {
+      $(this._element).off(EVENT_KEY);
+      $.removeData(this._element, DATA_KEY);
+
+      this._items = null;
+      this._config = null;
+      this._element = null;
+      this._interval = null;
+      this._isPaused = null;
+      this._isSliding = null;
+      this._activeElement = null;
+      this._indicatorsElement = null;
+    };
+
+    // private
+
+    Carousel.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Carousel.prototype._addEventListeners = function _addEventListeners() {
+      if (this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN, $.proxy(this._keydown, this));
+      }
+
+      if (this._config.pause === 'hover' && !('ontouchstart' in document.documentElement)) {
+        $(this._element).on(Event.MOUSEENTER, $.proxy(this.pause, this)).on(Event.MOUSELEAVE, $.proxy(this.cycle, this));
+      }
+    };
+
+    Carousel.prototype._keydown = function _keydown(event) {
+      event.preventDefault();
+
+      if (/input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      switch (event.which) {
+        case ARROW_LEFT_KEYCODE:
+          this.prev();
+          break;
+        case ARROW_RIGHT_KEYCODE:
+          this.next();
+          break;
+        default:
+          return;
+      }
+    };
+
+    Carousel.prototype._getItemIndex = function _getItemIndex(element) {
+      this._items = $.makeArray($(element).parent().find(Selector.ITEM));
+      return this._items.indexOf(element);
+    };
+
+    Carousel.prototype._getItemByDirection = function _getItemByDirection(direction, activeElement) {
+      var isNextDirection = direction === Direction.NEXT;
+      var isPrevDirection = direction === Direction.PREVIOUS;
+      var activeIndex = this._getItemIndex(activeElement);
+      var lastItemIndex = this._items.length - 1;
+      var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex;
+
+      if (isGoingToWrap && !this._config.wrap) {
+        return activeElement;
+      }
+
+      var delta = direction === Direction.PREVIOUS ? -1 : 1;
+      var itemIndex = (activeIndex + delta) % this._items.length;
+
+      return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex];
+    };
+
+    Carousel.prototype._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, directionalClassname) {
+      var slideEvent = $.Event(Event.SLIDE, {
+        relatedTarget: relatedTarget,
+        direction: directionalClassname
+      });
+
+      $(this._element).trigger(slideEvent);
+
+      return slideEvent;
+    };
+
+    Carousel.prototype._setActiveIndicatorElement = function _setActiveIndicatorElement(element) {
+      if (this._indicatorsElement) {
+        $(this._indicatorsElement).find(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+
+        var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)];
+
+        if (nextIndicator) {
+          $(nextIndicator).addClass(ClassName.ACTIVE);
+        }
+      }
+    };
+
+    Carousel.prototype._slide = function _slide(direction, element) {
+      var _this3 = this;
+
+      var activeElement = $(this._element).find(Selector.ACTIVE_ITEM)[0];
+      var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement);
+
+      var isCycling = Boolean(this._interval);
+
+      var directionalClassName = direction === Direction.NEXT ? ClassName.LEFT : ClassName.RIGHT;
+
+      if (nextElement && $(nextElement).hasClass(ClassName.ACTIVE)) {
+        this._isSliding = false;
+        return;
+      }
+
+      var slideEvent = this._triggerSlideEvent(nextElement, directionalClassName);
+      if (slideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (!activeElement || !nextElement) {
+        // some weirdness is happening, so we bail
+        return;
+      }
+
+      this._isSliding = true;
+
+      if (isCycling) {
+        this.pause();
+      }
+
+      this._setActiveIndicatorElement(nextElement);
+
+      var slidEvent = $.Event(Event.SLID, {
+        relatedTarget: nextElement,
+        direction: directionalClassName
+      });
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.SLIDE)) {
+
+        $(nextElement).addClass(direction);
+
+        Util.reflow(nextElement);
+
+        $(activeElement).addClass(directionalClassName);
+        $(nextElement).addClass(directionalClassName);
+
+        $(activeElement).one(Util.TRANSITION_END, function () {
+          $(nextElement).removeClass(directionalClassName).removeClass(direction);
+
+          $(nextElement).addClass(ClassName.ACTIVE);
+
+          $(activeElement).removeClass(ClassName.ACTIVE).removeClass(direction).removeClass(directionalClassName);
+
+          _this3._isSliding = false;
+
+          setTimeout(function () {
+            return $(_this3._element).trigger(slidEvent);
+          }, 0);
+        }).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        $(activeElement).removeClass(ClassName.ACTIVE);
+        $(nextElement).addClass(ClassName.ACTIVE);
+
+        this._isSliding = false;
+        $(this._element).trigger(slidEvent);
+      }
+
+      if (isCycling) {
+        this.cycle();
+      }
+    };
+
+    // static
+
+    Carousel._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Default, $(this).data());
+
+        if ((typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object') {
+          $.extend(_config, config);
+        }
+
+        var action = typeof config === 'string' ? config : _config.slide;
+
+        if (!data) {
+          data = new Carousel(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'number') {
+          data.to(config);
+        } else if (typeof action === 'string') {
+          if (data[action] === undefined) {
+            throw new Error('No method named "' + action + '"');
+          }
+          data[action]();
+        } else if (_config.interval) {
+          data.pause();
+          data.cycle();
+        }
+      });
+    };
+
+    Carousel._dataApiClickHandler = function _dataApiClickHandler(event) {
+      var selector = Util.getSelectorFromElement(this);
+
+      if (!selector) {
+        return;
+      }
+
+      var target = $(selector)[0];
+
+      if (!target || !$(target).hasClass(ClassName.CAROUSEL)) {
+        return;
+      }
+
+      var config = $.extend({}, $(target).data(), $(this).data());
+      var slideIndex = this.getAttribute('data-slide-to');
+
+      if (slideIndex) {
+        config.interval = false;
+      }
+
+      Carousel._jQueryInterface.call($(target), config);
+
+      if (slideIndex) {
+        $(target).data(DATA_KEY).to(slideIndex);
+      }
+
+      event.preventDefault();
+    };
+
+    _createClass(Carousel, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Carousel;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_SLIDE, Carousel._dataApiClickHandler);
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    $(Selector.DATA_RIDE).each(function () {
+      var $carousel = $(this);
+      Carousel._jQueryInterface.call($carousel, $carousel.data());
+    });
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Carousel._jQueryInterface;
+  $.fn[NAME].Constructor = Carousel;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Carousel._jQueryInterface;
+  };
+
+  return Carousel;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): collapse.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Collapse = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'collapse';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.collapse';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 600;
+
+  var Default = {
+    toggle: true,
+    parent: ''
+  };
+
+  var DefaultType = {
+    toggle: 'boolean',
+    parent: 'string'
+  };
+
+  var Event = {
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    IN: 'in',
+    COLLAPSE: 'collapse',
+    COLLAPSING: 'collapsing',
+    COLLAPSED: 'collapsed'
+  };
+
+  var Dimension = {
+    WIDTH: 'width',
+    HEIGHT: 'height'
+  };
+
+  var Selector = {
+    ACTIVES: '.card > .in, .card > .collapsing',
+    DATA_TOGGLE: '[data-toggle="collapse"]'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Collapse = function () {
+    function Collapse(element, config) {
+      _classCallCheck(this, Collapse);
+
+      this._isTransitioning = false;
+      this._element = element;
+      this._config = this._getConfig(config);
+      this._triggerArray = $.makeArray($('[data-toggle="collapse"][href="#' + element.id + '"],' + ('[data-toggle="collapse"][data-target="#' + element.id + '"]')));
+
+      this._parent = this._config.parent ? this._getParent() : null;
+
+      if (!this._config.parent) {
+        this._addAriaAndCollapsedClass(this._element, this._triggerArray);
+      }
+
+      if (this._config.toggle) {
+        this.toggle();
+      }
+    }
+
+    // getters
+
+    // public
+
+    Collapse.prototype.toggle = function toggle() {
+      if ($(this._element).hasClass(ClassName.IN)) {
+        this.hide();
+      } else {
+        this.show();
+      }
+    };
+
+    Collapse.prototype.show = function show() {
+      var _this4 = this;
+
+      if (this._isTransitioning || $(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var actives = void 0;
+      var activesData = void 0;
+
+      if (this._parent) {
+        actives = $.makeArray($(Selector.ACTIVES));
+        if (!actives.length) {
+          actives = null;
+        }
+      }
+
+      if (actives) {
+        activesData = $(actives).data(DATA_KEY);
+        if (activesData && activesData._isTransitioning) {
+          return;
+        }
+      }
+
+      var startEvent = $.Event(Event.SHOW);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (actives) {
+        Collapse._jQueryInterface.call($(actives), 'hide');
+        if (!activesData) {
+          $(actives).data(DATA_KEY, null);
+        }
+      }
+
+      var dimension = this._getDimension();
+
+      $(this._element).removeClass(ClassName.COLLAPSE).addClass(ClassName.COLLAPSING);
+
+      this._element.style[dimension] = 0;
+      this._element.setAttribute('aria-expanded', true);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).removeClass(ClassName.COLLAPSED).attr('aria-expanded', true);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        $(_this4._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).addClass(ClassName.IN);
+
+        _this4._element.style[dimension] = '';
+
+        _this4.setTransitioning(false);
+
+        $(_this4._element).trigger(Event.SHOWN);
+      };
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1);
+      var scrollSize = 'scroll' + capitalizedDimension;
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+
+      this._element.style[dimension] = this._element[scrollSize] + 'px';
+    };
+
+    Collapse.prototype.hide = function hide() {
+      var _this5 = this;
+
+      if (this._isTransitioning || !$(this._element).hasClass(ClassName.IN)) {
+        return;
+      }
+
+      var startEvent = $.Event(Event.HIDE);
+      $(this._element).trigger(startEvent);
+      if (startEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      var dimension = this._getDimension();
+      var offsetDimension = dimension === Dimension.WIDTH ? 'offsetWidth' : 'offsetHeight';
+
+      this._element.style[dimension] = this._element[offsetDimension] + 'px';
+
+      Util.reflow(this._element);
+
+      $(this._element).addClass(ClassName.COLLAPSING).removeClass(ClassName.COLLAPSE).removeClass(ClassName.IN);
+
+      this._element.setAttribute('aria-expanded', false);
+
+      if (this._triggerArray.length) {
+        $(this._triggerArray).addClass(ClassName.COLLAPSED).attr('aria-expanded', false);
+      }
+
+      this.setTransitioning(true);
+
+      var complete = function complete() {
+        _this5.setTransitioning(false);
+        $(_this5._element).removeClass(ClassName.COLLAPSING).addClass(ClassName.COLLAPSE).trigger(Event.HIDDEN);
+      };
+
+      this._element.style[dimension] = '';
+
+      if (!Util.supportsTransitionEnd()) {
+        complete();
+        return;
+      }
+
+      $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+    };
+
+    Collapse.prototype.setTransitioning = function setTransitioning(isTransitioning) {
+      this._isTransitioning = isTransitioning;
+    };
+
+    Collapse.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      this._config = null;
+      this._parent = null;
+      this._element = null;
+      this._triggerArray = null;
+      this._isTransitioning = null;
+    };
+
+    // private
+
+    Collapse.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      config.toggle = Boolean(config.toggle); // coerce string values
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Collapse.prototype._getDimension = function _getDimension() {
+      var hasWidth = $(this._element).hasClass(Dimension.WIDTH);
+      return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT;
+    };
+
+    Collapse.prototype._getParent = function _getParent() {
+      var _this6 = this;
+
+      var parent = $(this._config.parent)[0];
+      var selector = '[data-toggle="collapse"][data-parent="' + this._config.parent + '"]';
+
+      $(parent).find(selector).each(function (i, element) {
+        _this6._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]);
+      });
+
+      return parent;
+    };
+
+    Collapse.prototype._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) {
+      if (element) {
+        var isOpen = $(element).hasClass(ClassName.IN);
+        element.setAttribute('aria-expanded', isOpen);
+
+        if (triggerArray.length) {
+          $(triggerArray).toggleClass(ClassName.COLLAPSED, !isOpen).attr('aria-expanded', isOpen);
+        }
+      }
+    };
+
+    // static
+
+    Collapse._getTargetFromElement = function _getTargetFromElement(element) {
+      var selector = Util.getSelectorFromElement(element);
+      return selector ? $(selector)[0] : null;
+    };
+
+    Collapse._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+        var _config = $.extend({}, Default, $this.data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data && _config.toggle && /show|hide/.test(config)) {
+          _config.toggle = false;
+        }
+
+        if (!data) {
+          data = new Collapse(this, _config);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Collapse, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Collapse;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+
+    var target = Collapse._getTargetFromElement(this);
+    var data = $(target).data(DATA_KEY);
+    var config = data ? 'toggle' : $(this).data();
+
+    Collapse._jQueryInterface.call($(target), config);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Collapse._jQueryInterface;
+  $.fn[NAME].Constructor = Collapse;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Collapse._jQueryInterface;
+  };
+
+  return Collapse;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): dropdown.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Dropdown = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'dropdown';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.dropdown';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+  var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key
+  var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key
+  var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse)
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY,
+    KEYDOWN_DATA_API: 'keydown' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    BACKDROP: 'dropdown-backdrop',
+    DISABLED: 'disabled',
+    OPEN: 'open'
+  };
+
+  var Selector = {
+    BACKDROP: '.dropdown-backdrop',
+    DATA_TOGGLE: '[data-toggle="dropdown"]',
+    FORM_CHILD: '.dropdown form',
+    ROLE_MENU: '[role="menu"]',
+    ROLE_LISTBOX: '[role="listbox"]',
+    NAVBAR_NAV: '.navbar-nav',
+    VISIBLE_ITEMS: '[role="menu"] li:not(.disabled) a, ' + '[role="listbox"] li:not(.disabled) a'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Dropdown = function () {
+    function Dropdown(element) {
+      _classCallCheck(this, Dropdown);
+
+      this._element = element;
+
+      this._addEventListeners();
+    }
+
+    // getters
+
+    // public
+
+    Dropdown.prototype.toggle = function toggle() {
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return false;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      Dropdown._clearMenus();
+
+      if (isActive) {
+        return false;
+      }
+
+      if ('ontouchstart' in document.documentElement && !$(parent).closest(Selector.NAVBAR_NAV).length) {
+
+        // if mobile we use a backdrop because click events don't delegate
+        var dropdown = document.createElement('div');
+        dropdown.className = ClassName.BACKDROP;
+        $(dropdown).insertBefore(this);
+        $(dropdown).on('click', Dropdown._clearMenus);
+      }
+
+      var relatedTarget = { relatedTarget: this };
+      var showEvent = $.Event(Event.SHOW, relatedTarget);
+
+      $(parent).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented()) {
+        return false;
+      }
+
+      this.focus();
+      this.setAttribute('aria-expanded', 'true');
+
+      $(parent).toggleClass(ClassName.OPEN);
+      $(parent).trigger($.Event(Event.SHOWN, relatedTarget));
+
+      return false;
+    };
+
+    Dropdown.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._element).off(EVENT_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Dropdown.prototype._addEventListeners = function _addEventListeners() {
+      $(this._element).on(Event.CLICK, this.toggle);
+    };
+
+    // static
+
+    Dropdown._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+
+        if (!data) {
+          $(this).data(DATA_KEY, data = new Dropdown(this));
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config].call(this);
+        }
+      });
+    };
+
+    Dropdown._clearMenus = function _clearMenus(event) {
+      if (event && event.which === RIGHT_MOUSE_BUTTON_WHICH) {
+        return;
+      }
+
+      var backdrop = $(Selector.BACKDROP)[0];
+      if (backdrop) {
+        backdrop.parentNode.removeChild(backdrop);
+      }
+
+      var toggles = $.makeArray($(Selector.DATA_TOGGLE));
+
+      for (var i = 0; i < toggles.length; i++) {
+        var parent = Dropdown._getParentFromElement(toggles[i]);
+        var relatedTarget = { relatedTarget: toggles[i] };
+
+        if (!$(parent).hasClass(ClassName.OPEN)) {
+          continue;
+        }
+
+        if (event && event.type === 'click' && /input|textarea/i.test(event.target.tagName) && $.contains(parent, event.target)) {
+          continue;
+        }
+
+        var hideEvent = $.Event(Event.HIDE, relatedTarget);
+        $(parent).trigger(hideEvent);
+        if (hideEvent.isDefaultPrevented()) {
+          continue;
+        }
+
+        toggles[i].setAttribute('aria-expanded', 'false');
+
+        $(parent).removeClass(ClassName.OPEN).trigger($.Event(Event.HIDDEN, relatedTarget));
+      }
+    };
+
+    Dropdown._getParentFromElement = function _getParentFromElement(element) {
+      var parent = void 0;
+      var selector = Util.getSelectorFromElement(element);
+
+      if (selector) {
+        parent = $(selector)[0];
+      }
+
+      return parent || element.parentNode;
+    };
+
+    Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) {
+      if (!/(38|40|27|32)/.test(event.which) || /input|textarea/i.test(event.target.tagName)) {
+        return;
+      }
+
+      event.preventDefault();
+      event.stopPropagation();
+
+      if (this.disabled || $(this).hasClass(ClassName.DISABLED)) {
+        return;
+      }
+
+      var parent = Dropdown._getParentFromElement(this);
+      var isActive = $(parent).hasClass(ClassName.OPEN);
+
+      if (!isActive && event.which !== ESCAPE_KEYCODE || isActive && event.which === ESCAPE_KEYCODE) {
+
+        if (event.which === ESCAPE_KEYCODE) {
+          var toggle = $(parent).find(Selector.DATA_TOGGLE)[0];
+          $(toggle).trigger('focus');
+        }
+
+        $(this).trigger('click');
+        return;
+      }
+
+      var items = $.makeArray($(Selector.VISIBLE_ITEMS));
+
+      items = items.filter(function (item) {
+        return item.offsetWidth || item.offsetHeight;
+      });
+
+      if (!items.length) {
+        return;
+      }
+
+      var index = items.indexOf(event.target);
+
+      if (event.which === ARROW_UP_KEYCODE && index > 0) {
+        // up
+        index--;
+      }
+
+      if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) {
+        // down
+        index++;
+      }
+
+      if (index < 0) {
+        index = 0;
+      }
+
+      items[index].focus();
+    };
+
+    _createClass(Dropdown, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Dropdown;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.KEYDOWN_DATA_API, Selector.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_MENU, Dropdown._dataApiKeydownHandler).on(Event.KEYDOWN_DATA_API, Selector.ROLE_LISTBOX, Dropdown._dataApiKeydownHandler).on(Event.CLICK_DATA_API, Dropdown._clearMenus).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, Dropdown.prototype.toggle).on(Event.CLICK_DATA_API, Selector.FORM_CHILD, function (e) {
+    e.stopPropagation();
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Dropdown._jQueryInterface;
+  $.fn[NAME].Constructor = Dropdown;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Dropdown._jQueryInterface;
+  };
+
+  return Dropdown;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): modal.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Modal = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'modal';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.modal';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 300;
+  var BACKDROP_TRANSITION_DURATION = 150;
+  var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key
+
+  var Default = {
+    backdrop: true,
+    keyboard: true,
+    focus: true,
+    show: true
+  };
+
+  var DefaultType = {
+    backdrop: '(boolean|string)',
+    keyboard: 'boolean',
+    focus: 'boolean',
+    show: 'boolean'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    RESIZE: 'resize' + EVENT_KEY,
+    CLICK_DISMISS: 'click.dismiss' + EVENT_KEY,
+    KEYDOWN_DISMISS: 'keydown.dismiss' + EVENT_KEY,
+    MOUSEUP_DISMISS: 'mouseup.dismiss' + EVENT_KEY,
+    MOUSEDOWN_DISMISS: 'mousedown.dismiss' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    SCROLLBAR_MEASURER: 'modal-scrollbar-measure',
+    BACKDROP: 'modal-backdrop',
+    OPEN: 'modal-open',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    DIALOG: '.modal-dialog',
+    DATA_TOGGLE: '[data-toggle="modal"]',
+    DATA_DISMISS: '[data-dismiss="modal"]',
+    FIXED_CONTENT: '.navbar-fixed-top, .navbar-fixed-bottom, .is-fixed'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Modal = function () {
+    function Modal(element, config) {
+      _classCallCheck(this, Modal);
+
+      this._config = this._getConfig(config);
+      this._element = element;
+      this._dialog = $(element).find(Selector.DIALOG)[0];
+      this._backdrop = null;
+      this._isShown = false;
+      this._isBodyOverflowing = false;
+      this._ignoreBackdropClick = false;
+      this._originalBodyPadding = 0;
+      this._scrollbarWidth = 0;
+    }
+
+    // getters
+
+    // public
+
+    Modal.prototype.toggle = function toggle(relatedTarget) {
+      return this._isShown ? this.hide() : this.show(relatedTarget);
+    };
+
+    Modal.prototype.show = function show(relatedTarget) {
+      var _this7 = this;
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: relatedTarget
+      });
+
+      $(this._element).trigger(showEvent);
+
+      if (this._isShown || showEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = true;
+
+      this._checkScrollbar();
+      this._setScrollbar();
+
+      $(document.body).addClass(ClassName.OPEN);
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(this._element).on(Event.CLICK_DISMISS, Selector.DATA_DISMISS, $.proxy(this.hide, this));
+
+      $(this._dialog).on(Event.MOUSEDOWN_DISMISS, function () {
+        $(_this7._element).one(Event.MOUSEUP_DISMISS, function (event) {
+          if ($(event.target).is(_this7._element)) {
+            _this7._ignoreBackdropClick = true;
+          }
+        });
+      });
+
+      this._showBackdrop($.proxy(this._showElement, this, relatedTarget));
+    };
+
+    Modal.prototype.hide = function hide(event) {
+      if (event) {
+        event.preventDefault();
+      }
+
+      var hideEvent = $.Event(Event.HIDE);
+
+      $(this._element).trigger(hideEvent);
+
+      if (!this._isShown || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      this._isShown = false;
+
+      this._setEscapeEvent();
+      this._setResizeEvent();
+
+      $(document).off(Event.FOCUSIN);
+
+      $(this._element).removeClass(ClassName.IN);
+
+      $(this._element).off(Event.CLICK_DISMISS);
+      $(this._dialog).off(Event.MOUSEDOWN_DISMISS);
+
+      if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+
+        $(this._element).one(Util.TRANSITION_END, $.proxy(this._hideModal, this)).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        this._hideModal();
+      }
+    };
+
+    Modal.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+
+      $(window).off(EVENT_KEY);
+      $(document).off(EVENT_KEY);
+      $(this._element).off(EVENT_KEY);
+      $(this._backdrop).off(EVENT_KEY);
+
+      this._config = null;
+      this._element = null;
+      this._dialog = null;
+      this._backdrop = null;
+      this._isShown = null;
+      this._isBodyOverflowing = null;
+      this._ignoreBackdropClick = null;
+      this._originalBodyPadding = null;
+      this._scrollbarWidth = null;
+    };
+
+    // private
+
+    Modal.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+      Util.typeCheckConfig(NAME, config, DefaultType);
+      return config;
+    };
+
+    Modal.prototype._showElement = function _showElement(relatedTarget) {
+      var _this8 = this;
+
+      var transition = Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE);
+
+      if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) {
+        // don't move modals dom position
+        document.body.appendChild(this._element);
+      }
+
+      this._element.style.display = 'block';
+      this._element.removeAttribute('aria-hidden');
+      this._element.scrollTop = 0;
+
+      if (transition) {
+        Util.reflow(this._element);
+      }
+
+      $(this._element).addClass(ClassName.IN);
+
+      if (this._config.focus) {
+        this._enforceFocus();
+      }
+
+      var shownEvent = $.Event(Event.SHOWN, {
+        relatedTarget: relatedTarget
+      });
+
+      var transitionComplete = function transitionComplete() {
+        if (_this8._config.focus) {
+          _this8._element.focus();
+        }
+        $(_this8._element).trigger(shownEvent);
+      };
+
+      if (transition) {
+        $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        transitionComplete();
+      }
+    };
+
+    Modal.prototype._enforceFocus = function _enforceFocus() {
+      var _this9 = this;
+
+      $(document).off(Event.FOCUSIN) // guard against infinite focus loop
+      .on(Event.FOCUSIN, function (event) {
+        if (document !== event.target && _this9._element !== event.target && !$(_this9._element).has(event.target).length) {
+          _this9._element.focus();
+        }
+      });
+    };
+
+    Modal.prototype._setEscapeEvent = function _setEscapeEvent() {
+      var _this10 = this;
+
+      if (this._isShown && this._config.keyboard) {
+        $(this._element).on(Event.KEYDOWN_DISMISS, function (event) {
+          if (event.which === ESCAPE_KEYCODE) {
+            _this10.hide();
+          }
+        });
+      } else if (!this._isShown) {
+        $(this._element).off(Event.KEYDOWN_DISMISS);
+      }
+    };
+
+    Modal.prototype._setResizeEvent = function _setResizeEvent() {
+      if (this._isShown) {
+        $(window).on(Event.RESIZE, $.proxy(this._handleUpdate, this));
+      } else {
+        $(window).off(Event.RESIZE);
+      }
+    };
+
+    Modal.prototype._hideModal = function _hideModal() {
+      var _this11 = this;
+
+      this._element.style.display = 'none';
+      this._element.setAttribute('aria-hidden', 'true');
+      this._showBackdrop(function () {
+        $(document.body).removeClass(ClassName.OPEN);
+        _this11._resetAdjustments();
+        _this11._resetScrollbar();
+        $(_this11._element).trigger(Event.HIDDEN);
+      });
+    };
+
+    Modal.prototype._removeBackdrop = function _removeBackdrop() {
+      if (this._backdrop) {
+        $(this._backdrop).remove();
+        this._backdrop = null;
+      }
+    };
+
+    Modal.prototype._showBackdrop = function _showBackdrop(callback) {
+      var _this12 = this;
+
+      var animate = $(this._element).hasClass(ClassName.FADE) ? ClassName.FADE : '';
+
+      if (this._isShown && this._config.backdrop) {
+        var doAnimate = Util.supportsTransitionEnd() && animate;
+
+        this._backdrop = document.createElement('div');
+        this._backdrop.className = ClassName.BACKDROP;
+
+        if (animate) {
+          $(this._backdrop).addClass(animate);
+        }
+
+        $(this._backdrop).appendTo(document.body);
+
+        $(this._element).on(Event.CLICK_DISMISS, function (event) {
+          if (_this12._ignoreBackdropClick) {
+            _this12._ignoreBackdropClick = false;
+            return;
+          }
+          if (event.target !== event.currentTarget) {
+            return;
+          }
+          if (_this12._config.backdrop === 'static') {
+            _this12._element.focus();
+          } else {
+            _this12.hide();
+          }
+        });
+
+        if (doAnimate) {
+          Util.reflow(this._backdrop);
+        }
+
+        $(this._backdrop).addClass(ClassName.IN);
+
+        if (!callback) {
+          return;
+        }
+
+        if (!doAnimate) {
+          callback();
+          return;
+        }
+
+        $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+      } else if (!this._isShown && this._backdrop) {
+        $(this._backdrop).removeClass(ClassName.IN);
+
+        var callbackRemove = function callbackRemove() {
+          _this12._removeBackdrop();
+          if (callback) {
+            callback();
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this._element).hasClass(ClassName.FADE)) {
+          $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(BACKDROP_TRANSITION_DURATION);
+        } else {
+          callbackRemove();
+        }
+      } else if (callback) {
+        callback();
+      }
+    };
+
+    // ----------------------------------------------------------------------
+    // the following methods are used to handle overflowing modals
+    // todo (fat): these should probably be refactored out of modal.js
+    // ----------------------------------------------------------------------
+
+    Modal.prototype._handleUpdate = function _handleUpdate() {
+      this._adjustDialog();
+    };
+
+    Modal.prototype._adjustDialog = function _adjustDialog() {
+      var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight;
+
+      if (!this._isBodyOverflowing && isModalOverflowing) {
+        this._element.style.paddingLeft = this._scrollbarWidth + 'px';
+      }
+
+      if (this._isBodyOverflowing && !isModalOverflowing) {
+        this._element.style.paddingRight = this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetAdjustments = function _resetAdjustments() {
+      this._element.style.paddingLeft = '';
+      this._element.style.paddingRight = '';
+    };
+
+    Modal.prototype._checkScrollbar = function _checkScrollbar() {
+      this._isBodyOverflowing = document.body.clientWidth < window.innerWidth;
+      this._scrollbarWidth = this._getScrollbarWidth();
+    };
+
+    Modal.prototype._setScrollbar = function _setScrollbar() {
+      var bodyPadding = parseInt($(Selector.FIXED_CONTENT).css('padding-right') || 0, 10);
+
+      this._originalBodyPadding = document.body.style.paddingRight || '';
+
+      if (this._isBodyOverflowing) {
+        document.body.style.paddingRight = bodyPadding + this._scrollbarWidth + 'px';
+      }
+    };
+
+    Modal.prototype._resetScrollbar = function _resetScrollbar() {
+      document.body.style.paddingRight = this._originalBodyPadding;
+    };
+
+    Modal.prototype._getScrollbarWidth = function _getScrollbarWidth() {
+      // thx d.walsh
+      var scrollDiv = document.createElement('div');
+      scrollDiv.className = ClassName.SCROLLBAR_MEASURER;
+      document.body.appendChild(scrollDiv);
+      var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;
+      document.body.removeChild(scrollDiv);
+      return scrollbarWidth;
+    };
+
+    // static
+
+    Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = $.extend({}, Modal.Default, $(this).data(), (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config);
+
+        if (!data) {
+          data = new Modal(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config](relatedTarget);
+        } else if (_config.show) {
+          data.show(relatedTarget);
+        }
+      });
+    };
+
+    _createClass(Modal, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return Modal;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    var _this13 = this;
+
+    var target = void 0;
+    var selector = Util.getSelectorFromElement(this);
+
+    if (selector) {
+      target = $(selector)[0];
+    }
+
+    var config = $(target).data(DATA_KEY) ? 'toggle' : $.extend({}, $(target).data(), $(this).data());
+
+    if (this.tagName === 'A') {
+      event.preventDefault();
+    }
+
+    var $target = $(target).one(Event.SHOW, function (showEvent) {
+      if (showEvent.isDefaultPrevented()) {
+        // only register focus restorer if modal will actually get shown
+        return;
+      }
+
+      $target.one(Event.HIDDEN, function () {
+        if ($(_this13).is(':visible')) {
+          _this13.focus();
+        }
+      });
+    });
+
+    Modal._jQueryInterface.call($(target), config, this);
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Modal._jQueryInterface;
+  $.fn[NAME].Constructor = Modal;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Modal._jQueryInterface;
+  };
+
+  return Modal;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): scrollspy.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var ScrollSpy = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'scrollspy';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.scrollspy';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = {
+    offset: 10,
+    method: 'auto',
+    target: ''
+  };
+
+  var DefaultType = {
+    offset: 'number',
+    method: 'string',
+    target: '(string|element)'
+  };
+
+  var Event = {
+    ACTIVATE: 'activate' + EVENT_KEY,
+    SCROLL: 'scroll' + EVENT_KEY,
+    LOAD_DATA_API: 'load' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_ITEM: 'dropdown-item',
+    DROPDOWN_MENU: 'dropdown-menu',
+    NAV_LINK: 'nav-link',
+    NAV: 'nav',
+    ACTIVE: 'active'
+  };
+
+  var Selector = {
+    DATA_SPY: '[data-spy="scroll"]',
+    ACTIVE: '.active',
+    LIST_ITEM: '.list-item',
+    LI: 'li',
+    LI_DROPDOWN: 'li.dropdown',
+    NAV_LINKS: '.nav-link',
+    DROPDOWN: '.dropdown',
+    DROPDOWN_ITEMS: '.dropdown-item',
+    DROPDOWN_TOGGLE: '.dropdown-toggle'
+  };
+
+  var OffsetMethod = {
+    OFFSET: 'offset',
+    POSITION: 'position'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var ScrollSpy = function () {
+    function ScrollSpy(element, config) {
+      _classCallCheck(this, ScrollSpy);
+
+      this._element = element;
+      this._scrollElement = element.tagName === 'BODY' ? window : element;
+      this._config = this._getConfig(config);
+      this._selector = this._config.target + ' ' + Selector.NAV_LINKS + ',' + (this._config.target + ' ' + Selector.DROPDOWN_ITEMS);
+      this._offsets = [];
+      this._targets = [];
+      this._activeTarget = null;
+      this._scrollHeight = 0;
+
+      $(this._scrollElement).on(Event.SCROLL, $.proxy(this._process, this));
+
+      this.refresh();
+      this._process();
+    }
+
+    // getters
+
+    // public
+
+    ScrollSpy.prototype.refresh = function refresh() {
+      var _this14 = this;
+
+      var autoMethod = this._scrollElement !== this._scrollElement.window ? OffsetMethod.POSITION : OffsetMethod.OFFSET;
+
+      var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method;
+
+      var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0;
+
+      this._offsets = [];
+      this._targets = [];
+
+      this._scrollHeight = this._getScrollHeight();
+
+      var targets = $.makeArray($(this._selector));
+
+      targets.map(function (element) {
+        var target = void 0;
+        var targetSelector = Util.getSelectorFromElement(element);
+
+        if (targetSelector) {
+          target = $(targetSelector)[0];
+        }
+
+        if (target && (target.offsetWidth || target.offsetHeight)) {
+          // todo (fat): remove sketch reliance on jQuery position/offset
+          return [$(target)[offsetMethod]().top + offsetBase, targetSelector];
+        }
+        return null;
+      }).filter(function (item) {
+        return item;
+      }).sort(function (a, b) {
+        return a[0] - b[0];
+      }).forEach(function (item) {
+        _this14._offsets.push(item[0]);
+        _this14._targets.push(item[1]);
+      });
+    };
+
+    ScrollSpy.prototype.dispose = function dispose() {
+      $.removeData(this._element, DATA_KEY);
+      $(this._scrollElement).off(EVENT_KEY);
+
+      this._element = null;
+      this._scrollElement = null;
+      this._config = null;
+      this._selector = null;
+      this._offsets = null;
+      this._targets = null;
+      this._activeTarget = null;
+      this._scrollHeight = null;
+    };
+
+    // private
+
+    ScrollSpy.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, Default, config);
+
+      if (typeof config.target !== 'string') {
+        var id = $(config.target).attr('id');
+        if (!id) {
+          id = Util.getUID(NAME);
+          $(config.target).attr('id', id);
+        }
+        config.target = '#' + id;
+      }
+
+      Util.typeCheckConfig(NAME, config, DefaultType);
+
+      return config;
+    };
+
+    ScrollSpy.prototype._getScrollTop = function _getScrollTop() {
+      return this._scrollElement === window ? this._scrollElement.scrollY : this._scrollElement.scrollTop;
+    };
+
+    ScrollSpy.prototype._getScrollHeight = function _getScrollHeight() {
+      return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight);
+    };
+
+    ScrollSpy.prototype._process = function _process() {
+      var scrollTop = this._getScrollTop() + this._config.offset;
+      var scrollHeight = this._getScrollHeight();
+      var maxScroll = this._config.offset + scrollHeight - this._scrollElement.offsetHeight;
+
+      if (this._scrollHeight !== scrollHeight) {
+        this.refresh();
+      }
+
+      if (scrollTop >= maxScroll) {
+        var target = this._targets[this._targets.length - 1];
+
+        if (this._activeTarget !== target) {
+          this._activate(target);
+        }
+      }
+
+      if (this._activeTarget && scrollTop < this._offsets[0]) {
+        this._activeTarget = null;
+        this._clear();
+        return;
+      }
+
+      for (var i = this._offsets.length; i--;) {
+        var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (this._offsets[i + 1] === undefined || scrollTop < this._offsets[i + 1]);
+
+        if (isActiveTarget) {
+          this._activate(this._targets[i]);
+        }
+      }
+    };
+
+    ScrollSpy.prototype._activate = function _activate(target) {
+      this._activeTarget = target;
+
+      this._clear();
+
+      var queries = this._selector.split(',');
+      queries = queries.map(function (selector) {
+        return selector + '[data-target="' + target + '"],' + (selector + '[href="' + target + '"]');
+      });
+
+      var $link = $(queries.join(','));
+
+      if ($link.hasClass(ClassName.DROPDOWN_ITEM)) {
+        $link.closest(Selector.DROPDOWN).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        $link.addClass(ClassName.ACTIVE);
+      } else {
+        // todo (fat) this is kinda sus...
+        // recursively add actives to tested nav-links
+        $link.parents(Selector.LI).find(Selector.NAV_LINKS).addClass(ClassName.ACTIVE);
+      }
+
+      $(this._scrollElement).trigger(Event.ACTIVATE, {
+        relatedTarget: target
+      });
+    };
+
+    ScrollSpy.prototype._clear = function _clear() {
+      $(this._selector).filter(Selector.ACTIVE).removeClass(ClassName.ACTIVE);
+    };
+
+    // static
+
+    ScrollSpy._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' && config || null;
+
+        if (!data) {
+          data = new ScrollSpy(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(ScrollSpy, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }]);
+
+    return ScrollSpy;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(window).on(Event.LOAD_DATA_API, function () {
+    var scrollSpys = $.makeArray($(Selector.DATA_SPY));
+
+    for (var i = scrollSpys.length; i--;) {
+      var $spy = $(scrollSpys[i]);
+      ScrollSpy._jQueryInterface.call($spy, $spy.data());
+    }
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = ScrollSpy._jQueryInterface;
+  $.fn[NAME].Constructor = ScrollSpy;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return ScrollSpy._jQueryInterface;
+  };
+
+  return ScrollSpy;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tab.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tab = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tab';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tab';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var DATA_API_KEY = '.data-api';
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    CLICK_DATA_API: 'click' + EVENT_KEY + DATA_API_KEY
+  };
+
+  var ClassName = {
+    DROPDOWN_MENU: 'dropdown-menu',
+    ACTIVE: 'active',
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    A: 'a',
+    LI: 'li',
+    DROPDOWN: '.dropdown',
+    UL: 'ul:not(.dropdown-menu)',
+    FADE_CHILD: '> .nav-item .fade, > .fade',
+    ACTIVE: '.active',
+    ACTIVE_CHILD: '> .nav-item > .active, > .active',
+    DATA_TOGGLE: '[data-toggle="tab"], [data-toggle="pill"]',
+    DROPDOWN_TOGGLE: '.dropdown-toggle',
+    DROPDOWN_ACTIVE_CHILD: '> .dropdown-menu .active'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tab = function () {
+    function Tab(element) {
+      _classCallCheck(this, Tab);
+
+      this._element = element;
+    }
+
+    // getters
+
+    // public
+
+    Tab.prototype.show = function show() {
+      var _this15 = this;
+
+      if (this._element.parentNode && this._element.parentNode.nodeType === Node.ELEMENT_NODE && $(this._element).hasClass(ClassName.ACTIVE)) {
+        return;
+      }
+
+      var target = void 0;
+      var previous = void 0;
+      var ulElement = $(this._element).closest(Selector.UL)[0];
+      var selector = Util.getSelectorFromElement(this._element);
+
+      if (ulElement) {
+        previous = $.makeArray($(ulElement).find(Selector.ACTIVE));
+        previous = previous[previous.length - 1];
+      }
+
+      var hideEvent = $.Event(Event.HIDE, {
+        relatedTarget: this._element
+      });
+
+      var showEvent = $.Event(Event.SHOW, {
+        relatedTarget: previous
+      });
+
+      if (previous) {
+        $(previous).trigger(hideEvent);
+      }
+
+      $(this._element).trigger(showEvent);
+
+      if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      if (selector) {
+        target = $(selector)[0];
+      }
+
+      this._activate(this._element, ulElement);
+
+      var complete = function complete() {
+        var hiddenEvent = $.Event(Event.HIDDEN, {
+          relatedTarget: _this15._element
+        });
+
+        var shownEvent = $.Event(Event.SHOWN, {
+          relatedTarget: previous
+        });
+
+        $(previous).trigger(hiddenEvent);
+        $(_this15._element).trigger(shownEvent);
+      };
+
+      if (target) {
+        this._activate(target, target.parentNode, complete);
+      } else {
+        complete();
+      }
+    };
+
+    Tab.prototype.dispose = function dispose() {
+      $.removeClass(this._element, DATA_KEY);
+      this._element = null;
+    };
+
+    // private
+
+    Tab.prototype._activate = function _activate(element, container, callback) {
+      var active = $(container).find(Selector.ACTIVE_CHILD)[0];
+      var isTransitioning = callback && Util.supportsTransitionEnd() && (active && $(active).hasClass(ClassName.FADE) || Boolean($(container).find(Selector.FADE_CHILD)[0]));
+
+      var complete = $.proxy(this._transitionComplete, this, element, active, isTransitioning, callback);
+
+      if (active && isTransitioning) {
+        $(active).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      if (active) {
+        $(active).removeClass(ClassName.IN);
+      }
+    };
+
+    Tab.prototype._transitionComplete = function _transitionComplete(element, active, isTransitioning, callback) {
+      if (active) {
+        $(active).removeClass(ClassName.ACTIVE);
+
+        var dropdownChild = $(active).find(Selector.DROPDOWN_ACTIVE_CHILD)[0];
+
+        if (dropdownChild) {
+          $(dropdownChild).removeClass(ClassName.ACTIVE);
+        }
+
+        active.setAttribute('aria-expanded', false);
+      }
+
+      $(element).addClass(ClassName.ACTIVE);
+      element.setAttribute('aria-expanded', true);
+
+      if (isTransitioning) {
+        Util.reflow(element);
+        $(element).addClass(ClassName.IN);
+      } else {
+        $(element).removeClass(ClassName.FADE);
+      }
+
+      if (element.parentNode && $(element.parentNode).hasClass(ClassName.DROPDOWN_MENU)) {
+
+        var dropdownElement = $(element).closest(Selector.DROPDOWN)[0];
+        if (dropdownElement) {
+          $(dropdownElement).find(Selector.DROPDOWN_TOGGLE).addClass(ClassName.ACTIVE);
+        }
+
+        element.setAttribute('aria-expanded', true);
+      }
+
+      if (callback) {
+        callback();
+      }
+    };
+
+    // static
+
+    Tab._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var $this = $(this);
+        var data = $this.data(DATA_KEY);
+
+        if (!data) {
+          data = data = new Tab(this);
+          $this.data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tab, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }]);
+
+    return Tab;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * Data Api implementation
+   * ------------------------------------------------------------------------
+   */
+
+  $(document).on(Event.CLICK_DATA_API, Selector.DATA_TOGGLE, function (event) {
+    event.preventDefault();
+    Tab._jQueryInterface.call($(this), 'show');
+  });
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tab._jQueryInterface;
+  $.fn[NAME].Constructor = Tab;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tab._jQueryInterface;
+  };
+
+  return Tab;
+}(jQuery);
+
+/* global Tether */
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): tooltip.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Tooltip = function ($) {
+
+  /**
+   * Check for Tether dependency
+   * Tether - http://tether.io/
+   */
+  if (window.Tether === undefined) {
+    throw new Error('Bootstrap tooltips require Tether (http://tether.io/)');
+  }
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'tooltip';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.tooltip';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+  var TRANSITION_DURATION = 150;
+  var CLASS_PREFIX = 'bs-tether';
+
+  var Default = {
+    animation: true,
+    template: '<div class="tooltip" role="tooltip">' + '<div class="tooltip-inner"></div></div>',
+    trigger: 'hover focus',
+    title: '',
+    delay: 0,
+    html: false,
+    selector: false,
+    placement: 'top',
+    offset: '0 0',
+    constraints: []
+  };
+
+  var DefaultType = {
+    animation: 'boolean',
+    template: 'string',
+    title: '(string|element|function)',
+    trigger: 'string',
+    delay: '(number|object)',
+    html: 'boolean',
+    selector: '(string|boolean)',
+    placement: '(string|function)',
+    offset: 'string',
+    constraints: 'array'
+  };
+
+  var AttachmentMap = {
+    TOP: 'bottom center',
+    RIGHT: 'middle left',
+    BOTTOM: 'top center',
+    LEFT: 'middle right'
+  };
+
+  var HoverState = {
+    IN: 'in',
+    OUT: 'out'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TOOLTIP: '.tooltip',
+    TOOLTIP_INNER: '.tooltip-inner'
+  };
+
+  var TetherClass = {
+    element: false,
+    enabled: false
+  };
+
+  var Trigger = {
+    HOVER: 'hover',
+    FOCUS: 'focus',
+    CLICK: 'click',
+    MANUAL: 'manual'
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Tooltip = function () {
+    function Tooltip(element, config) {
+      _classCallCheck(this, Tooltip);
+
+      // private
+      this._isEnabled = true;
+      this._timeout = 0;
+      this._hoverState = '';
+      this._activeTrigger = {};
+      this._tether = null;
+
+      // protected
+      this.element = element;
+      this.config = this._getConfig(config);
+      this.tip = null;
+
+      this._setListeners();
+    }
+
+    // getters
+
+    // public
+
+    Tooltip.prototype.enable = function enable() {
+      this._isEnabled = true;
+    };
+
+    Tooltip.prototype.disable = function disable() {
+      this._isEnabled = false;
+    };
+
+    Tooltip.prototype.toggleEnabled = function toggleEnabled() {
+      this._isEnabled = !this._isEnabled;
+    };
+
+    Tooltip.prototype.toggle = function toggle(event) {
+      if (event) {
+        var dataKey = this.constructor.DATA_KEY;
+        var context = $(event.currentTarget).data(dataKey);
+
+        if (!context) {
+          context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+          $(event.currentTarget).data(dataKey, context);
+        }
+
+        context._activeTrigger.click = !context._activeTrigger.click;
+
+        if (context._isWithActiveTrigger()) {
+          context._enter(null, context);
+        } else {
+          context._leave(null, context);
+        }
+      } else {
+
+        if ($(this.getTipElement()).hasClass(ClassName.IN)) {
+          this._leave(null, this);
+          return;
+        }
+
+        this._enter(null, this);
+      }
+    };
+
+    Tooltip.prototype.dispose = function dispose() {
+      clearTimeout(this._timeout);
+
+      this.cleanupTether();
+
+      $.removeData(this.element, this.constructor.DATA_KEY);
+
+      $(this.element).off(this.constructor.EVENT_KEY);
+
+      if (this.tip) {
+        $(this.tip).remove();
+      }
+
+      this._isEnabled = null;
+      this._timeout = null;
+      this._hoverState = null;
+      this._activeTrigger = null;
+      this._tether = null;
+
+      this.element = null;
+      this.config = null;
+      this.tip = null;
+    };
+
+    Tooltip.prototype.show = function show() {
+      var _this16 = this;
+
+      var showEvent = $.Event(this.constructor.Event.SHOW);
+
+      if (this.isWithContent() && this._isEnabled) {
+        $(this.element).trigger(showEvent);
+
+        var isInTheDom = $.contains(this.element.ownerDocument.documentElement, this.element);
+
+        if (showEvent.isDefaultPrevented() || !isInTheDom) {
+          return;
+        }
+
+        var tip = this.getTipElement();
+        var tipId = Util.getUID(this.constructor.NAME);
+
+        tip.setAttribute('id', tipId);
+        this.element.setAttribute('aria-describedby', tipId);
+
+        this.setContent();
+
+        if (this.config.animation) {
+          $(tip).addClass(ClassName.FADE);
+        }
+
+        var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement;
+
+        var attachment = this._getAttachment(placement);
+
+        $(tip).data(this.constructor.DATA_KEY, this).appendTo(document.body);
+
+        $(this.element).trigger(this.constructor.Event.INSERTED);
+
+        this._tether = new Tether({
+          attachment: attachment,
+          element: tip,
+          target: this.element,
+          classes: TetherClass,
+          classPrefix: CLASS_PREFIX,
+          offset: this.config.offset,
+          constraints: this.config.constraints,
+          addTargetClasses: false
+        });
+
+        Util.reflow(tip);
+        this._tether.position();
+
+        $(tip).addClass(ClassName.IN);
+
+        var complete = function complete() {
+          var prevHoverState = _this16._hoverState;
+          _this16._hoverState = null;
+
+          $(_this16.element).trigger(_this16.constructor.Event.SHOWN);
+
+          if (prevHoverState === HoverState.OUT) {
+            _this16._leave(null, _this16);
+          }
+        };
+
+        if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+          $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(Tooltip._TRANSITION_DURATION);
+          return;
+        }
+
+        complete();
+      }
+    };
+
+    Tooltip.prototype.hide = function hide(callback) {
+      var _this17 = this;
+
+      var tip = this.getTipElement();
+      var hideEvent = $.Event(this.constructor.Event.HIDE);
+      var complete = function complete() {
+        if (_this17._hoverState !== HoverState.IN && tip.parentNode) {
+          tip.parentNode.removeChild(tip);
+        }
+
+        _this17.element.removeAttribute('aria-describedby');
+        $(_this17.element).trigger(_this17.constructor.Event.HIDDEN);
+        _this17.cleanupTether();
+
+        if (callback) {
+          callback();
+        }
+      };
+
+      $(this.element).trigger(hideEvent);
+
+      if (hideEvent.isDefaultPrevented()) {
+        return;
+      }
+
+      $(tip).removeClass(ClassName.IN);
+
+      if (Util.supportsTransitionEnd() && $(this.tip).hasClass(ClassName.FADE)) {
+
+        $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(TRANSITION_DURATION);
+      } else {
+        complete();
+      }
+
+      this._hoverState = '';
+    };
+
+    // protected
+
+    Tooltip.prototype.isWithContent = function isWithContent() {
+      return Boolean(this.getTitle());
+    };
+
+    Tooltip.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Tooltip.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      this.setElementContent($tip.find(Selector.TOOLTIP_INNER), this.getTitle());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    Tooltip.prototype.setElementContent = function setElementContent($element, content) {
+      var html = this.config.html;
+      if ((typeof content === 'undefined' ? 'undefined' : _typeof(content)) === 'object' && (content.nodeType || content.jquery)) {
+        // content is a DOM node or a jQuery
+        if (html) {
+          if (!$(content).parent().is($element)) {
+            $element.empty().append(content);
+          }
+        } else {
+          $element.text($(content).text());
+        }
+      } else {
+        $element[html ? 'html' : 'text'](content);
+      }
+    };
+
+    Tooltip.prototype.getTitle = function getTitle() {
+      var title = this.element.getAttribute('data-original-title');
+
+      if (!title) {
+        title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title;
+      }
+
+      return title;
+    };
+
+    Tooltip.prototype.cleanupTether = function cleanupTether() {
+      if (this._tether) {
+        this._tether.destroy();
+      }
+    };
+
+    // private
+
+    Tooltip.prototype._getAttachment = function _getAttachment(placement) {
+      return AttachmentMap[placement.toUpperCase()];
+    };
+
+    Tooltip.prototype._setListeners = function _setListeners() {
+      var _this18 = this;
+
+      var triggers = this.config.trigger.split(' ');
+
+      triggers.forEach(function (trigger) {
+        if (trigger === 'click') {
+          $(_this18.element).on(_this18.constructor.Event.CLICK, _this18.config.selector, $.proxy(_this18.toggle, _this18));
+        } else if (trigger !== Trigger.MANUAL) {
+          var eventIn = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSEENTER : _this18.constructor.Event.FOCUSIN;
+          var eventOut = trigger === Trigger.HOVER ? _this18.constructor.Event.MOUSELEAVE : _this18.constructor.Event.FOCUSOUT;
+
+          $(_this18.element).on(eventIn, _this18.config.selector, $.proxy(_this18._enter, _this18)).on(eventOut, _this18.config.selector, $.proxy(_this18._leave, _this18));
+        }
+      });
+
+      if (this.config.selector) {
+        this.config = $.extend({}, this.config, {
+          trigger: 'manual',
+          selector: ''
+        });
+      } else {
+        this._fixTitle();
+      }
+    };
+
+    Tooltip.prototype._fixTitle = function _fixTitle() {
+      var titleType = _typeof(this.element.getAttribute('data-original-title'));
+      if (this.element.getAttribute('title') || titleType !== 'string') {
+        this.element.setAttribute('data-original-title', this.element.getAttribute('title') || '');
+        this.element.setAttribute('title', '');
+      }
+    };
+
+    Tooltip.prototype._enter = function _enter(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true;
+      }
+
+      if ($(context.getTipElement()).hasClass(ClassName.IN) || context._hoverState === HoverState.IN) {
+        context._hoverState = HoverState.IN;
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.IN;
+
+      if (!context.config.delay || !context.config.delay.show) {
+        context.show();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.IN) {
+          context.show();
+        }
+      }, context.config.delay.show);
+    };
+
+    Tooltip.prototype._leave = function _leave(event, context) {
+      var dataKey = this.constructor.DATA_KEY;
+
+      context = context || $(event.currentTarget).data(dataKey);
+
+      if (!context) {
+        context = new this.constructor(event.currentTarget, this._getDelegateConfig());
+        $(event.currentTarget).data(dataKey, context);
+      }
+
+      if (event) {
+        context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false;
+      }
+
+      if (context._isWithActiveTrigger()) {
+        return;
+      }
+
+      clearTimeout(context._timeout);
+
+      context._hoverState = HoverState.OUT;
+
+      if (!context.config.delay || !context.config.delay.hide) {
+        context.hide();
+        return;
+      }
+
+      context._timeout = setTimeout(function () {
+        if (context._hoverState === HoverState.OUT) {
+          context.hide();
+        }
+      }, context.config.delay.hide);
+    };
+
+    Tooltip.prototype._isWithActiveTrigger = function _isWithActiveTrigger() {
+      for (var trigger in this._activeTrigger) {
+        if (this._activeTrigger[trigger]) {
+          return true;
+        }
+      }
+
+      return false;
+    };
+
+    Tooltip.prototype._getConfig = function _getConfig(config) {
+      config = $.extend({}, this.constructor.Default, $(this.element).data(), config);
+
+      if (config.delay && typeof config.delay === 'number') {
+        config.delay = {
+          show: config.delay,
+          hide: config.delay
+        };
+      }
+
+      Util.typeCheckConfig(NAME, config, this.constructor.DefaultType);
+
+      return config;
+    };
+
+    Tooltip.prototype._getDelegateConfig = function _getDelegateConfig() {
+      var config = {};
+
+      if (this.config) {
+        for (var key in this.config) {
+          if (this.constructor.Default[key] !== this.config[key]) {
+            config[key] = this.config[key];
+          }
+        }
+      }
+
+      return config;
+    };
+
+    // static
+
+    Tooltip._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /dispose|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Tooltip(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Tooltip, null, [{
+      key: 'VERSION',
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Tooltip;
+  }();
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Tooltip._jQueryInterface;
+  $.fn[NAME].Constructor = Tooltip;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Tooltip._jQueryInterface;
+  };
+
+  return Tooltip;
+}(jQuery);
+
+/**
+ * --------------------------------------------------------------------------
+ * Bootstrap (v4.0.0-alpha.5): popover.js
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ * --------------------------------------------------------------------------
+ */
+
+var Popover = function ($) {
+
+  /**
+   * ------------------------------------------------------------------------
+   * Constants
+   * ------------------------------------------------------------------------
+   */
+
+  var NAME = 'popover';
+  var VERSION = '4.0.0-alpha.5';
+  var DATA_KEY = 'bs.popover';
+  var EVENT_KEY = '.' + DATA_KEY;
+  var JQUERY_NO_CONFLICT = $.fn[NAME];
+
+  var Default = $.extend({}, Tooltip.Default, {
+    placement: 'right',
+    trigger: 'click',
+    content: '',
+    template: '<div class="popover" role="tooltip">' + '<h3 class="popover-title"></h3>' + '<div class="popover-content"></div></div>'
+  });
+
+  var DefaultType = $.extend({}, Tooltip.DefaultType, {
+    content: '(string|element|function)'
+  });
+
+  var ClassName = {
+    FADE: 'fade',
+    IN: 'in'
+  };
+
+  var Selector = {
+    TITLE: '.popover-title',
+    CONTENT: '.popover-content'
+  };
+
+  var Event = {
+    HIDE: 'hide' + EVENT_KEY,
+    HIDDEN: 'hidden' + EVENT_KEY,
+    SHOW: 'show' + EVENT_KEY,
+    SHOWN: 'shown' + EVENT_KEY,
+    INSERTED: 'inserted' + EVENT_KEY,
+    CLICK: 'click' + EVENT_KEY,
+    FOCUSIN: 'focusin' + EVENT_KEY,
+    FOCUSOUT: 'focusout' + EVENT_KEY,
+    MOUSEENTER: 'mouseenter' + EVENT_KEY,
+    MOUSELEAVE: 'mouseleave' + EVENT_KEY
+  };
+
+  /**
+   * ------------------------------------------------------------------------
+   * Class Definition
+   * ------------------------------------------------------------------------
+   */
+
+  var Popover = function (_Tooltip) {
+    _inherits(Popover, _Tooltip);
+
+    function Popover() {
+      _classCallCheck(this, Popover);
+
+      return _possibleConstructorReturn(this, _Tooltip.apply(this, arguments));
+    }
+
+    // overrides
+
+    Popover.prototype.isWithContent = function isWithContent() {
+      return this.getTitle() || this._getContent();
+    };
+
+    Popover.prototype.getTipElement = function getTipElement() {
+      return this.tip = this.tip || $(this.config.template)[0];
+    };
+
+    Popover.prototype.setContent = function setContent() {
+      var $tip = $(this.getTipElement());
+
+      // we use append for html objects to maintain js events
+      this.setElementContent($tip.find(Selector.TITLE), this.getTitle());
+      this.setElementContent($tip.find(Selector.CONTENT), this._getContent());
+
+      $tip.removeClass(ClassName.FADE).removeClass(ClassName.IN);
+
+      this.cleanupTether();
+    };
+
+    // private
+
+    Popover.prototype._getContent = function _getContent() {
+      return this.element.getAttribute('data-content') || (typeof this.config.content === 'function' ? this.config.content.call(this.element) : this.config.content);
+    };
+
+    // static
+
+    Popover._jQueryInterface = function _jQueryInterface(config) {
+      return this.each(function () {
+        var data = $(this).data(DATA_KEY);
+        var _config = (typeof config === 'undefined' ? 'undefined' : _typeof(config)) === 'object' ? config : null;
+
+        if (!data && /destroy|hide/.test(config)) {
+          return;
+        }
+
+        if (!data) {
+          data = new Popover(this, _config);
+          $(this).data(DATA_KEY, data);
+        }
+
+        if (typeof config === 'string') {
+          if (data[config] === undefined) {
+            throw new Error('No method named "' + config + '"');
+          }
+          data[config]();
+        }
+      });
+    };
+
+    _createClass(Popover, null, [{
+      key: 'VERSION',
+
+
+      // getters
+
+      get: function get() {
+        return VERSION;
+      }
+    }, {
+      key: 'Default',
+      get: function get() {
+        return Default;
+      }
+    }, {
+      key: 'NAME',
+      get: function get() {
+        return NAME;
+      }
+    }, {
+      key: 'DATA_KEY',
+      get: function get() {
+        return DATA_KEY;
+      }
+    }, {
+      key: 'Event',
+      get: function get() {
+        return Event;
+      }
+    }, {
+      key: 'EVENT_KEY',
+      get: function get() {
+        return EVENT_KEY;
+      }
+    }, {
+      key: 'DefaultType',
+      get: function get() {
+        return DefaultType;
+      }
+    }]);
+
+    return Popover;
+  }(Tooltip);
+
+  /**
+   * ------------------------------------------------------------------------
+   * jQuery
+   * ------------------------------------------------------------------------
+   */
+
+  $.fn[NAME] = Popover._jQueryInterface;
+  $.fn[NAME].Constructor = Popover;
+  $.fn[NAME].noConflict = function () {
+    $.fn[NAME] = JQUERY_NO_CONFLICT;
+    return Popover._jQueryInterface;
+  };
+
+  return Popover;
+}(jQuery);
+
+}();
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
new file mode 100644
index 0000000..f8559b3
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js
@@ -0,0 +1,7 @@
+/*!
+ * Bootstrap v4.0.0-alpha.5 (https://getbootstrap.com)
+ * Copyright 2011-2017 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
+ * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
+ */
+if("undefined"==typeof jQuery)throw new Error("Bootstrap's JavaScript requires jQuery");+function(a){var b=a.fn.jquery.split(" ")[0].split(".");if(b[0]<2&&b[1]<9||1==b[0]&&9==b[1]&&b[2]<1||b[0]>=4)throw new Error("Bootstrap's JavaScript requires at least jQuery v1.9.1 but less than v4.0.0")}(jQuery),+function(){function a(a,b){if(!a)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!b||"object"!=typeof b&&"function"!=typeof b?a:b}function b(a,b){ [...]
+DROPDOWN_TOGGLE:".dropdown-toggle",DROPDOWN_ACTIVE_CHILD:"> .dropdown-menu .active"},o=function(){function b(a){c(this,b),this._element=a}return b.prototype.show=function(){var b=this;if(!this._element.parentNode||this._element.parentNode.nodeType!==Node.ELEMENT_NODE||!a(this._element).hasClass(m.ACTIVE)){var c=void 0,d=void 0,e=a(this._element).closest(n.UL)[0],g=f.getSelectorFromElement(this._element);e&&(d=a.makeArray(a(e).find(n.ACTIVE)),d=d[d.length-1]);var h=a.Event(l.HIDE,{related [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/css/font-awesome.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/css/font-awesome.css
new file mode 100644
index 0000000..bb0fe51
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/css/font-awesome.css
@@ -0,0 +1,2178 @@
+/*!
+ *  Font Awesome 4.6.1 by @davegandy - http://fontawesome.io - @fontawesome
+ *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */
+/* FONT PATH
+ * -------------------------- */
+@font-face {
+  font-family: 'FontAwesome';
+  src: url('../fonts/fontawesome-webfont.eot?v=4.6.1');
+  src: url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.1') format('embedded-opentype'), url('../fonts/fontawesome-webfont.woff2?v=4.6.1') format('woff2'), url('../fonts/fontawesome-webfont.woff?v=4.6.1') format('woff'), url('../fonts/fontawesome-webfont.ttf?v=4.6.1') format('truetype'), url('../fonts/fontawesome-webfont.svg?v=4.6.1#fontawesomeregular') format('svg');
+  font-weight: normal;
+  font-style: normal;
+}
+.fa {
+  display: inline-block;
+  font: normal normal normal 14px/1 FontAwesome;
+  font-size: inherit;
+  text-rendering: auto;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
+}
+/* makes the font 33% larger relative to the icon container */
+.fa-lg {
+  font-size: 1.33333333em;
+  line-height: 0.75em;
+  vertical-align: -15%;
+}
+.fa-2x {
+  font-size: 2em;
+}
+.fa-3x {
+  font-size: 3em;
+}
+.fa-4x {
+  font-size: 4em;
+}
+.fa-5x {
+  font-size: 5em;
+}
+.fa-fw {
+  width: 1.28571429em;
+  text-align: center;
+}
+.fa-ul {
+  padding-left: 0;
+  margin-left: 2.14285714em;
+  list-style-type: none;
+}
+.fa-ul > li {
+  position: relative;
+}
+.fa-li {
+  position: absolute;
+  left: -2.14285714em;
+  width: 2.14285714em;
+  top: 0.14285714em;
+  text-align: center;
+}
+.fa-li.fa-lg {
+  left: -1.85714286em;
+}
+.fa-border {
+  padding: .2em .25em .15em;
+  border: solid 0.08em #eeeeee;
+  border-radius: .1em;
+}
+.fa-pull-left {
+  float: left;
+}
+.fa-pull-right {
+  float: right;
+}
+.fa.fa-pull-left {
+  margin-right: .3em;
+}
+.fa.fa-pull-right {
+  margin-left: .3em;
+}
+/* Deprecated as of 4.4.0 */
+.pull-right {
+  float: right;
+}
+.pull-left {
+  float: left;
+}
+.fa.pull-left {
+  margin-right: .3em;
+}
+.fa.pull-right {
+  margin-left: .3em;
+}
+.fa-spin {
+  -webkit-animation: fa-spin 2s infinite linear;
+  animation: fa-spin 2s infinite linear;
+}
+.fa-pulse {
+  -webkit-animation: fa-spin 1s infinite steps(8);
+  animation: fa-spin 1s infinite steps(8);
+}
+@-webkit-keyframes fa-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+@keyframes fa-spin {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(359deg);
+    transform: rotate(359deg);
+  }
+}
+.fa-rotate-90 {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";
+  -webkit-transform: rotate(90deg);
+  -ms-transform: rotate(90deg);
+  transform: rotate(90deg);
+}
+.fa-rotate-180 {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2)";
+  -webkit-transform: rotate(180deg);
+  -ms-transform: rotate(180deg);
+  transform: rotate(180deg);
+}
+.fa-rotate-270 {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=3)";
+  -webkit-transform: rotate(270deg);
+  -ms-transform: rotate(270deg);
+  transform: rotate(270deg);
+}
+.fa-flip-horizontal {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";
+  -webkit-transform: scale(-1, 1);
+  -ms-transform: scale(-1, 1);
+  transform: scale(-1, 1);
+}
+.fa-flip-vertical {
+  -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=2, mirror=1)";
+  -webkit-transform: scale(1, -1);
+  -ms-transform: scale(1, -1);
+  transform: scale(1, -1);
+}
+:root .fa-rotate-90,
+:root .fa-rotate-180,
+:root .fa-rotate-270,
+:root .fa-flip-horizontal,
+:root .fa-flip-vertical {
+  filter: none;
+}
+.fa-stack {
+  position: relative;
+  display: inline-block;
+  width: 2em;
+  height: 2em;
+  line-height: 2em;
+  vertical-align: middle;
+}
+.fa-stack-1x,
+.fa-stack-2x {
+  position: absolute;
+  left: 0;
+  width: 100%;
+  text-align: center;
+}
+.fa-stack-1x {
+  line-height: inherit;
+}
+.fa-stack-2x {
+  font-size: 2em;
+}
+.fa-inverse {
+  color: #ffffff;
+}
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+   readers do not read off random characters that represent icons */
+.fa-glass:before {
+  content: "\f000";
+}
+.fa-music:before {
+  content: "\f001";
+}
+.fa-search:before {
+  content: "\f002";
+}
+.fa-envelope-o:before {
+  content: "\f003";
+}
+.fa-heart:before {
+  content: "\f004";
+}
+.fa-star:before {
+  content: "\f005";
+}
+.fa-star-o:before {
+  content: "\f006";
+}
+.fa-user:before {
+  content: "\f007";
+}
+.fa-film:before {
+  content: "\f008";
+}
+.fa-th-large:before {
+  content: "\f009";
+}
+.fa-th:before {
+  content: "\f00a";
+}
+.fa-th-list:before {
+  content: "\f00b";
+}
+.fa-check:before {
+  content: "\f00c";
+}
+.fa-remove:before,
+.fa-close:before,
+.fa-times:before {
+  content: "\f00d";
+}
+.fa-search-plus:before {
+  content: "\f00e";
+}
+.fa-search-minus:before {
+  content: "\f010";
+}
+.fa-power-off:before {
+  content: "\f011";
+}
+.fa-signal:before {
+  content: "\f012";
+}
+.fa-gear:before,
+.fa-cog:before {
+  content: "\f013";
+}
+.fa-trash-o:before {
+  content: "\f014";
+}
+.fa-home:before {
+  content: "\f015";
+}
+.fa-file-o:before {
+  content: "\f016";
+}
+.fa-clock-o:before {
+  content: "\f017";
+}
+.fa-road:before {
+  content: "\f018";
+}
+.fa-download:before {
+  content: "\f019";
+}
+.fa-arrow-circle-o-down:before {
+  content: "\f01a";
+}
+.fa-arrow-circle-o-up:before {
+  content: "\f01b";
+}
+.fa-inbox:before {
+  content: "\f01c";
+}
+.fa-play-circle-o:before {
+  content: "\f01d";
+}
+.fa-rotate-right:before,
+.fa-repeat:before {
+  content: "\f01e";
+}
+.fa-refresh:before {
+  content: "\f021";
+}
+.fa-list-alt:before {
+  content: "\f022";
+}
+.fa-lock:before {
+  content: "\f023";
+}
+.fa-flag:before {
+  content: "\f024";
+}
+.fa-headphones:before {
+  content: "\f025";
+}
+.fa-volume-off:before {
+  content: "\f026";
+}
+.fa-volume-down:before {
+  content: "\f027";
+}
+.fa-volume-up:before {
+  content: "\f028";
+}
+.fa-qrcode:before {
+  content: "\f029";
+}
+.fa-barcode:before {
+  content: "\f02a";
+}
+.fa-tag:before {
+  content: "\f02b";
+}
+.fa-tags:before {
+  content: "\f02c";
+}
+.fa-book:before {
+  content: "\f02d";
+}
+.fa-bookmark:before {
+  content: "\f02e";
+}
+.fa-print:before {
+  content: "\f02f";
+}
+.fa-camera:before {
+  content: "\f030";
+}
+.fa-font:before {
+  content: "\f031";
+}
+.fa-bold:before {
+  content: "\f032";
+}
+.fa-italic:before {
+  content: "\f033";
+}
+.fa-text-height:before {
+  content: "\f034";
+}
+.fa-text-width:before {
+  content: "\f035";
+}
+.fa-align-left:before {
+  content: "\f036";
+}
+.fa-align-center:before {
+  content: "\f037";
+}
+.fa-align-right:before {
+  content: "\f038";
+}
+.fa-align-justify:before {
+  content: "\f039";
+}
+.fa-list:before {
+  content: "\f03a";
+}
+.fa-dedent:before,
+.fa-outdent:before {
+  content: "\f03b";
+}
+.fa-indent:before {
+  content: "\f03c";
+}
+.fa-video-camera:before {
+  content: "\f03d";
+}
+.fa-photo:before,
+.fa-image:before,
+.fa-picture-o:before {
+  content: "\f03e";
+}
+.fa-pencil:before {
+  content: "\f040";
+}
+.fa-map-marker:before {
+  content: "\f041";
+}
+.fa-adjust:before {
+  content: "\f042";
+}
+.fa-tint:before {
+  content: "\f043";
+}
+.fa-edit:before,
+.fa-pencil-square-o:before {
+  content: "\f044";
+}
+.fa-share-square-o:before {
+  content: "\f045";
+}
+.fa-check-square-o:before {
+  content: "\f046";
+}
+.fa-arrows:before {
+  content: "\f047";
+}
+.fa-step-backward:before {
+  content: "\f048";
+}
+.fa-fast-backward:before {
+  content: "\f049";
+}
+.fa-backward:before {
+  content: "\f04a";
+}
+.fa-play:before {
+  content: "\f04b";
+}
+.fa-pause:before {
+  content: "\f04c";
+}
+.fa-stop:before {
+  content: "\f04d";
+}
+.fa-forward:before {
+  content: "\f04e";
+}
+.fa-fast-forward:before {
+  content: "\f050";
+}
+.fa-step-forward:before {
+  content: "\f051";
+}
+.fa-eject:before {
+  content: "\f052";
+}
+.fa-chevron-left:before {
+  content: "\f053";
+}
+.fa-chevron-right:before {
+  content: "\f054";
+}
+.fa-plus-circle:before {
+  content: "\f055";
+}
+.fa-minus-circle:before {
+  content: "\f056";
+}
+.fa-times-circle:before {
+  content: "\f057";
+}
+.fa-check-circle:before {
+  content: "\f058";
+}
+.fa-question-circle:before {
+  content: "\f059";
+}
+.fa-info-circle:before {
+  content: "\f05a";
+}
+.fa-crosshairs:before {
+  content: "\f05b";
+}
+.fa-times-circle-o:before {
+  content: "\f05c";
+}
+.fa-check-circle-o:before {
+  content: "\f05d";
+}
+.fa-ban:before {
+  content: "\f05e";
+}
+.fa-arrow-left:before {
+  content: "\f060";
+}
+.fa-arrow-right:before {
+  content: "\f061";
+}
+.fa-arrow-up:before {
+  content: "\f062";
+}
+.fa-arrow-down:before {
+  content: "\f063";
+}
+.fa-mail-forward:before,
+.fa-share:before {
+  content: "\f064";
+}
+.fa-expand:before {
+  content: "\f065";
+}
+.fa-compress:before {
+  content: "\f066";
+}
+.fa-plus:before {
+  content: "\f067";
+}
+.fa-minus:before {
+  content: "\f068";
+}
+.fa-asterisk:before {
+  content: "\f069";
+}
+.fa-exclamation-circle:before {
+  content: "\f06a";
+}
+.fa-gift:before {
+  content: "\f06b";
+}
+.fa-leaf:before {
+  content: "\f06c";
+}
+.fa-fire:before {
+  content: "\f06d";
+}
+.fa-eye:before {
+  content: "\f06e";
+}
+.fa-eye-slash:before {
+  content: "\f070";
+}
+.fa-warning:before,
+.fa-exclamation-triangle:before {
+  content: "\f071";
+}
+.fa-plane:before {
+  content: "\f072";
+}
+.fa-calendar:before {
+  content: "\f073";
+}
+.fa-random:before {
+  content: "\f074";
+}
+.fa-comment:before {
+  content: "\f075";
+}
+.fa-magnet:before {
+  content: "\f076";
+}
+.fa-chevron-up:before {
+  content: "\f077";
+}
+.fa-chevron-down:before {
+  content: "\f078";
+}
+.fa-retweet:before {
+  content: "\f079";
+}
+.fa-shopping-cart:before {
+  content: "\f07a";
+}
+.fa-folder:before {
+  content: "\f07b";
+}
+.fa-folder-open:before {
+  content: "\f07c";
+}
+.fa-arrows-v:before {
+  content: "\f07d";
+}
+.fa-arrows-h:before {
+  content: "\f07e";
+}
+.fa-bar-chart-o:before,
+.fa-bar-chart:before {
+  content: "\f080";
+}
+.fa-twitter-square:before {
+  content: "\f081";
+}
+.fa-facebook-square:before {
+  content: "\f082";
+}
+.fa-camera-retro:before {
+  content: "\f083";
+}
+.fa-key:before {
+  content: "\f084";
+}
+.fa-gears:before,
+.fa-cogs:before {
+  content: "\f085";
+}
+.fa-comments:before {
+  content: "\f086";
+}
+.fa-thumbs-o-up:before {
+  content: "\f087";
+}
+.fa-thumbs-o-down:before {
+  content: "\f088";
+}
+.fa-star-half:before {
+  content: "\f089";
+}
+.fa-heart-o:before {
+  content: "\f08a";
+}
+.fa-sign-out:before {
+  content: "\f08b";
+}
+.fa-linkedin-square:before {
+  content: "\f08c";
+}
+.fa-thumb-tack:before {
+  content: "\f08d";
+}
+.fa-external-link:before {
+  content: "\f08e";
+}
+.fa-sign-in:before {
+  content: "\f090";
+}
+.fa-trophy:before {
+  content: "\f091";
+}
+.fa-github-square:before {
+  content: "\f092";
+}
+.fa-upload:before {
+  content: "\f093";
+}
+.fa-lemon-o:before {
+  content: "\f094";
+}
+.fa-phone:before {
+  content: "\f095";
+}
+.fa-square-o:before {
+  content: "\f096";
+}
+.fa-bookmark-o:before {
+  content: "\f097";
+}
+.fa-phone-square:before {
+  content: "\f098";
+}
+.fa-twitter:before {
+  content: "\f099";
+}
+.fa-facebook-f:before,
+.fa-facebook:before {
+  content: "\f09a";
+}
+.fa-github:before {
+  content: "\f09b";
+}
+.fa-unlock:before {
+  content: "\f09c";
+}
+.fa-credit-card:before {
+  content: "\f09d";
+}
+.fa-feed:before,
+.fa-rss:before {
+  content: "\f09e";
+}
+.fa-hdd-o:before {
+  content: "\f0a0";
+}
+.fa-bullhorn:before {
+  content: "\f0a1";
+}
+.fa-bell:before {
+  content: "\f0f3";
+}
+.fa-certificate:before {
+  content: "\f0a3";
+}
+.fa-hand-o-right:before {
+  content: "\f0a4";
+}
+.fa-hand-o-left:before {
+  content: "\f0a5";
+}
+.fa-hand-o-up:before {
+  content: "\f0a6";
+}
+.fa-hand-o-down:before {
+  content: "\f0a7";
+}
+.fa-arrow-circle-left:before {
+  content: "\f0a8";
+}
+.fa-arrow-circle-right:before {
+  content: "\f0a9";
+}
+.fa-arrow-circle-up:before {
+  content: "\f0aa";
+}
+.fa-arrow-circle-down:before {
+  content: "\f0ab";
+}
+.fa-globe:before {
+  content: "\f0ac";
+}
+.fa-wrench:before {
+  content: "\f0ad";
+}
+.fa-tasks:before {
+  content: "\f0ae";
+}
+.fa-filter:before {
+  content: "\f0b0";
+}
+.fa-briefcase:before {
+  content: "\f0b1";
+}
+.fa-arrows-alt:before {
+  content: "\f0b2";
+}
+.fa-group:before,
+.fa-users:before {
+  content: "\f0c0";
+}
+.fa-chain:before,
+.fa-link:before {
+  content: "\f0c1";
+}
+.fa-cloud:before {
+  content: "\f0c2";
+}
+.fa-flask:before {
+  content: "\f0c3";
+}
+.fa-cut:before,
+.fa-scissors:before {
+  content: "\f0c4";
+}
+.fa-copy:before,
+.fa-files-o:before {
+  content: "\f0c5";
+}
+.fa-paperclip:before {
+  content: "\f0c6";
+}
+.fa-save:before,
+.fa-floppy-o:before {
+  content: "\f0c7";
+}
+.fa-square:before {
+  content: "\f0c8";
+}
+.fa-navicon:before,
+.fa-reorder:before,
+.fa-bars:before {
+  content: "\f0c9";
+}
+.fa-list-ul:before {
+  content: "\f0ca";
+}
+.fa-list-ol:before {
+  content: "\f0cb";
+}
+.fa-strikethrough:before {
+  content: "\f0cc";
+}
+.fa-underline:before {
+  content: "\f0cd";
+}
+.fa-table:before {
+  content: "\f0ce";
+}
+.fa-magic:before {
+  content: "\f0d0";
+}
+.fa-truck:before {
+  content: "\f0d1";
+}
+.fa-pinterest:before {
+  content: "\f0d2";
+}
+.fa-pinterest-square:before {
+  content: "\f0d3";
+}
+.fa-google-plus-square:before {
+  content: "\f0d4";
+}
+.fa-google-plus:before {
+  content: "\f0d5";
+}
+.fa-money:before {
+  content: "\f0d6";
+}
+.fa-caret-down:before {
+  content: "\f0d7";
+}
+.fa-caret-up:before {
+  content: "\f0d8";
+}
+.fa-caret-left:before {
+  content: "\f0d9";
+}
+.fa-caret-right:before {
+  content: "\f0da";
+}
+.fa-columns:before {
+  content: "\f0db";
+}
+.fa-unsorted:before,
+.fa-sort:before {
+  content: "\f0dc";
+}
+.fa-sort-down:before,
+.fa-sort-desc:before {
+  content: "\f0dd";
+}
+.fa-sort-up:before,
+.fa-sort-asc:before {
+  content: "\f0de";
+}
+.fa-envelope:before {
+  content: "\f0e0";
+}
+.fa-linkedin:before {
+  content: "\f0e1";
+}
+.fa-rotate-left:before,
+.fa-undo:before {
+  content: "\f0e2";
+}
+.fa-legal:before,
+.fa-gavel:before {
+  content: "\f0e3";
+}
+.fa-dashboard:before,
+.fa-tachometer:before {
+  content: "\f0e4";
+}
+.fa-comment-o:before {
+  content: "\f0e5";
+}
+.fa-comments-o:before {
+  content: "\f0e6";
+}
+.fa-flash:before,
+.fa-bolt:before {
+  content: "\f0e7";
+}
+.fa-sitemap:before {
+  content: "\f0e8";
+}
+.fa-umbrella:before {
+  content: "\f0e9";
+}
+.fa-paste:before,
+.fa-clipboard:before {
+  content: "\f0ea";
+}
+.fa-lightbulb-o:before {
+  content: "\f0eb";
+}
+.fa-exchange:before {
+  content: "\f0ec";
+}
+.fa-cloud-download:before {
+  content: "\f0ed";
+}
+.fa-cloud-upload:before {
+  content: "\f0ee";
+}
+.fa-user-md:before {
+  content: "\f0f0";
+}
+.fa-stethoscope:before {
+  content: "\f0f1";
+}
+.fa-suitcase:before {
+  content: "\f0f2";
+}
+.fa-bell-o:before {
+  content: "\f0a2";
+}
+.fa-coffee:before {
+  content: "\f0f4";
+}
+.fa-cutlery:before {
+  content: "\f0f5";
+}
+.fa-file-text-o:before {
+  content: "\f0f6";
+}
+.fa-building-o:before {
+  content: "\f0f7";
+}
+.fa-hospital-o:before {
+  content: "\f0f8";
+}
+.fa-ambulance:before {
+  content: "\f0f9";
+}
+.fa-medkit:before {
+  content: "\f0fa";
+}
+.fa-fighter-jet:before {
+  content: "\f0fb";
+}
+.fa-beer:before {
+  content: "\f0fc";
+}
+.fa-h-square:before {
+  content: "\f0fd";
+}
+.fa-plus-square:before {
+  content: "\f0fe";
+}
+.fa-angle-double-left:before {
+  content: "\f100";
+}
+.fa-angle-double-right:before {
+  content: "\f101";
+}
+.fa-angle-double-up:before {
+  content: "\f102";
+}
+.fa-angle-double-down:before {
+  content: "\f103";
+}
+.fa-angle-left:before {
+  content: "\f104";
+}
+.fa-angle-right:before {
+  content: "\f105";
+}
+.fa-angle-up:before {
+  content: "\f106";
+}
+.fa-angle-down:before {
+  content: "\f107";
+}
+.fa-desktop:before {
+  content: "\f108";
+}
+.fa-laptop:before {
+  content: "\f109";
+}
+.fa-tablet:before {
+  content: "\f10a";
+}
+.fa-mobile-phone:before,
+.fa-mobile:before {
+  content: "\f10b";
+}
+.fa-circle-o:before {
+  content: "\f10c";
+}
+.fa-quote-left:before {
+  content: "\f10d";
+}
+.fa-quote-right:before {
+  content: "\f10e";
+}
+.fa-spinner:before {
+  content: "\f110";
+}
+.fa-circle:before {
+  content: "\f111";
+}
+.fa-mail-reply:before,
+.fa-reply:before {
+  content: "\f112";
+}
+.fa-github-alt:before {
+  content: "\f113";
+}
+.fa-folder-o:before {
+  content: "\f114";
+}
+.fa-folder-open-o:before {
+  content: "\f115";
+}
+.fa-smile-o:before {
+  content: "\f118";
+}
+.fa-frown-o:before {
+  content: "\f119";
+}
+.fa-meh-o:before {
+  content: "\f11a";
+}
+.fa-gamepad:before {
+  content: "\f11b";
+}
+.fa-keyboard-o:before {
+  content: "\f11c";
+}
+.fa-flag-o:before {
+  content: "\f11d";
+}
+.fa-flag-checkered:before {
+  content: "\f11e";
+}
+.fa-terminal:before {
+  content: "\f120";
+}
+.fa-code:before {
+  content: "\f121";
+}
+.fa-mail-reply-all:before,
+.fa-reply-all:before {
+  content: "\f122";
+}
+.fa-star-half-empty:before,
+.fa-star-half-full:before,
+.fa-star-half-o:before {
+  content: "\f123";
+}
+.fa-location-arrow:before {
+  content: "\f124";
+}
+.fa-crop:before {
+  content: "\f125";
+}
+.fa-code-fork:before {
+  content: "\f126";
+}
+.fa-unlink:before,
+.fa-chain-broken:before {
+  content: "\f127";
+}
+.fa-question:before {
+  content: "\f128";
+}
+.fa-info:before {
+  content: "\f129";
+}
+.fa-exclamation:before {
+  content: "\f12a";
+}
+.fa-superscript:before {
+  content: "\f12b";
+}
+.fa-subscript:before {
+  content: "\f12c";
+}
+.fa-eraser:before {
+  content: "\f12d";
+}
+.fa-puzzle-piece:before {
+  content: "\f12e";
+}
+.fa-microphone:before {
+  content: "\f130";
+}
+.fa-microphone-slash:before {
+  content: "\f131";
+}
+.fa-shield:before {
+  content: "\f132";
+}
+.fa-calendar-o:before {
+  content: "\f133";
+}
+.fa-fire-extinguisher:before {
+  content: "\f134";
+}
+.fa-rocket:before {
+  content: "\f135";
+}
+.fa-maxcdn:before {
+  content: "\f136";
+}
+.fa-chevron-circle-left:before {
+  content: "\f137";
+}
+.fa-chevron-circle-right:before {
+  content: "\f138";
+}
+.fa-chevron-circle-up:before {
+  content: "\f139";
+}
+.fa-chevron-circle-down:before {
+  content: "\f13a";
+}
+.fa-html5:before {
+  content: "\f13b";
+}
+.fa-css3:before {
+  content: "\f13c";
+}
+.fa-anchor:before {
+  content: "\f13d";
+}
+.fa-unlock-alt:before {
+  content: "\f13e";
+}
+.fa-bullseye:before {
+  content: "\f140";
+}
+.fa-ellipsis-h:before {
+  content: "\f141";
+}
+.fa-ellipsis-v:before {
+  content: "\f142";
+}
+.fa-rss-square:before {
+  content: "\f143";
+}
+.fa-play-circle:before {
+  content: "\f144";
+}
+.fa-ticket:before {
+  content: "\f145";
+}
+.fa-minus-square:before {
+  content: "\f146";
+}
+.fa-minus-square-o:before {
+  content: "\f147";
+}
+.fa-level-up:before {
+  content: "\f148";
+}
+.fa-level-down:before {
+  content: "\f149";
+}
+.fa-check-square:before {
+  content: "\f14a";
+}
+.fa-pencil-square:before {
+  content: "\f14b";
+}
+.fa-external-link-square:before {
+  content: "\f14c";
+}
+.fa-share-square:before {
+  content: "\f14d";
+}
+.fa-compass:before {
+  content: "\f14e";
+}
+.fa-toggle-down:before,
+.fa-caret-square-o-down:before {
+  content: "\f150";
+}
+.fa-toggle-up:before,
+.fa-caret-square-o-up:before {
+  content: "\f151";
+}
+.fa-toggle-right:before,
+.fa-caret-square-o-right:before {
+  content: "\f152";
+}
+.fa-euro:before,
+.fa-eur:before {
+  content: "\f153";
+}
+.fa-gbp:before {
+  content: "\f154";
+}
+.fa-dollar:before,
+.fa-usd:before {
+  content: "\f155";
+}
+.fa-rupee:before,
+.fa-inr:before {
+  content: "\f156";
+}
+.fa-cny:before,
+.fa-rmb:before,
+.fa-yen:before,
+.fa-jpy:before {
+  content: "\f157";
+}
+.fa-ruble:before,
+.fa-rouble:before,
+.fa-rub:before {
+  content: "\f158";
+}
+.fa-won:before,
+.fa-krw:before {
+  content: "\f159";
+}
+.fa-bitcoin:before,
+.fa-btc:before {
+  content: "\f15a";
+}
+.fa-file:before {
+  content: "\f15b";
+}
+.fa-file-text:before {
+  content: "\f15c";
+}
+.fa-sort-alpha-asc:before {
+  content: "\f15d";
+}
+.fa-sort-alpha-desc:before {
+  content: "\f15e";
+}
+.fa-sort-amount-asc:before {
+  content: "\f160";
+}
+.fa-sort-amount-desc:before {
+  content: "\f161";
+}
+.fa-sort-numeric-asc:before {
+  content: "\f162";
+}
+.fa-sort-numeric-desc:before {
+  content: "\f163";
+}
+.fa-thumbs-up:before {
+  content: "\f164";
+}
+.fa-thumbs-down:before {
+  content: "\f165";
+}
+.fa-youtube-square:before {
+  content: "\f166";
+}
+.fa-youtube:before {
+  content: "\f167";
+}
+.fa-xing:before {
+  content: "\f168";
+}
+.fa-xing-square:before {
+  content: "\f169";
+}
+.fa-youtube-play:before {
+  content: "\f16a";
+}
+.fa-dropbox:before {
+  content: "\f16b";
+}
+.fa-stack-overflow:before {
+  content: "\f16c";
+}
+.fa-instagram:before {
+  content: "\f16d";
+}
+.fa-flickr:before {
+  content: "\f16e";
+}
+.fa-adn:before {
+  content: "\f170";
+}
+.fa-bitbucket:before {
+  content: "\f171";
+}
+.fa-bitbucket-square:before {
+  content: "\f172";
+}
+.fa-tumblr:before {
+  content: "\f173";
+}
+.fa-tumblr-square:before {
+  content: "\f174";
+}
+.fa-long-arrow-down:before {
+  content: "\f175";
+}
+.fa-long-arrow-up:before {
+  content: "\f176";
+}
+.fa-long-arrow-left:before {
+  content: "\f177";
+}
+.fa-long-arrow-right:before {
+  content: "\f178";
+}
+.fa-apple:before {
+  content: "\f179";
+}
+.fa-windows:before {
+  content: "\f17a";
+}
+.fa-android:before {
+  content: "\f17b";
+}
+.fa-linux:before {
+  content: "\f17c";
+}
+.fa-dribbble:before {
+  content: "\f17d";
+}
+.fa-skype:before {
+  content: "\f17e";
+}
+.fa-foursquare:before {
+  content: "\f180";
+}
+.fa-trello:before {
+  content: "\f181";
+}
+.fa-female:before {
+  content: "\f182";
+}
+.fa-male:before {
+  content: "\f183";
+}
+.fa-gittip:before,
+.fa-gratipay:before {
+  content: "\f184";
+}
+.fa-sun-o:before {
+  content: "\f185";
+}
+.fa-moon-o:before {
+  content: "\f186";
+}
+.fa-archive:before {
+  content: "\f187";
+}
+.fa-bug:before {
+  content: "\f188";
+}
+.fa-vk:before {
+  content: "\f189";
+}
+.fa-weibo:before {
+  content: "\f18a";
+}
+.fa-renren:before {
+  content: "\f18b";
+}
+.fa-pagelines:before {
+  content: "\f18c";
+}
+.fa-stack-exchange:before {
+  content: "\f18d";
+}
+.fa-arrow-circle-o-right:before {
+  content: "\f18e";
+}
+.fa-arrow-circle-o-left:before {
+  content: "\f190";
+}
+.fa-toggle-left:before,
+.fa-caret-square-o-left:before {
+  content: "\f191";
+}
+.fa-dot-circle-o:before {
+  content: "\f192";
+}
+.fa-wheelchair:before {
+  content: "\f193";
+}
+.fa-vimeo-square:before {
+  content: "\f194";
+}
+.fa-turkish-lira:before,
+.fa-try:before {
+  content: "\f195";
+}
+.fa-plus-square-o:before {
+  content: "\f196";
+}
+.fa-space-shuttle:before {
+  content: "\f197";
+}
+.fa-slack:before {
+  content: "\f198";
+}
+.fa-envelope-square:before {
+  content: "\f199";
+}
+.fa-wordpress:before {
+  content: "\f19a";
+}
+.fa-openid:before {
+  content: "\f19b";
+}
+.fa-institution:before,
+.fa-bank:before,
+.fa-university:before {
+  content: "\f19c";
+}
+.fa-mortar-board:before,
+.fa-graduation-cap:before {
+  content: "\f19d";
+}
+.fa-yahoo:before {
+  content: "\f19e";
+}
+.fa-google:before {
+  content: "\f1a0";
+}
+.fa-reddit:before {
+  content: "\f1a1";
+}
+.fa-reddit-square:before {
+  content: "\f1a2";
+}
+.fa-stumbleupon-circle:before {
+  content: "\f1a3";
+}
+.fa-stumbleupon:before {
+  content: "\f1a4";
+}
+.fa-delicious:before {
+  content: "\f1a5";
+}
+.fa-digg:before {
+  content: "\f1a6";
+}
+.fa-pied-piper:before {
+  content: "\f1a7";
+}
+.fa-pied-piper-alt:before {
+  content: "\f1a8";
+}
+.fa-drupal:before {
+  content: "\f1a9";
+}
+.fa-joomla:before {
+  content: "\f1aa";
+}
+.fa-language:before {
+  content: "\f1ab";
+}
+.fa-fax:before {
+  content: "\f1ac";
+}
+.fa-building:before {
+  content: "\f1ad";
+}
+.fa-child:before {
+  content: "\f1ae";
+}
+.fa-paw:before {
+  content: "\f1b0";
+}
+.fa-spoon:before {
+  content: "\f1b1";
+}
+.fa-cube:before {
+  content: "\f1b2";
+}
+.fa-cubes:before {
+  content: "\f1b3";
+}
+.fa-behance:before {
+  content: "\f1b4";
+}
+.fa-behance-square:before {
+  content: "\f1b5";
+}
+.fa-steam:before {
+  content: "\f1b6";
+}
+.fa-steam-square:before {
+  content: "\f1b7";
+}
+.fa-recycle:before {
+  content: "\f1b8";
+}
+.fa-automobile:before,
+.fa-car:before {
+  content: "\f1b9";
+}
+.fa-cab:before,
+.fa-taxi:before {
+  content: "\f1ba";
+}
+.fa-tree:before {
+  content: "\f1bb";
+}
+.fa-spotify:before {
+  content: "\f1bc";
+}
+.fa-deviantart:before {
+  content: "\f1bd";
+}
+.fa-soundcloud:before {
+  content: "\f1be";
+}
+.fa-database:before {
+  content: "\f1c0";
+}
+.fa-file-pdf-o:before {
+  content: "\f1c1";
+}
+.fa-file-word-o:before {
+  content: "\f1c2";
+}
+.fa-file-excel-o:before {
+  content: "\f1c3";
+}
+.fa-file-powerpoint-o:before {
+  content: "\f1c4";
+}
+.fa-file-photo-o:before,
+.fa-file-picture-o:before,
+.fa-file-image-o:before {
+  content: "\f1c5";
+}
+.fa-file-zip-o:before,
+.fa-file-archive-o:before {
+  content: "\f1c6";
+}
+.fa-file-sound-o:before,
+.fa-file-audio-o:before {
+  content: "\f1c7";
+}
+.fa-file-movie-o:before,
+.fa-file-video-o:before {
+  content: "\f1c8";
+}
+.fa-file-code-o:before {
+  content: "\f1c9";
+}
+.fa-vine:before {
+  content: "\f1ca";
+}
+.fa-codepen:before {
+  content: "\f1cb";
+}
+.fa-jsfiddle:before {
+  content: "\f1cc";
+}
+.fa-life-bouy:before,
+.fa-life-buoy:before,
+.fa-life-saver:before,
+.fa-support:before,
+.fa-life-ring:before {
+  content: "\f1cd";
+}
+.fa-circle-o-notch:before {
+  content: "\f1ce";
+}
+.fa-ra:before,
+.fa-rebel:before {
+  content: "\f1d0";
+}
+.fa-ge:before,
+.fa-empire:before {
+  content: "\f1d1";
+}
+.fa-git-square:before {
+  content: "\f1d2";
+}
+.fa-git:before {
+  content: "\f1d3";
+}
+.fa-y-combinator-square:before,
+.fa-yc-square:before,
+.fa-hacker-news:before {
+  content: "\f1d4";
+}
+.fa-tencent-weibo:before {
+  content: "\f1d5";
+}
+.fa-qq:before {
+  content: "\f1d6";
+}
+.fa-wechat:before,
+.fa-weixin:before {
+  content: "\f1d7";
+}
+.fa-send:before,
+.fa-paper-plane:before {
+  content: "\f1d8";
+}
+.fa-send-o:before,
+.fa-paper-plane-o:before {
+  content: "\f1d9";
+}
+.fa-history:before {
+  content: "\f1da";
+}
+.fa-circle-thin:before {
+  content: "\f1db";
+}
+.fa-header:before {
+  content: "\f1dc";
+}
+.fa-paragraph:before {
+  content: "\f1dd";
+}
+.fa-sliders:before {
+  content: "\f1de";
+}
+.fa-share-alt:before {
+  content: "\f1e0";
+}
+.fa-share-alt-square:before {
+  content: "\f1e1";
+}
+.fa-bomb:before {
+  content: "\f1e2";
+}
+.fa-soccer-ball-o:before,
+.fa-futbol-o:before {
+  content: "\f1e3";
+}
+.fa-tty:before {
+  content: "\f1e4";
+}
+.fa-binoculars:before {
+  content: "\f1e5";
+}
+.fa-plug:before {
+  content: "\f1e6";
+}
+.fa-slideshare:before {
+  content: "\f1e7";
+}
+.fa-twitch:before {
+  content: "\f1e8";
+}
+.fa-yelp:before {
+  content: "\f1e9";
+}
+.fa-newspaper-o:before {
+  content: "\f1ea";
+}
+.fa-wifi:before {
+  content: "\f1eb";
+}
+.fa-calculator:before {
+  content: "\f1ec";
+}
+.fa-paypal:before {
+  content: "\f1ed";
+}
+.fa-google-wallet:before {
+  content: "\f1ee";
+}
+.fa-cc-visa:before {
+  content: "\f1f0";
+}
+.fa-cc-mastercard:before {
+  content: "\f1f1";
+}
+.fa-cc-discover:before {
+  content: "\f1f2";
+}
+.fa-cc-amex:before {
+  content: "\f1f3";
+}
+.fa-cc-paypal:before {
+  content: "\f1f4";
+}
+.fa-cc-stripe:before {
+  content: "\f1f5";
+}
+.fa-bell-slash:before {
+  content: "\f1f6";
+}
+.fa-bell-slash-o:before {
+  content: "\f1f7";
+}
+.fa-trash:before {
+  content: "\f1f8";
+}
+.fa-copyright:before {
+  content: "\f1f9";
+}
+.fa-at:before {
+  content: "\f1fa";
+}
+.fa-eyedropper:before {
+  content: "\f1fb";
+}
+.fa-paint-brush:before {
+  content: "\f1fc";
+}
+.fa-birthday-cake:before {
+  content: "\f1fd";
+}
+.fa-area-chart:before {
+  content: "\f1fe";
+}
+.fa-pie-chart:before {
+  content: "\f200";
+}
+.fa-line-chart:before {
+  content: "\f201";
+}
+.fa-lastfm:before {
+  content: "\f202";
+}
+.fa-lastfm-square:before {
+  content: "\f203";
+}
+.fa-toggle-off:before {
+  content: "\f204";
+}
+.fa-toggle-on:before {
+  content: "\f205";
+}
+.fa-bicycle:before {
+  content: "\f206";
+}
+.fa-bus:before {
+  content: "\f207";
+}
+.fa-ioxhost:before {
+  content: "\f208";
+}
+.fa-angellist:before {
+  content: "\f209";
+}
+.fa-cc:before {
+  content: "\f20a";
+}
+.fa-shekel:before,
+.fa-sheqel:before,
+.fa-ils:before {
+  content: "\f20b";
+}
+.fa-meanpath:before {
+  content: "\f20c";
+}
+.fa-buysellads:before {
+  content: "\f20d";
+}
+.fa-connectdevelop:before {
+  content: "\f20e";
+}
+.fa-dashcube:before {
+  content: "\f210";
+}
+.fa-forumbee:before {
+  content: "\f211";
+}
+.fa-leanpub:before {
+  content: "\f212";
+}
+.fa-sellsy:before {
+  content: "\f213";
+}
+.fa-shirtsinbulk:before {
+  content: "\f214";
+}
+.fa-simplybuilt:before {
+  content: "\f215";
+}
+.fa-skyatlas:before {
+  content: "\f216";
+}
+.fa-cart-plus:before {
+  content: "\f217";
+}
+.fa-cart-arrow-down:before {
+  content: "\f218";
+}
+.fa-diamond:before {
+  content: "\f219";
+}
+.fa-ship:before {
+  content: "\f21a";
+}
+.fa-user-secret:before {
+  content: "\f21b";
+}
+.fa-motorcycle:before {
+  content: "\f21c";
+}
+.fa-street-view:before {
+  content: "\f21d";
+}
+.fa-heartbeat:before {
+  content: "\f21e";
+}
+.fa-venus:before {
+  content: "\f221";
+}
+.fa-mars:before {
+  content: "\f222";
+}
+.fa-mercury:before {
+  content: "\f223";
+}
+.fa-intersex:before,
+.fa-transgender:before {
+  content: "\f224";
+}
+.fa-transgender-alt:before {
+  content: "\f225";
+}
+.fa-venus-double:before {
+  content: "\f226";
+}
+.fa-mars-double:before {
+  content: "\f227";
+}
+.fa-venus-mars:before {
+  content: "\f228";
+}
+.fa-mars-stroke:before {
+  content: "\f229";
+}
+.fa-mars-stroke-v:before {
+  content: "\f22a";
+}
+.fa-mars-stroke-h:before {
+  content: "\f22b";
+}
+.fa-neuter:before {
+  content: "\f22c";
+}
+.fa-genderless:before {
+  content: "\f22d";
+}
+.fa-facebook-official:before {
+  content: "\f230";
+}
+.fa-pinterest-p:before {
+  content: "\f231";
+}
+.fa-whatsapp:before {
+  content: "\f232";
+}
+.fa-server:before {
+  content: "\f233";
+}
+.fa-user-plus:before {
+  content: "\f234";
+}
+.fa-user-times:before {
+  content: "\f235";
+}
+.fa-hotel:before,
+.fa-bed:before {
+  content: "\f236";
+}
+.fa-viacoin:before {
+  content: "\f237";
+}
+.fa-train:before {
+  content: "\f238";
+}
+.fa-subway:before {
+  content: "\f239";
+}
+.fa-medium:before {
+  content: "\f23a";
+}
+.fa-yc:before,
+.fa-y-combinator:before {
+  content: "\f23b";
+}
+.fa-optin-monster:before {
+  content: "\f23c";
+}
+.fa-opencart:before {
+  content: "\f23d";
+}
+.fa-expeditedssl:before {
+  content: "\f23e";
+}
+.fa-battery-4:before,
+.fa-battery-full:before {
+  content: "\f240";
+}
+.fa-battery-3:before,
+.fa-battery-three-quarters:before {
+  content: "\f241";
+}
+.fa-battery-2:before,
+.fa-battery-half:before {
+  content: "\f242";
+}
+.fa-battery-1:before,
+.fa-battery-quarter:before {
+  content: "\f243";
+}
+.fa-battery-0:before,
+.fa-battery-empty:before {
+  content: "\f244";
+}
+.fa-mouse-pointer:before {
+  content: "\f245";
+}
+.fa-i-cursor:before {
+  content: "\f246";
+}
+.fa-object-group:before {
+  content: "\f247";
+}
+.fa-object-ungroup:before {
+  content: "\f248";
+}
+.fa-sticky-note:before {
+  content: "\f249";
+}
+.fa-sticky-note-o:before {
+  content: "\f24a";
+}
+.fa-cc-jcb:before {
+  content: "\f24b";
+}
+.fa-cc-diners-club:before {
+  content: "\f24c";
+}
+.fa-clone:before {
+  content: "\f24d";
+}
+.fa-balance-scale:before {
+  content: "\f24e";
+}
+.fa-hourglass-o:before {
+  content: "\f250";
+}
+.fa-hourglass-1:before,
+.fa-hourglass-start:before {
+  content: "\f251";
+}
+.fa-hourglass-2:before,
+.fa-hourglass-half:before {
+  content: "\f252";
+}
+.fa-hourglass-3:before,
+.fa-hourglass-end:before {
+  content: "\f253";
+}
+.fa-hourglass:before {
+  content: "\f254";
+}
+.fa-hand-grab-o:before,
+.fa-hand-rock-o:before {
+  content: "\f255";
+}
+.fa-hand-stop-o:before,
+.fa-hand-paper-o:before {
+  content: "\f256";
+}
+.fa-hand-scissors-o:before {
+  content: "\f257";
+}
+.fa-hand-lizard-o:before {
+  content: "\f258";
+}
+.fa-hand-spock-o:before {
+  content: "\f259";
+}
+.fa-hand-pointer-o:before {
+  content: "\f25a";
+}
+.fa-hand-peace-o:before {
+  content: "\f25b";
+}
+.fa-trademark:before {
+  content: "\f25c";
+}
+.fa-registered:before {
+  content: "\f25d";
+}
+.fa-creative-commons:before {
+  content: "\f25e";
+}
+.fa-gg:before {
+  content: "\f260";
+}
+.fa-gg-circle:before {
+  content: "\f261";
+}
+.fa-tripadvisor:before {
+  content: "\f262";
+}
+.fa-odnoklassniki:before {
+  content: "\f263";
+}
+.fa-odnoklassniki-square:before {
+  content: "\f264";
+}
+.fa-get-pocket:before {
+  content: "\f265";
+}
+.fa-wikipedia-w:before {
+  content: "\f266";
+}
+.fa-safari:before {
+  content: "\f267";
+}
+.fa-chrome:before {
+  content: "\f268";
+}
+.fa-firefox:before {
+  content: "\f269";
+}
+.fa-opera:before {
+  content: "\f26a";
+}
+.fa-internet-explorer:before {
+  content: "\f26b";
+}
+.fa-tv:before,
+.fa-television:before {
+  content: "\f26c";
+}
+.fa-contao:before {
+  content: "\f26d";
+}
+.fa-500px:before {
+  content: "\f26e";
+}
+.fa-amazon:before {
+  content: "\f270";
+}
+.fa-calendar-plus-o:before {
+  content: "\f271";
+}
+.fa-calendar-minus-o:before {
+  content: "\f272";
+}
+.fa-calendar-times-o:before {
+  content: "\f273";
+}
+.fa-calendar-check-o:before {
+  content: "\f274";
+}
+.fa-industry:before {
+  content: "\f275";
+}
+.fa-map-pin:before {
+  content: "\f276";
+}
+.fa-map-signs:before {
+  content: "\f277";
+}
+.fa-map-o:before {
+  content: "\f278";
+}
+.fa-map:before {
+  content: "\f279";
+}
+.fa-commenting:before {
+  content: "\f27a";
+}
+.fa-commenting-o:before {
+  content: "\f27b";
+}
+.fa-houzz:before {
+  content: "\f27c";
+}
+.fa-vimeo:before {
+  content: "\f27d";
+}
+.fa-black-tie:before {
+  content: "\f27e";
+}
+.fa-fonticons:before {
+  content: "\f280";
+}
+.fa-reddit-alien:before {
+  content: "\f281";
+}
+.fa-edge:before {
+  content: "\f282";
+}
+.fa-credit-card-alt:before {
+  content: "\f283";
+}
+.fa-codiepie:before {
+  content: "\f284";
+}
+.fa-modx:before {
+  content: "\f285";
+}
+.fa-fort-awesome:before {
+  content: "\f286";
+}
+.fa-usb:before {
+  content: "\f287";
+}
+.fa-product-hunt:before {
+  content: "\f288";
+}
+.fa-mixcloud:before {
+  content: "\f289";
+}
+.fa-scribd:before {
+  content: "\f28a";
+}
+.fa-pause-circle:before {
+  content: "\f28b";
+}
+.fa-pause-circle-o:before {
+  content: "\f28c";
+}
+.fa-stop-circle:before {
+  content: "\f28d";
+}
+.fa-stop-circle-o:before {
+  content: "\f28e";
+}
+.fa-shopping-bag:before {
+  content: "\f290";
+}
+.fa-shopping-basket:before {
+  content: "\f291";
+}
+.fa-hashtag:before {
+  content: "\f292";
+}
+.fa-bluetooth:before {
+  content: "\f293";
+}
+.fa-bluetooth-b:before {
+  content: "\f294";
+}
+.fa-percent:before {
+  content: "\f295";
+}
+.fa-gitlab:before {
+  content: "\f296";
+}
+.fa-wpbeginner:before {
+  content: "\f297";
+}
+.fa-wpforms:before {
+  content: "\f298";
+}
+.fa-envira:before {
+  content: "\f299";
+}
+.fa-universal-access:before {
+  content: "\f29a";
+}
+.fa-wheelchair-alt:before {
+  content: "\f29b";
+}
+.fa-question-circle-o:before {
+  content: "\f29c";
+}
+.fa-blind:before {
+  content: "\f29d";
+}
+.fa-audio-description:before {
+  content: "\f29e";
+}
+.fa-volume-control-phone:before {
+  content: "\f2a0";
+}
+.fa-braille:before {
+  content: "\f2a1";
+}
+.fa-assistive-listening-systems:before {
+  content: "\f2a2";
+}
+.fa-asl-interpreting:before,
+.fa-american-sign-language-interpreting:before {
+  content: "\f2a3";
+}
+.fa-deafness:before,
+.fa-hard-of-hearing:before,
+.fa-deaf:before {
+  content: "\f2a4";
+}
+.fa-glide:before {
+  content: "\f2a5";
+}
+.fa-glide-g:before {
+  content: "\f2a6";
+}
+.fa-signing:before,
+.fa-sign-language:before {
+  content: "\f2a7";
+}
+.fa-low-vision:before {
+  content: "\f2a8";
+}
+.fa-viadeo:before {
+  content: "\f2a9";
+}
+.fa-viadeo-square:before {
+  content: "\f2aa";
+}
+.fa-snapchat:before {
+  content: "\f2ab";
+}
+.fa-snapchat-ghost:before {
+  content: "\f2ac";
+}
+.fa-snapchat-square:before {
+  content: "\f2ad";
+}
+.sr-only {
+  position: absolute;
+  width: 1px;
+  height: 1px;
+  padding: 0;
+  margin: -1px;
+  overflow: hidden;
+  clip: rect(0, 0, 0, 0);
+  border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+  position: static;
+  width: auto;
+  height: auto;
+  margin: 0;
+  overflow: visible;
+  clip: auto;
+}
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/css/font-awesome.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/css/font-awesome.min.css
new file mode 100644
index 0000000..d794a99
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/css/font-awesome.min.css
@@ -0,0 +1,4 @@
+/*!
+ *  Font Awesome 4.6.1 by @davegandy - http://fontawesome.io - @fontawesome
+ *  License - http://fontawesome.io/license (Font: SIL OFL 1.1, CSS: MIT License)
+ */@font-face{font-family:'FontAwesome';src:url('../fonts/fontawesome-webfont.eot?v=4.6.1');src:url('../fonts/fontawesome-webfont.eot?#iefix&v=4.6.1') format('embedded-opentype'),url('../fonts/fontawesome-webfont.woff2?v=4.6.1') format('woff2'),url('../fonts/fontawesome-webfont.woff?v=4.6.1') format('woff'),url('../fonts/fontawesome-webfont.ttf?v=4.6.1') format('truetype'),url('../fonts/fontawesome-webfont.svg?v=4.6.1#fontawesomeregular') format('svg');font-weight:normal;font-style:norma [...]
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/FontAwesome.otf b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/FontAwesome.otf
new file mode 100644
index 0000000..59853bc
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/FontAwesome.otf differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.eot b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.eot
new file mode 100644
index 0000000..96f92f9
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.eot differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.svg b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.svg
new file mode 100644
index 0000000..5a5f0ec
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.svg
@@ -0,0 +1,685 @@
+<?xml version="1.0" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
+<svg xmlns="http://www.w3.org/2000/svg">
+<metadata></metadata>
+<defs>
+<font id="fontawesomeregular" horiz-adv-x="1536" >
+<font-face units-per-em="1792" ascent="1536" descent="-256" />
+<missing-glyph horiz-adv-x="448" />
+<glyph unicode=" "  horiz-adv-x="448" />
+<glyph unicode="&#x09;" horiz-adv-x="448" />
+<glyph unicode="&#xa0;" horiz-adv-x="448" />
+<glyph unicode="&#xa8;" horiz-adv-x="1792" />
+<glyph unicode="&#xa9;" horiz-adv-x="1792" />
+<glyph unicode="&#xae;" horiz-adv-x="1792" />
+<glyph unicode="&#xb4;" horiz-adv-x="1792" />
+<glyph unicode="&#xc6;" horiz-adv-x="1792" />
+<glyph unicode="&#xd8;" horiz-adv-x="1792" />
+<glyph unicode="&#x2000;" horiz-adv-x="768" />
+<glyph unicode="&#x2001;" horiz-adv-x="1537" />
+<glyph unicode="&#x2002;" horiz-adv-x="768" />
+<glyph unicode="&#x2003;" horiz-adv-x="1537" />
+<glyph unicode="&#x2004;" horiz-adv-x="512" />
+<glyph unicode="&#x2005;" horiz-adv-x="384" />
+<glyph unicode="&#x2006;" horiz-adv-x="256" />
+<glyph unicode="&#x2007;" horiz-adv-x="256" />
+<glyph unicode="&#x2008;" horiz-adv-x="192" />
+<glyph unicode="&#x2009;" horiz-adv-x="307" />
+<glyph unicode="&#x200a;" horiz-adv-x="85" />
+<glyph unicode="&#x202f;" horiz-adv-x="307" />
+<glyph unicode="&#x205f;" horiz-adv-x="384" />
+<glyph unicode="&#x2122;" horiz-adv-x="1792" />
+<glyph unicode="&#x221e;" horiz-adv-x="1792" />
+<glyph unicode="&#x2260;" horiz-adv-x="1792" />
+<glyph unicode="&#x25fc;" horiz-adv-x="500" d="M0 0z" />
+<glyph unicode="&#xf000;" horiz-adv-x="1792" d="M1699 1350q0 -35 -43 -78l-632 -632v-768h320q26 0 45 -19t19 -45t-19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45t45 19h320v768l-632 632q-43 43 -43 78q0 23 18 36.5t38 17.5t43 4h1408q23 0 43 -4t38 -17.5t18 -36.5z" />
+<glyph unicode="&#xf001;" d="M1536 1312v-1120q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v537l-768 -237v-709q0 -50 -34 -89t-86 -60.5t-103.5 -32t-96.5 -10.5t-96.5 10.5t-103.5 32t-86 60.5t-34 89 t34 89t86 60.5t103.5 32t96.5 10.5q105 0 192 -39v967q0 31 19 56.5t49 35.5l832 256q12 4 28 4q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf002;" horiz-adv-x="1664" d="M1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -52 -38 -90t-90 -38q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5 t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150 -225t55.5 -273.5q0 -220 -124 -399l343 -343q37 -37 37 -90z" />
+<glyph unicode="&#xf003;" horiz-adv-x="1792" d="M1664 32v768q-32 -36 -69 -66q-268 -206 -426 -338q-51 -43 -83 -67t-86.5 -48.5t-102.5 -24.5h-1h-1q-48 0 -102.5 24.5t-86.5 48.5t-83 67q-158 132 -426 338q-37 30 -69 66v-768q0 -13 9.5 -22.5t22.5 -9.5h1472q13 0 22.5 9.5t9.5 22.5zM1664 1083v11v13.5t-0.5 13 t-3 12.5t-5.5 9t-9 7.5t-14 2.5h-1472q-13 0 -22.5 -9.5t-9.5 -22.5q0 -168 147 -284q193 -152 401 -317q6 -5 35 -29.5t46 -37.5t44.5 -31.5t50.5 -27.5t43 -9h1h1q20 0 43 9t50.5 27.5t44.5 31.5t46 37.5t35 [...]
+<glyph unicode="&#xf004;" horiz-adv-x="1792" d="M896 -128q-26 0 -44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t76 -68q36 36 76 68t95.5 68.5t120 58t126.5 21.5q224 0 351 -124t127 -344q0 -221 -229 -450l-623 -600 q-18 -18 -44 -18z" />
+<glyph unicode="&#xf005;" horiz-adv-x="1664" d="M1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -21 -10.5 -35.5t-30.5 -14.5q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455 l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf006;" horiz-adv-x="1664" d="M1137 532l306 297l-422 62l-189 382l-189 -382l-422 -62l306 -297l-73 -421l378 199l377 -199zM1664 889q0 -22 -26 -48l-363 -354l86 -500q1 -7 1 -20q0 -50 -41 -50q-19 0 -40 12l-449 236l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500 l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41t49 -41l225 -455l502 -73q56 -9 56 -46z" />
+<glyph unicode="&#xf007;" horiz-adv-x="1408" d="M1408 131q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5t43 97.5t62 81t85.5 53.5t111.5 20q9 0 42 -21.5t74.5 -48t108 -48t133.5 -21.5t133.5 21.5t108 48t74.5 48t42 21.5q61 0 111.5 -20t85.5 -53.5t62 -81 t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM1088 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf008;" horiz-adv-x="1920" d="M384 -64v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 320v128q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM384 704v128q0 26 -19 45t-45 19h-128 q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1408 -64v512q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-512q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM384 1088v128q0 26 -19 [...]
+<glyph unicode="&#xf009;" horiz-adv-x="1664" d="M768 512v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM768 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 512v-384q0 -52 -38 -90t-90 -38 h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90zM1664 1280v-384q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf00a;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 288v-192q0 -40 -28 -68t-68 -28h-320 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1152 800v-192q0 -40  [...]
+<glyph unicode="&#xf00b;" horiz-adv-x="1792" d="M512 288v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM512 800v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 288v-192q0 -40 -28 -68t-68 -28h-960 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h960q40 0 68 -28t28 -68zM512 1312v-192q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h320q40 0 68 -28t28 -68zM1792 800v-192q0 -40  [...]
+<glyph unicode="&#xf00c;" horiz-adv-x="1792" d="M1671 970q0 -40 -28 -68l-724 -724l-136 -136q-28 -28 -68 -28t-68 28l-136 136l-362 362q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -295l656 657q28 28 68 28t68 -28l136 -136q28 -28 28 -68z" />
+<glyph unicode="&#xf00d;" horiz-adv-x="1408" d="M1298 214q0 -40 -28 -68l-136 -136q-28 -28 -68 -28t-68 28l-294 294l-294 -294q-28 -28 -68 -28t-68 28l-136 136q-28 28 -28 68t28 68l294 294l-294 294q-28 28 -28 68t28 68l136 136q28 28 68 28t68 -28l294 -294l294 294q28 28 68 28t68 -28l136 -136q28 -28 28 -68 t-28 -68l-294 -294l294 -294q28 -28 28 -68z" />
+<glyph unicode="&#xf00e;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-224q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v224h-224q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h224v224q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5v-224h224 q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343  [...]
+<glyph unicode="&#xf010;" horiz-adv-x="1664" d="M1024 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-576q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h576q13 0 22.5 -9.5t9.5 -22.5zM1152 704q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5z M1664 -128q0 -53 -37.5 -90.5t-90.5 -37.5q-54 0 -90 38l-343 342q-179 -124 -399 -124q-143 0 -273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5t273.5 -55.5t225 -150t150  [...]
+<glyph unicode="&#xf011;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61t-298 61t-245 164t-164 245t-61 298q0 182 80.5 343t226.5 270q43 32 95.5 25t83.5 -50q32 -42 24.5 -94.5t-49.5 -84.5q-98 -74 -151.5 -181t-53.5 -228q0 -104 40.5 -198.5t109.5 -163.5t163.5 -109.5 t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5q0 121 -53.5 228t-151.5 181q-42 32 -49.5 84.5t24.5 94.5q31 43 84 50t95 -25q146 -109 226.5 -270t80.5 -343zM896 1408v-640q0 -52 -38 -90t-90 -38t-90 38t-38 90v640q0  [...]
+<glyph unicode="&#xf012;" horiz-adv-x="1792" d="M256 96v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 224v-320q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1024 480v-576q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1408 864v-960q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM1792 1376v-1472q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t [...]
+<glyph unicode="&#xf013;" d="M1024 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1536 749v-222q0 -12 -8 -23t-20 -13l-185 -28q-19 -54 -39 -91q35 -50 107 -138q10 -12 10 -25t-9 -23q-27 -37 -99 -108t-94 -71q-12 0 -26 9l-138 108q-44 -23 -91 -38 q-16 -136 -29 -186q-7 -28 -36 -28h-222q-14 0 -24.5 8.5t-11.5 21.5l-28 184q-49 16 -90 37l-141 -107q-10 -9 -25 -9q-14 0 -25 11q-126 114 -165 168q-7 10 -7 23q0 12 8 23q15 21 51 66.5t54 70.5q-27 50 -41 99l-183 27q-13 2 -21 12.5 [...]
+<glyph unicode="&#xf014;" horiz-adv-x="1408" d="M512 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM768 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1024 800v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1152 76v948h-896v-948q0 -22 7 -40.5t14.5 -27t10.5 -8.5h832q3 0 10.5 8.5t14.5 27t7 40.5zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q [...]
+<glyph unicode="&#xf015;" horiz-adv-x="1664" d="M1408 544v-480q0 -26 -19 -45t-45 -19h-384v384h-256v-384h-384q-26 0 -45 19t-19 45v480q0 1 0.5 3t0.5 3l575 474l575 -474q1 -2 1 -6zM1631 613l-62 -74q-8 -9 -21 -11h-3q-13 0 -21 7l-692 577l-692 -577q-12 -8 -24 -7q-13 2 -21 11l-62 74q-8 10 -7 23.5t11 21.5 l719 599q32 26 76 26t76 -26l244 -204v195q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-408l219 -182q10 -8 11 -21.5t-7 -23.5z" />
+<glyph unicode="&#xf016;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z " />
+<glyph unicode="&#xf017;" d="M896 992v-448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf018;" horiz-adv-x="1920" d="M1111 540v4l-24 320q-1 13 -11 22.5t-23 9.5h-186q-13 0 -23 -9.5t-11 -22.5l-24 -320v-4q-1 -12 8 -20t21 -8h244q12 0 21 8t8 20zM1870 73q0 -73 -46 -73h-704q13 0 22 9.5t8 22.5l-20 256q-1 13 -11 22.5t-23 9.5h-272q-13 0 -23 -9.5t-11 -22.5l-20 -256 q-1 -13 8 -22.5t22 -9.5h-704q-46 0 -46 73q0 54 26 116l417 1044q8 19 26 33t38 14h339q-13 0 -23 -9.5t-11 -22.5l-15 -192q-1 -14 8 -23t22 -9h166q13 0 22 9t8 23l-15 192q-1 13 -11 22.5t-23 9.5h339q20 0 38 -14t2 [...]
+<glyph unicode="&#xf019;" horiz-adv-x="1664" d="M1280 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 416v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h465l135 -136 q58 -56 136 -56t136 56l136 136h464q40 0 68 -28t28 -68zM1339 985q17 -41 -14 -70l-448 -448q-18 -19 -45 -19t-45 19l-448 448q-31 29 -14 70q17 39 59 39h256v448q0 26 19 45t45 19h256q26 0 45 -19t19 -45v-448h256q4 [...]
+<glyph unicode="&#xf01a;" d="M1120 608q0 -12 -10 -24l-319 -319q-11 -9 -23 -9t-23 9l-320 320q-15 16 -7 35q8 20 30 20h192v352q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-352h192q14 0 23 -9t9 -23zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273 t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01b;" d="M1118 660q-8 -20 -30 -20h-192v-352q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v352h-192q-14 0 -23 9t-9 23q0 12 10 24l319 319q11 9 23 9t23 -9l320 -320q15 -16 7 -35zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198 t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01c;" d="M1023 576h316q-1 3 -2.5 8t-2.5 8l-212 496h-708l-212 -496q-1 -2 -2.5 -8t-2.5 -8h316l95 -192h320zM1536 546v-482q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v482q0 62 25 123l238 552q10 25 36.5 42t52.5 17h832q26 0 52.5 -17t36.5 -42l238 -552 q25 -61 25 -123z" />
+<glyph unicode="&#xf01d;" d="M1184 640q0 -37 -32 -55l-544 -320q-15 -9 -32 -9q-16 0 -32 8q-32 19 -32 56v640q0 37 32 56q33 18 64 -1l544 -320q32 -18 32 -55zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf01e;" d="M1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l138 138q-148 137 -349 137q-104 0 -198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5q119 0 225 52t179 147q7 10 23 12q14 0 25 -9 l137 -138q9 -8 9.5 -20.5t-7.5 -22.5q-109 -132 -264 -204.5t-327 -72.5q-156 0 -298 61t-245 164t-164 245t-61 298t61 298t164 245t245 164t298 61q147 0 284.5 -55.5t244.5 -156.5l130 129q29 31 70 14q39 -17 39 -59z" />
+<glyph unicode="&#xf021;" d="M1511 480q0 -5 -1 -7q-64 -268 -268 -434.5t-478 -166.5q-146 0 -282.5 55t-243.5 157l-129 -129q-19 -19 -45 -19t-45 19t-19 45v448q0 26 19 45t45 19h448q26 0 45 -19t19 -45t-19 -45l-137 -137q71 -66 161 -102t187 -36q134 0 250 65t186 179q11 17 53 117 q8 23 30 23h192q13 0 22.5 -9.5t9.5 -22.5zM1536 1280v-448q0 -26 -19 -45t-45 -19h-448q-26 0 -45 19t-19 45t19 45l138 138q-148 137 -349 137q-134 0 -250 -65t-186 -179q-11 -17 -53 -117q-8 -23 -30 -23h-199q-13 0 -22.5 9.5t-9.5 2 [...]
+<glyph unicode="&#xf022;" horiz-adv-x="1792" d="M384 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 608v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M384 864v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM1536 352v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-13 0 -22.5 9.5t-9.5  [...]
+<glyph unicode="&#xf023;" horiz-adv-x="1152" d="M320 768h512v192q0 106 -75 181t-181 75t-181 -75t-75 -181v-192zM1152 672v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v192q0 184 132 316t316 132t316 -132t132 -316v-192h32q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf024;" horiz-adv-x="1792" d="M320 1280q0 -72 -64 -110v-1266q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v1266q-64 38 -64 110q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -25 -12.5 -38.5t-39.5 -27.5q-215 -116 -369 -116q-61 0 -123.5 22t-108.5 48 t-115.5 48t-142.5 22q-192 0 -464 -146q-17 -9 -33 -9q-26 0 -45 19t-19 45v742q0 32 31 55q21 14 79 43q236 120 421 120q107 0 200 -29t219 -88q38 -19 88 -19q54 0 117.5 21t110 47t88 47t54.5 21q26 0 45 -1 [...]
+<glyph unicode="&#xf025;" horiz-adv-x="1664" d="M1664 650q0 -166 -60 -314l-20 -49l-185 -33q-22 -83 -90.5 -136.5t-156.5 -53.5v-32q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-32q71 0 130 -35.5t93 -95.5l68 12q29 95 29 193q0 148 -88 279t-236.5 209t-315.5 78 t-315.5 -78t-236.5 -209t-88 -279q0 -98 29 -193l68 -12q34 60 93 95.5t130 35.5v32q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v32q-88 0 -156.5 53.5t-90.5 136.5l-185  [...]
+<glyph unicode="&#xf026;" horiz-adv-x="768" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf027;" horiz-adv-x="1152" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142z" />
+<glyph unicode="&#xf028;" horiz-adv-x="1664" d="M768 1184v-1088q0 -26 -19 -45t-45 -19t-45 19l-333 333h-262q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h262l333 333q19 19 45 19t45 -19t19 -45zM1152 640q0 -76 -42.5 -141.5t-112.5 -93.5q-10 -5 -25 -5q-26 0 -45 18.5t-19 45.5q0 21 12 35.5t29 25t34 23t29 35.5 t12 57t-12 57t-29 35.5t-34 23t-29 25t-12 35.5q0 27 19 45.5t45 18.5q15 0 25 -5q70 -27 112.5 -93t42.5 -142zM1408 640q0 -153 -85 -282.5t-225 -188.5q-13 -5 -25 -5q-27 0 -46 19t-19 45q0 39 39 59q56  [...]
+<glyph unicode="&#xf029;" horiz-adv-x="1408" d="M384 384v-128h-128v128h128zM384 1152v-128h-128v128h128zM1152 1152v-128h-128v128h128zM128 129h384v383h-384v-383zM128 896h384v384h-384v-384zM896 896h384v384h-384v-384zM640 640v-640h-640v640h640zM1152 128v-128h-128v128h128zM1408 128v-128h-128v128h128z M1408 640v-384h-384v128h-128v-384h-128v640h384v-128h128v128h128zM640 1408v-640h-640v640h640zM1408 1408v-640h-640v640h640z" />
+<glyph unicode="&#xf02a;" horiz-adv-x="1792" d="M63 0h-63v1408h63v-1408zM126 1h-32v1407h32v-1407zM220 1h-31v1407h31v-1407zM377 1h-31v1407h31v-1407zM534 1h-62v1407h62v-1407zM660 1h-31v1407h31v-1407zM723 1h-31v1407h31v-1407zM786 1h-31v1407h31v-1407zM943 1h-63v1407h63v-1407zM1100 1h-63v1407h63v-1407z M1226 1h-63v1407h63v-1407zM1352 1h-63v1407h63v-1407zM1446 1h-63v1407h63v-1407zM1635 1h-94v1407h94v-1407zM1698 1h-32v1407h32v-1407zM1792 0h-63v1408h63v-1408z" />
+<glyph unicode="&#xf02b;" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91z" />
+<glyph unicode="&#xf02c;" horiz-adv-x="1920" d="M448 1088q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1515 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-53 0 -90 37l-715 716q-38 37 -64.5 101t-26.5 117v416q0 52 38 90t90 38h416q53 0 117 -26.5t102 -64.5 l715 -714q37 -39 37 -91zM1899 512q0 -53 -37 -90l-491 -492q-39 -37 -91 -37q-36 0 -59 14t-53 45l470 470q37 37 37 90q0 52 -37 91l-715 714q-38 38 -102 64.5t-117 26.5h224q53 0 117 -26.5t102 -64.5l7 [...]
+<glyph unicode="&#xf02d;" horiz-adv-x="1664" d="M1639 1058q40 -57 18 -129l-275 -906q-19 -64 -76.5 -107.5t-122.5 -43.5h-923q-77 0 -148.5 53.5t-99.5 131.5q-24 67 -2 127q0 4 3 27t4 37q1 8 -3 21.5t-3 19.5q2 11 8 21t16.5 23.5t16.5 23.5q23 38 45 91.5t30 91.5q3 10 0.5 30t-0.5 28q3 11 17 28t17 23 q21 36 42 92t25 90q1 9 -2.5 32t0.5 28q4 13 22 30.5t22 22.5q19 26 42.5 84.5t27.5 96.5q1 8 -3 25.5t-2 26.5q2 8 9 18t18 23t17 21q8 12 16.5 30.5t15 35t16 36t19.5 32t26.5 23.5t36 11.5t47.5 -5.5l-1 -3q38 9 51 [...]
+<glyph unicode="&#xf02e;" horiz-adv-x="1280" d="M1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf02f;" horiz-adv-x="1664" d="M384 0h896v256h-896v-256zM384 640h896v384h-160q-40 0 -68 28t-28 68v160h-640v-640zM1536 576q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 576v-416q0 -13 -9.5 -22.5t-22.5 -9.5h-224v-160q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68 v160h-224q-13 0 -22.5 9.5t-9.5 22.5v416q0 79 56.5 135.5t135.5 56.5h64v544q0 40 28 68t68 28h672q40 0 88 -20t76 -48l152 -152q28 -28 48 -76t20 -88v-256h64q79 0 135.5 -56.5t56.5 -135.5z" />
+<glyph unicode="&#xf030;" horiz-adv-x="1920" d="M960 864q119 0 203.5 -84.5t84.5 -203.5t-84.5 -203.5t-203.5 -84.5t-203.5 84.5t-84.5 203.5t84.5 203.5t203.5 84.5zM1664 1280q106 0 181 -75t75 -181v-896q0 -106 -75 -181t-181 -75h-1408q-106 0 -181 75t-75 181v896q0 106 75 181t181 75h224l51 136 q19 49 69.5 84.5t103.5 35.5h512q53 0 103.5 -35.5t69.5 -84.5l51 -136h224zM960 128q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf031;" horiz-adv-x="1664" d="M725 977l-170 -450q33 0 136.5 -2t160.5 -2q19 0 57 2q-87 253 -184 452zM0 -128l2 79q23 7 56 12.5t57 10.5t49.5 14.5t44.5 29t31 50.5l237 616l280 724h75h53q8 -14 11 -21l205 -480q33 -78 106 -257.5t114 -274.5q15 -34 58 -144.5t72 -168.5q20 -45 35 -57 q19 -15 88 -29.5t84 -20.5q6 -38 6 -57q0 -4 -0.5 -13t-0.5 -13q-63 0 -190 8t-191 8q-76 0 -215 -7t-178 -8q0 43 4 78l131 28q1 0 12.5 2.5t15.5 3.5t14.5 4.5t15 6.5t11 8t9 11t2.5 14q0 16 -31 96.5t-72 177.5t-4 [...]
+<glyph unicode="&#xf032;" horiz-adv-x="1408" d="M555 15q74 -32 140 -32q376 0 376 335q0 114 -41 180q-27 44 -61.5 74t-67.5 46.5t-80.5 25t-84 10.5t-94.5 2q-73 0 -101 -10q0 -53 -0.5 -159t-0.5 -158q0 -8 -1 -67.5t-0.5 -96.5t4.5 -83.5t12 -66.5zM541 761q42 -7 109 -7q82 0 143 13t110 44.5t74.5 89.5t25.5 142 q0 70 -29 122.5t-79 82t-108 43.5t-124 14q-50 0 -130 -13q0 -50 4 -151t4 -152q0 -27 -0.5 -80t-0.5 -79q0 -46 1 -69zM0 -128l2 94q15 4 85 16t106 27q7 12 12.5 27t8.5 33.5t5.5 32.5t3 37.5t0.5 34v35.5v [...]
+<glyph unicode="&#xf033;" horiz-adv-x="1024" d="M0 -126l17 85q6 2 81.5 21.5t111.5 37.5q28 35 41 101q1 7 62 289t114 543.5t52 296.5v25q-24 13 -54.5 18.5t-69.5 8t-58 5.5l19 103q33 -2 120 -6.5t149.5 -7t120.5 -2.5q48 0 98.5 2.5t121 7t98.5 6.5q-5 -39 -19 -89q-30 -10 -101.5 -28.5t-108.5 -33.5 q-8 -19 -14 -42.5t-9 -40t-7.5 -45.5t-6.5 -42q-27 -148 -87.5 -419.5t-77.5 -355.5q-2 -9 -13 -58t-20 -90t-16 -83.5t-6 -57.5l1 -18q17 -4 185 -31q-3 -44 -16 -99q-11 0 -32.5 -1.5t-32.5 -1.5q-29 0 -87 10t-86 10q- [...]
+<glyph unicode="&#xf034;" horiz-adv-x="1792" d="M1744 128q33 0 42 -18.5t-11 -44.5l-126 -162q-20 -26 -49 -26t-49 26l-126 162q-20 26 -11 44.5t42 18.5h80v1024h-80q-33 0 -42 18.5t11 44.5l126 162q20 26 49 26t49 -26l126 -162q20 -26 11 -44.5t-42 -18.5h-80v-1024h80zM81 1407l54 -27q12 -5 211 -5q44 0 132 2 t132 2q36 0 107.5 -0.5t107.5 -0.5h293q6 0 21 -0.5t20.5 0t16 3t17.5 9t15 17.5l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 48t-14.5 73.5t-7.5 35.5q [...]
+<glyph unicode="&#xf035;" d="M81 1407l54 -27q12 -5 211 -5q44 0 132 2t132 2q70 0 246.5 1t304.5 0.5t247 -4.5q33 -1 56 31l42 1q4 0 14 -0.5t14 -0.5q2 -112 2 -336q0 -80 -5 -109q-39 -14 -68 -18q-25 44 -54 128q-3 9 -11 47.5t-15 73.5t-7 36q-10 13 -27 19q-5 2 -66 2q-30 0 -93 1t-103 1 t-94 -2t-96 -7q-9 -81 -8 -136l1 -152v52q0 -55 1 -154t1.5 -180t0.5 -153q0 -16 -2.5 -71.5t0 -91.5t12.5 -69q40 -21 124 -42.5t120 -37.5q5 -40 5 -50q0 -14 -3 -29l-34 -1q-76 -2 -218 8t-207 10q-50 0 -151 -9t-152 -9q-3 51 -3 [...]
+<glyph unicode="&#xf036;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf037;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1408 576v-128q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h896q26 0 45 -19t19 -45zM1664 960v-128q0 -26 -19 -45t-45 -19 h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1280 1344v-128q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h640q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf038;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1280q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1536q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1536q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1152q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf039;" horiz-adv-x="1792" d="M1792 192v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 576v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 960v-128q0 -26 -19 -45 t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-128q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf03a;" horiz-adv-x="1792" d="M256 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM256 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5 t9.5 -22.5zM256 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 - [...]
+<glyph unicode="&#xf03b;" horiz-adv-x="1792" d="M384 992v-576q0 -13 -9.5 -22.5t-22.5 -9.5q-14 0 -23 9l-288 288q-9 9 -9 23t9 23l288 288q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22 [...]
+<glyph unicode="&#xf03c;" horiz-adv-x="1792" d="M352 704q0 -14 -9 -23l-288 -288q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v576q0 13 9.5 22.5t22.5 9.5q14 0 23 -9l288 -288q9 -9 9 -23zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1728q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1728q13 0 22.5 -9.5 t9.5 -22.5zM1792 608v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1088q13 0 22.5 -9.5t9.5 -22.5zM1792 992v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1088q- [...]
+<glyph unicode="&#xf03d;" horiz-adv-x="1792" d="M1792 1184v-1088q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-403 403v-166q0 -119 -84.5 -203.5t-203.5 -84.5h-704q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h704q119 0 203.5 -84.5t84.5 -203.5v-165l403 402q18 19 45 19q12 0 25 -5 q39 -17 39 -59z" />
+<glyph unicode="&#xf03e;" horiz-adv-x="1920" d="M640 960q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1664 576v-448h-1408v192l320 320l160 -160l512 512zM1760 1280h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-1216q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5v1216 q0 13 -9.5 22.5t-22.5 9.5zM1920 1248v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf040;" d="M363 0l91 91l-235 235l-91 -91v-107h128v-128h107zM886 928q0 22 -22 22q-10 0 -17 -7l-542 -542q-7 -7 -7 -17q0 -22 22 -22q10 0 17 7l542 542q7 7 7 17zM832 1120l416 -416l-832 -832h-416v416zM1515 1024q0 -53 -37 -90l-166 -166l-416 416l166 165q36 38 90 38 q53 0 91 -38l235 -234q37 -39 37 -91z" />
+<glyph unicode="&#xf041;" horiz-adv-x="1024" d="M768 896q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1024 896q0 -109 -33 -179l-364 -774q-16 -33 -47.5 -52t-67.5 -19t-67.5 19t-46.5 52l-365 774q-33 70 -33 179q0 212 150 362t362 150t362 -150t150 -362z" />
+<glyph unicode="&#xf042;" d="M768 96v1088q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf043;" horiz-adv-x="1024" d="M512 384q0 36 -20 69q-1 1 -15.5 22.5t-25.5 38t-25 44t-21 50.5q-4 16 -21 16t-21 -16q-7 -23 -21 -50.5t-25 -44t-25.5 -38t-15.5 -22.5q-20 -33 -20 -69q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 512q0 -212 -150 -362t-362 -150t-362 150t-150 362 q0 145 81 275q6 9 62.5 90.5t101 151t99.5 178t83 201.5q9 30 34 47t51 17t51.5 -17t33.5 -47q28 -93 83 -201.5t99.5 -178t101 -151t62.5 -90.5q81 -127 81 -275z" />
+<glyph unicode="&#xf044;" horiz-adv-x="1792" d="M888 352l116 116l-152 152l-116 -116v-56h96v-96h56zM1328 1072q-16 16 -33 -1l-350 -350q-17 -17 -1 -33t33 1l350 350q17 17 1 33zM1408 478v-190q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-14 -14 -32 -8q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v126q0 13 9 22l64 64q15 15 35 7t20 -29zM1312 12 [...]
+<glyph unicode="&#xf045;" horiz-adv-x="1664" d="M1408 547v-259q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h255v0q13 0 22.5 -9.5t9.5 -22.5q0 -27 -26 -32q-77 -26 -133 -60q-10 -4 -16 -4h-112q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832 q66 0 113 47t47 113v214q0 19 18 29q28 13 54 37q16 16 35 8q21 -9 21 -29zM1645 1043l-384 -384q-18 -19 -45 -19q-12 0 -25 5q-39 17 -39 59v192h-160q-323 0 -438 -131q-119 -137 -74 -473q3 -23 -20 -34 [...]
+<glyph unicode="&#xf046;" horiz-adv-x="1664" d="M1408 606v-318q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q63 0 117 -25q15 -7 18 -23q3 -17 -9 -29l-49 -49q-10 -10 -23 -10q-3 0 -9 2q-23 6 -45 6h-832q-66 0 -113 -47t-47 -113v-832 q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v254q0 13 9 22l64 64q10 10 23 10q6 0 12 -3q20 -8 20 -29zM1639 1095l-814 -814q-24 -24 -57 -24t-57 24l-430 430q-24 24 -24 57t24 57l110 110q24 24 57 24t57 -24l263  [...]
+<glyph unicode="&#xf047;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-384v-384h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v384h-384v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45 t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h384v384h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45t-19 -45t-45 -19h-128v-384h384v128q0 26 19 45t45 19t45 -19l256  [...]
+<glyph unicode="&#xf048;" horiz-adv-x="1024" d="M979 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19z" />
+<glyph unicode="&#xf049;" horiz-adv-x="1792" d="M1747 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-9 9 -13 19v-678q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-678q4 11 13 19l710 710 q19 19 32 13t13 -32v-710q4 11 13 19z" />
+<glyph unicode="&#xf04a;" horiz-adv-x="1664" d="M1619 1395q19 19 32 13t13 -32v-1472q0 -26 -13 -32t-32 13l-710 710q-8 9 -13 19v-710q0 -26 -13 -32t-32 13l-710 710q-19 19 -19 45t19 45l710 710q19 19 32 13t13 -32v-710q5 11 13 19z" />
+<glyph unicode="&#xf04b;" horiz-adv-x="1408" d="M1384 609l-1328 -738q-23 -13 -39.5 -3t-16.5 36v1472q0 26 16.5 36t39.5 -3l1328 -738q23 -13 23 -31t-23 -31z" />
+<glyph unicode="&#xf04c;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45zM640 1344v-1408q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h512q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04d;" d="M1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf04e;" horiz-adv-x="1664" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q19 -19 19 -45t-19 -45l-710 -710q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf050;" horiz-adv-x="1792" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v710q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19l-710 -710 q-19 -19 -32 -13t-13 32v710q-5 -10 -13 -19z" />
+<glyph unicode="&#xf051;" horiz-adv-x="1024" d="M45 -115q-19 -19 -32 -13t-13 32v1472q0 26 13 32t32 -13l710 -710q8 -8 13 -19v678q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-1408q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v678q-5 -10 -13 -19z" />
+<glyph unicode="&#xf052;" horiz-adv-x="1538" d="M14 557l710 710q19 19 45 19t45 -19l710 -710q19 -19 13 -32t-32 -13h-1472q-26 0 -32 13t13 32zM1473 0h-1408q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1408q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19z" />
+<glyph unicode="&#xf053;" horiz-adv-x="1280" d="M1171 1235l-531 -531l531 -531q19 -19 19 -45t-19 -45l-166 -166q-19 -19 -45 -19t-45 19l-742 742q-19 19 -19 45t19 45l742 742q19 19 45 19t45 -19l166 -166q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf054;" horiz-adv-x="1280" d="M1107 659l-742 -742q-19 -19 -45 -19t-45 19l-166 166q-19 19 -19 45t19 45l531 531l-531 531q-19 19 -19 45t19 45l166 166q19 19 45 19t45 -19l742 -742q19 -19 19 -45t-19 -45z" />
+<glyph unicode="&#xf055;" d="M1216 576v128q0 26 -19 45t-45 19h-256v256q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-256h-256q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h256v-256q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v256h256q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5 t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf056;" d="M1216 576v128q0 26 -19 45t-45 19h-768q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h768q26 0 45 19t19 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
+<glyph unicode="&#xf057;" d="M1149 414q0 26 -19 45l-181 181l181 181q19 19 19 45q0 27 -19 46l-90 90q-19 19 -46 19q-26 0 -45 -19l-181 -181l-181 181q-19 19 -45 19q-27 0 -46 -19l-90 -90q-19 -19 -19 -46q0 -26 19 -45l181 -181l-181 -181q-19 -19 -19 -45q0 -27 19 -46l90 -90q19 -19 46 -19 q26 0 45 19l181 181l181 -181q19 -19 45 -19q27 0 46 19l90 90q19 19 19 46zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 - [...]
+<glyph unicode="&#xf058;" d="M1284 802q0 28 -18 46l-91 90q-19 19 -45 19t-45 -19l-408 -407l-226 226q-19 19 -45 19t-45 -19l-91 -90q-18 -18 -18 -46q0 -27 18 -45l362 -362q19 -19 45 -19q27 0 46 19l543 543q18 18 18 45zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf059;" d="M896 160v192q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h192q14 0 23 9t9 23zM1152 832q0 88 -55.5 163t-138.5 116t-170 41q-243 0 -371 -213q-15 -24 8 -42l132 -100q7 -6 19 -6q16 0 25 12q53 68 86 92q34 24 86 24q48 0 85.5 -26t37.5 -59 q0 -38 -20 -61t-68 -45q-63 -28 -115.5 -86.5t-52.5 -125.5v-36q0 -14 9 -23t23 -9h192q14 0 23 9t9 23q0 19 21.5 49.5t54.5 49.5q32 18 49 28.5t46 35t44.5 48t28 60.5t12.5 81zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-38 [...]
+<glyph unicode="&#xf05a;" d="M1024 160v160q0 14 -9 23t-23 9h-96v512q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h96v-320h-96q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23t23 -9h448q14 0 23 9t9 23zM896 1056v160q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-160q0 -14 9 -23 t23 -9h192q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05b;" d="M1197 512h-109q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h109q-32 108 -112.5 188.5t-188.5 112.5v-109q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v109q-108 -32 -188.5 -112.5t-112.5 -188.5h109q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-109 q32 -108 112.5 -188.5t188.5 -112.5v109q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-109q108 32 188.5 112.5t112.5 188.5zM1536 704v-128q0 -26 -19 -45t-45 -19h-143q-37 -161 -154.5 -278.5t-278.5 -154.5v-143q0 -26 -19 -45t-45 -19h [...]
+<glyph unicode="&#xf05c;" d="M1097 457l-146 -146q-10 -10 -23 -10t-23 10l-137 137l-137 -137q-10 -10 -23 -10t-23 10l-146 146q-10 10 -10 23t10 23l137 137l-137 137q-10 10 -10 23t10 23l146 146q10 10 23 10t23 -10l137 -137l137 137q10 10 23 10t23 -10l146 -146q10 -10 10 -23t-10 -23 l-137 -137l137 -137q10 -10 10 -23t-10 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385. [...]
+<glyph unicode="&#xf05d;" d="M1171 723l-422 -422q-19 -19 -45 -19t-45 19l-294 294q-19 19 -19 45t19 45l102 102q19 19 45 19t45 -19l147 -147l275 275q19 19 45 19t45 -19l102 -102q19 -19 19 -45t-19 -45zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198 t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf05e;" d="M1312 643q0 161 -87 295l-754 -753q137 -89 297 -89q111 0 211.5 43.5t173.5 116.5t116 174.5t43 212.5zM313 344l755 754q-135 91 -300 91q-148 0 -273 -73t-198 -199t-73 -274q0 -162 89 -299zM1536 643q0 -157 -61 -300t-163.5 -246t-245 -164t-298.5 -61t-298.5 61 t-245 164t-163.5 246t-61 300t61 299.5t163.5 245.5t245 164t298.5 61t298.5 -61t245 -164t163.5 -245.5t61 -299.5z" />
+<glyph unicode="&#xf060;" d="M1536 640v-128q0 -53 -32.5 -90.5t-84.5 -37.5h-704l293 -294q38 -36 38 -90t-38 -90l-75 -76q-37 -37 -90 -37q-52 0 -91 37l-651 652q-37 37 -37 90q0 52 37 91l651 650q38 38 91 38q52 0 90 -38l75 -74q38 -38 38 -91t-38 -91l-293 -293h704q52 0 84.5 -37.5 t32.5 -90.5z" />
+<glyph unicode="&#xf061;" d="M1472 576q0 -54 -37 -91l-651 -651q-39 -37 -91 -37q-51 0 -90 37l-75 75q-38 38 -38 91t38 91l293 293h-704q-52 0 -84.5 37.5t-32.5 90.5v128q0 53 32.5 90.5t84.5 37.5h704l-293 294q-38 36 -38 90t38 90l75 75q38 38 90 38q53 0 91 -38l651 -651q37 -35 37 -90z" />
+<glyph unicode="&#xf062;" horiz-adv-x="1664" d="M1611 565q0 -51 -37 -90l-75 -75q-38 -38 -91 -38q-54 0 -90 38l-294 293v-704q0 -52 -37.5 -84.5t-90.5 -32.5h-128q-53 0 -90.5 32.5t-37.5 84.5v704l-294 -293q-36 -38 -90 -38t-90 38l-75 75q-38 38 -38 90q0 53 38 91l651 651q35 37 90 37q54 0 91 -37l651 -651 q37 -39 37 -91z" />
+<glyph unicode="&#xf063;" horiz-adv-x="1664" d="M1611 704q0 -53 -37 -90l-651 -652q-39 -37 -91 -37q-53 0 -90 37l-651 652q-38 36 -38 90q0 53 38 91l74 75q39 37 91 37q53 0 90 -37l294 -294v704q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-704l294 294q37 37 90 37q52 0 91 -37l75 -75q37 -39 37 -91z" />
+<glyph unicode="&#xf064;" horiz-adv-x="1792" d="M1792 896q0 -26 -19 -45l-512 -512q-19 -19 -45 -19t-45 19t-19 45v256h-224q-98 0 -175.5 -6t-154 -21.5t-133 -42.5t-105.5 -69.5t-80 -101t-48.5 -138.5t-17.5 -181q0 -55 5 -123q0 -6 2.5 -23.5t2.5 -26.5q0 -15 -8.5 -25t-23.5 -10q-16 0 -28 17q-7 9 -13 22 t-13.5 30t-10.5 24q-127 285 -127 451q0 199 53 333q162 403 875 403h224v256q0 26 19 45t45 19t45 -19l512 -512q19 -19 19 -45z" />
+<glyph unicode="&#xf065;" d="M755 480q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23zM1536 1344v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332 q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf066;" d="M768 576v-448q0 -26 -19 -45t-45 -19t-45 19l-144 144l-332 -332q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l332 332l-144 144q-19 19 -19 45t19 45t45 19h448q26 0 45 -19t19 -45zM1523 1248q0 -13 -10 -23l-332 -332l144 -144q19 -19 19 -45t-19 -45 t-45 -19h-448q-26 0 -45 19t-19 45v448q0 26 19 45t45 19t45 -19l144 -144l332 332q10 10 23 10t23 -10l114 -114q10 -10 10 -23z" />
+<glyph unicode="&#xf067;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-416v-416q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v416h-416q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h416v416q0 40 28 68t68 28h192q40 0 68 -28t28 -68v-416h416q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf068;" horiz-adv-x="1408" d="M1408 800v-192q0 -40 -28 -68t-68 -28h-1216q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h1216q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf069;" horiz-adv-x="1664" d="M1482 486q46 -26 59.5 -77.5t-12.5 -97.5l-64 -110q-26 -46 -77.5 -59.5t-97.5 12.5l-266 153v-307q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v307l-266 -153q-46 -26 -97.5 -12.5t-77.5 59.5l-64 110q-26 46 -12.5 97.5t59.5 77.5l266 154l-266 154 q-46 26 -59.5 77.5t12.5 97.5l64 110q26 46 77.5 59.5t97.5 -12.5l266 -153v307q0 52 38 90t90 38h128q52 0 90 -38t38 -90v-307l266 153q46 26 97.5 12.5t77.5 -59.5l64 -110q26 -46 12.5 -97.5t-59.5 -77.5l-266 -154z" />
+<glyph unicode="&#xf06a;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM896 161v190q0 14 -9 23.5t-22 9.5h-192q-13 0 -23 -10t-10 -23v-190q0 -13 10 -23t23 -10h192 q13 0 22 9.5t9 23.5zM894 505l18 621q0 12 -10 18q-10 8 -24 8h-220q-14 0 -24 -8q-10 -6 -10 -18l17 -621q0 -10 10 -17.5t24 -7.5h185q14 0 23.5 7.5t10.5 17.5z" />
+<glyph unicode="&#xf06b;" d="M928 180v56v468v192h-320v-192v-468v-56q0 -25 18 -38.5t46 -13.5h192q28 0 46 13.5t18 38.5zM472 1024h195l-126 161q-26 31 -69 31q-40 0 -68 -28t-28 -68t28 -68t68 -28zM1160 1120q0 40 -28 68t-68 28q-43 0 -69 -31l-125 -161h194q40 0 68 28t28 68zM1536 864v-320 q0 -14 -9 -23t-23 -9h-96v-416q0 -40 -28 -68t-68 -28h-1088q-40 0 -68 28t-28 68v416h-96q-14 0 -23 9t-9 23v320q0 14 9 23t23 9h440q-93 0 -158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5q107 0 168 -77l128 -165l128 165q61 [...]
+<glyph unicode="&#xf06c;" horiz-adv-x="1792" d="M1280 832q0 26 -19 45t-45 19q-172 0 -318 -49.5t-259.5 -134t-235.5 -219.5q-19 -21 -19 -45q0 -26 19 -45t45 -19q24 0 45 19q27 24 74 71t67 66q137 124 268.5 176t313.5 52q26 0 45 19t19 45zM1792 1030q0 -95 -20 -193q-46 -224 -184.5 -383t-357.5 -268 q-214 -108 -438 -108q-148 0 -286 47q-15 5 -88 42t-96 37q-16 0 -39.5 -32t-45 -70t-52.5 -70t-60 -32q-30 0 -51 11t-31 24t-27 42q-2 4 -6 11t-5.5 10t-3 9.5t-1.5 13.5q0 35 31 73.5t68 65.5t68 56t31 48q0 4 -14 3 [...]
+<glyph unicode="&#xf06d;" horiz-adv-x="1408" d="M1408 -160v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-1344q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h1344q13 0 22.5 -9.5t9.5 -22.5zM1152 896q0 -78 -24.5 -144t-64 -112.5t-87.5 -88t-96 -77.5t-87.5 -72t-64 -81.5t-24.5 -96.5q0 -96 67 -224l-4 1l1 -1 q-90 41 -160 83t-138.5 100t-113.5 122.5t-72.5 150.5t-27.5 184q0 78 24.5 144t64 112.5t87.5 88t96 77.5t87.5 72t64 81.5t24.5 96.5q0 94 -66 224l3 -1l-1 1q90 -41 160 -83t138.5 -100t113.5 -122.5t72.5 -150. [...]
+<glyph unicode="&#xf06e;" horiz-adv-x="1792" d="M1664 576q-152 236 -381 353q61 -104 61 -225q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 316.5q0 121 61 225q-229 -117 -381 -353q133 -205 333.5 -326.5t434.5 -121.5t434.5 121.5t333.5 326.5zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5 t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1792 576q0 -34 -20 -69q-140 -230 -376.5 -368.5t-499.5 -138.5t-499.5 139t-376.5 368q-20 35 -20 69t20 69q140 229 376.5 [...]
+<glyph unicode="&#xf070;" horiz-adv-x="1792" d="M555 201l78 141q-87 63 -136 159t-49 203q0 121 61 225q-229 -117 -381 -353q167 -258 427 -375zM944 960q0 20 -14 34t-34 14q-125 0 -214.5 -89.5t-89.5 -214.5q0 -20 14 -34t34 -14t34 14t14 34q0 86 61 147t147 61q20 0 34 14t14 34zM1307 1151q0 -7 -1 -9 q-105 -188 -315 -566t-316 -567l-49 -89q-10 -16 -28 -16q-12 0 -134 70q-16 10 -16 28q0 12 44 87q-143 65 -263.5 173t-208.5 245q-20 31 -20 69t20 69q153 235 380 371t496 136q89 0 180 -17l54 97q10 16 28 16q5 0 [...]
+<glyph unicode="&#xf071;" horiz-adv-x="1792" d="M1024 161v190q0 14 -9.5 23.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -23.5v-190q0 -14 9.5 -23.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 23.5zM1022 535l18 459q0 12 -10 19q-13 11 -24 11h-220q-11 0 -24 -11q-10 -7 -10 -21l17 -457q0 -10 10 -16.5t24 -6.5h185 q14 0 23.5 6.5t10.5 16.5zM1008 1469l768 -1408q35 -63 -2 -126q-17 -29 -46.5 -46t-63.5 -17h-1536q-34 0 -63.5 17t-46.5 46q-37 63 -2 126l768 1408q17 31 47 49t65 18t65 -18t47 -49z" />
+<glyph unicode="&#xf072;" horiz-adv-x="1408" d="M1376 1376q44 -52 12 -148t-108 -172l-161 -161l160 -696q5 -19 -12 -33l-128 -96q-7 -6 -19 -6q-4 0 -7 1q-15 3 -21 16l-279 508l-259 -259l53 -194q5 -17 -8 -31l-96 -96q-9 -9 -23 -9h-2q-15 2 -24 13l-189 252l-252 189q-11 7 -13 23q-1 13 9 25l96 97q9 9 23 9 q6 0 8 -1l194 -53l259 259l-508 279q-14 8 -17 24q-2 16 9 27l128 128q14 13 30 8l665 -159l160 160q76 76 172 108t148 -12z" />
+<glyph unicode="&#xf073;" horiz-adv-x="1664" d="M128 -128h288v288h-288v-288zM480 -128h320v288h-320v-288zM128 224h288v320h-288v-320zM480 224h320v320h-320v-320zM128 608h288v288h-288v-288zM864 -128h320v288h-320v-288zM480 608h320v288h-320v-288zM1248 -128h288v288h-288v-288zM864 224h320v320h-320v-320z M512 1088v288q0 13 -9.5 22.5t-22.5 9.5h-64q-13 0 -22.5 -9.5t-9.5 -22.5v-288q0 -13 9.5 -22.5t22.5 -9.5h64q13 0 22.5 9.5t9.5 22.5zM1248 224h288v320h-288v-320zM864 608h320v288h-320v-288zM1248 608h28 [...]
+<glyph unicode="&#xf074;" horiz-adv-x="1792" d="M666 1055q-60 -92 -137 -273q-22 45 -37 72.5t-40.5 63.5t-51 56.5t-63 35t-81.5 14.5h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224q250 0 410 -225zM1792 256q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192q-32 0 -85 -0.5t-81 -1t-73 1 t-71 5t-64 10.5t-63 18.5t-58 28.5t-59 40t-55 53.5t-56 69.5q59 93 136 273q22 -45 37 -72.5t40.5 -63.5t51 -56.5t63 -35t81.5 -14.5h256v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1792 1152q0 -1 [...]
+<glyph unicode="&#xf075;" horiz-adv-x="1792" d="M1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22q-17 -2 -30.5 9t-17.5 29v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26 76q-157 89 -247.5 220t-90.5 281 q0 130 71 248.5t191 204.5t286 136.5t348 50.5q244 0 450 -85.5t326 -233t120 -321.5z" />
+<glyph unicode="&#xf076;" d="M1536 704v-128q0 -201 -98.5 -362t-274 -251.5t-395.5 -90.5t-395.5 90.5t-274 251.5t-98.5 362v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-128q0 -52 23.5 -90t53.5 -57t71 -30t64 -13t44 -2t44 2t64 13t71 30t53.5 57t23.5 90v128q0 26 19 45t45 19h384 q26 0 45 -19t19 -45zM512 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 -19t19 -45zM1536 1344v-384q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h384q26 0 45 [...]
+<glyph unicode="&#xf077;" horiz-adv-x="1792" d="M1683 205l-166 -165q-19 -19 -45 -19t-45 19l-531 531l-531 -531q-19 -19 -45 -19t-45 19l-166 165q-19 19 -19 45.5t19 45.5l742 741q19 19 45 19t45 -19l742 -741q19 -19 19 -45.5t-19 -45.5z" />
+<glyph unicode="&#xf078;" horiz-adv-x="1792" d="M1683 728l-742 -741q-19 -19 -45 -19t-45 19l-742 741q-19 19 -19 45.5t19 45.5l166 165q19 19 45 19t45 -19l531 -531l531 531q19 19 45 19t45 -19l166 -165q19 -19 19 -45.5t-19 -45.5z" />
+<glyph unicode="&#xf079;" horiz-adv-x="1920" d="M1280 32q0 -13 -9.5 -22.5t-22.5 -9.5h-960q-8 0 -13.5 2t-9 7t-5.5 8t-3 11.5t-1 11.5v13v11v160v416h-192q-26 0 -45 19t-19 45q0 24 15 41l320 384q19 22 49 22t49 -22l320 -384q15 -17 15 -41q0 -26 -19 -45t-45 -19h-192v-384h576q16 0 25 -11l160 -192q7 -11 7 -21 zM1920 448q0 -24 -15 -41l-320 -384q-20 -23 -49 -23t-49 23l-320 384q-15 17 -15 41q0 26 19 45t45 19h192v384h-576q-16 0 -25 12l-160 192q-7 9 -7 20q0 13 9.5 22.5t22.5 9.5h960q8 0 13.5 -2t9 -7t5.5  [...]
+<glyph unicode="&#xf07a;" horiz-adv-x="1664" d="M640 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1536 0q0 -52 -38 -90t-90 -38t-90 38t-38 90t38 90t90 38t90 -38t38 -90zM1664 1088v-512q0 -24 -16.5 -42.5t-40.5 -21.5l-1044 -122q13 -60 13 -70q0 -16 -24 -64h920q26 0 45 -19t19 -45 t-19 -45t-45 -19h-1024q-26 0 -45 19t-19 45q0 11 8 31.5t16 36t21.5 40t15.5 29.5l-177 823h-204q-26 0 -45 19t-19 45t19 45t45 19h256q16 0 28.5 -6.5t19.5 -15.5t13 -24.5t8 -26t5.5 -29.5t4.5 -26h1201q26 0 [...]
+<glyph unicode="&#xf07b;" horiz-adv-x="1664" d="M1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07c;" horiz-adv-x="1920" d="M1879 584q0 -31 -31 -66l-336 -396q-43 -51 -120.5 -86.5t-143.5 -35.5h-1088q-34 0 -60.5 13t-26.5 43q0 31 31 66l336 396q43 51 120.5 86.5t143.5 35.5h1088q34 0 60.5 -13t26.5 -43zM1536 928v-160h-832q-94 0 -197 -47.5t-164 -119.5l-337 -396l-5 -6q0 4 -0.5 12.5 t-0.5 12.5v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf07d;" horiz-adv-x="768" d="M704 1216q0 -26 -19 -45t-45 -19h-128v-1024h128q26 0 45 -19t19 -45t-19 -45l-256 -256q-19 -19 -45 -19t-45 19l-256 256q-19 19 -19 45t19 45t45 19h128v1024h-128q-26 0 -45 19t-19 45t19 45l256 256q19 19 45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf07e;" horiz-adv-x="1792" d="M1792 640q0 -26 -19 -45l-256 -256q-19 -19 -45 -19t-45 19t-19 45v128h-1024v-128q0 -26 -19 -45t-45 -19t-45 19l-256 256q-19 19 -19 45t19 45l256 256q19 19 45 19t45 -19t19 -45v-128h1024v128q0 26 19 45t45 19t45 -19l256 -256q19 -19 19 -45z" />
+<glyph unicode="&#xf080;" horiz-adv-x="2048" d="M640 640v-512h-256v512h256zM1024 1152v-1024h-256v1024h256zM2048 0v-128h-2048v1536h128v-1408h1920zM1408 896v-768h-256v768h256zM1792 1280v-1152h-256v1152h256z" />
+<glyph unicode="&#xf081;" d="M1280 926q-56 -25 -121 -34q68 40 93 117q-65 -38 -134 -51q-61 66 -153 66q-87 0 -148.5 -61.5t-61.5 -148.5q0 -29 5 -48q-129 7 -242 65t-192 155q-29 -50 -29 -106q0 -114 91 -175q-47 1 -100 26v-2q0 -75 50 -133.5t123 -72.5q-29 -8 -51 -8q-13 0 -39 4 q21 -63 74.5 -104t121.5 -42q-116 -90 -261 -90q-26 0 -50 3q148 -94 322 -94q112 0 210 35.5t168 95t120.5 137t75 162t24.5 168.5q0 18 -1 27q63 45 105 109zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t [...]
+<glyph unicode="&#xf082;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-188v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-532q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960z" />
+<glyph unicode="&#xf083;" horiz-adv-x="1792" d="M928 704q0 14 -9 23t-23 9q-66 0 -113 -47t-47 -113q0 -14 9 -23t23 -9t23 9t9 23q0 40 28 68t68 28q14 0 23 9t9 23zM1152 574q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM128 0h1536v128h-1536v-128zM1280 574q0 159 -112.5 271.5 t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM256 1216h384v128h-384v-128zM128 1024h1536v118v138h-828l-64 -128h-644v-128zM1792 1280v-1280q0 -53 -37.5 - [...]
+<glyph unicode="&#xf084;" horiz-adv-x="1792" d="M832 1024q0 80 -56 136t-136 56t-136 -56t-56 -136q0 -42 19 -83q-41 19 -83 19q-80 0 -136 -56t-56 -136t56 -136t136 -56t136 56t56 136q0 42 -19 83q41 -19 83 -19q80 0 136 56t56 136zM1683 320q0 -17 -49 -66t-66 -49q-9 0 -28.5 16t-36.5 33t-38.5 40t-24.5 26 l-96 -96l220 -220q28 -28 28 -68q0 -42 -39 -81t-81 -39q-40 0 -68 28l-671 671q-176 -131 -365 -131q-163 0 -265.5 102.5t-102.5 265.5q0 160 95 313t248 248t313 95q163 0 265.5 -102.5t102.5 -265.5q0 -189  [...]
+<glyph unicode="&#xf085;" horiz-adv-x="1920" d="M896 640q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM1664 128q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 1152q0 52 -38 90t-90 38t-90 -38t-38 -90q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1280 731v-185q0 -10 -7 -19.5t-16 -10.5l-155 -24q-11 -35 -32 -76q34 -48 90 -115q7 -10 7 -20q0 -12 -7 -19q-23 -30 -82.5 -89.5t-78.5 -59.5q-11 0 -21 7l-115 90q-37 -19 -77 -31q-11  [...]
+<glyph unicode="&#xf086;" horiz-adv-x="1792" d="M1408 768q0 -139 -94 -257t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q-124 72 -195 177t-71 224 q0 139 94 257t256.5 186.5t353.5 68.5t353.5 -68.5t256.5 -186.5t94 -257zM1792 512q0 -120 -71 -224.5t-195 -176.5q10 -24 20.5 -44t25 -38.5t22.5 -29t26 -29.5t23 -25q1 -1 4 -4.5t4.5 -5t4 -5t3.5 -5.5l2.5 [...]
+<glyph unicode="&#xf087;" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 768q0 51 -39 89.5t-89 38.5h-352q0 58 48 159.5t48 160.5q0 98 -32 145t-128 47q-26 -26 -38 -85t-30.5 -125.5t-59.5 -109.5q-22 -23 -77 -91q-4 -5 -23 -30t-31.5 -41t-34.5 -42.5 t-40 -44t-38.5 -35.5t-40 -27t-35.5 -9h-32v-640h32q13 0 31.5 -3t33 -6.5t38 -11t35 -11.5t35.5 -12.5t29 -10.5q211 -73 342 -73h121q192 0 192 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 4 [...]
+<glyph unicode="&#xf088;" d="M256 1088q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 512q0 35 -21.5 81t-53.5 47q15 17 25 47.5t10 55.5q0 69 -53 119q18 32 18 69t-17.5 73.5t-47.5 52.5q5 30 5 56q0 85 -49 126t-136 41h-128q-131 0 -342 -73q-5 -2 -29 -10.5 t-35.5 -12.5t-35 -11.5t-38 -11t-33 -6.5t-31.5 -3h-32v-640h32q16 0 35.5 -9t40 -27t38.5 -35.5t40 -44t34.5 -42.5t31.5 -41t23 -30q55 -68 77 -91q41 -43 59.5 -109.5t30.5 -125.5t38 -85q96 0 128 47t32 145q0 59 -48 160.5t-48 159.5h [...]
+<glyph unicode="&#xf089;" horiz-adv-x="896" d="M832 1504v-1339l-449 -236q-22 -12 -40 -12q-21 0 -31.5 14.5t-10.5 35.5q0 6 2 20l86 500l-364 354q-25 27 -25 48q0 37 56 46l502 73l225 455q19 41 49 41z" />
+<glyph unicode="&#xf08a;" horiz-adv-x="1792" d="M1664 940q0 81 -21.5 143t-55 98.5t-81.5 59.5t-94 31t-98 8t-112 -25.5t-110.5 -64t-86.5 -72t-60 -61.5q-18 -22 -49 -22t-49 22q-24 28 -60 61.5t-86.5 72t-110.5 64t-112 25.5t-98 -8t-94 -31t-81.5 -59.5t-55 -98.5t-21.5 -143q0 -168 187 -355l581 -560l580 559 q188 188 188 356zM1792 940q0 -221 -229 -450l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-10 8 -27.5 26t-55.5 65.5t-68 97.5t-53.5 121t-23.5 138q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -6 [...]
+<glyph unicode="&#xf08b;" horiz-adv-x="1664" d="M640 96q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-119 0 -203.5 84.5t-84.5 203.5v704q0 119 84.5 203.5t203.5 84.5h320q13 0 22.5 -9.5t9.5 -22.5q0 -4 1 -20t0.5 -26.5t-3 -23.5t-10 -19.5t-20.5 -6.5h-320q-66 0 -113 -47t-47 -113v-704 q0 -66 47 -113t113 -47h288h11h13t11.5 -1t11.5 -3t8 -5.5t7 -9t2 -13.5zM1568 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t4 [...]
+<glyph unicode="&#xf08c;" d="M237 122h231v694h-231v-694zM483 1030q-1 52 -36 86t-93 34t-94.5 -34t-36.5 -86q0 -51 35.5 -85.5t92.5 -34.5h1q59 0 95 34.5t36 85.5zM1068 122h231v398q0 154 -73 233t-193 79q-136 0 -209 -117h2v101h-231q3 -66 0 -694h231v388q0 38 7 56q15 35 45 59.5t74 24.5 q116 0 116 -157v-371zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf08d;" horiz-adv-x="1152" d="M480 672v448q0 14 -9 23t-23 9t-23 -9t-9 -23v-448q0 -14 9 -23t23 -9t23 9t9 23zM1152 320q0 -26 -19 -45t-45 -19h-429l-51 -483q-2 -12 -10.5 -20.5t-20.5 -8.5h-1q-27 0 -32 27l-76 485h-404q-26 0 -45 19t-19 45q0 123 78.5 221.5t177.5 98.5v512q-52 0 -90 38 t-38 90t38 90t90 38h640q52 0 90 -38t38 -90t-38 -90t-90 -38v-512q99 0 177.5 -98.5t78.5 -221.5z" />
+<glyph unicode="&#xf08e;" horiz-adv-x="1792" d="M1408 608v-320q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v320 q0 14 9 23t23 9h64q14 0 23 -9t9 -23zM1792 1472v-512q0 -26 -19 -45t-45 -19t-45 19l-176 176l-652 -652q-10 -10 -23 -10t-23 10l-114 114q-10 10 -10 23t10 23l652 652l-176 176q-19 19 -19 45t19 45t45 19h512q2 [...]
+<glyph unicode="&#xf090;" d="M1184 640q0 -26 -19 -45l-544 -544q-19 -19 -45 -19t-45 19t-19 45v288h-448q-26 0 -45 19t-19 45v384q0 26 19 45t45 19h448v288q0 26 19 45t45 19t45 -19l544 -544q19 -19 19 -45zM1536 992v-704q0 -119 -84.5 -203.5t-203.5 -84.5h-320q-13 0 -22.5 9.5t-9.5 22.5 q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q66 0 113 47t47 113v704q0 66 -47 113t-113 47h-288h-11h-13t-11.5 1t-11.5 3t-8 5.5t-7 9t-2 13.5q0 4 -1 20t-0.5 26.5t3 23.5t10 19.5t20.5 6.5h320q119 0 203.5 -84.5t84.5 -2 [...]
+<glyph unicode="&#xf091;" horiz-adv-x="1664" d="M458 653q-74 162 -74 371h-256v-96q0 -78 94.5 -162t235.5 -113zM1536 928v96h-256q0 -209 -74 -371q141 29 235.5 113t94.5 162zM1664 1056v-128q0 -71 -41.5 -143t-112 -130t-173 -97.5t-215.5 -44.5q-42 -54 -95 -95q-38 -34 -52.5 -72.5t-14.5 -89.5q0 -54 30.5 -91 t97.5 -37q75 0 133.5 -45.5t58.5 -114.5v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 69 58.5 114.5t133.5 45.5q67 0 97.5 37t30.5 91q0 51 -14.5 89.5t-52.5 72.5q-53 41 -95 95q-113 5 -215.5 4 [...]
+<glyph unicode="&#xf092;" d="M519 336q4 6 -3 13q-9 7 -14 2q-4 -6 3 -13q9 -7 14 -2zM491 377q-5 7 -12 4q-6 -4 0 -12q7 -8 12 -5q6 4 0 13zM450 417q2 4 -5 8q-7 2 -8 -2q-3 -5 4 -8q8 -2 9 2zM471 394q2 1 1.5 4.5t-3.5 5.5q-6 7 -10 3t1 -11q6 -6 11 -2zM557 319q2 7 -9 11q-9 3 -13 -4 q-2 -7 9 -11q9 -3 13 4zM599 316q0 8 -12 8q-10 0 -10 -8t11 -8t11 8zM638 323q-2 7 -13 5t-9 -9q2 -8 12 -6t10 10zM1280 640q0 212 -150 362t-362 150t-362 -150t-150 -362q0 -167 98 -300.5t252 -185.5q18 -3 26.5 5t8.5 20q0 52 -1 9 [...]
+<glyph unicode="&#xf093;" horiz-adv-x="1664" d="M1280 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1536 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 288v-320q0 -40 -28 -68t-68 -28h-1472q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h427q21 -56 70.5 -92 t110.5 -36h256q61 0 110.5 36t70.5 92h427q40 0 68 -28t28 -68zM1339 936q-17 -40 -59 -40h-256v-448q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v448h-256q-42 0 -59 40q-17 39 14 69l448 448q18 19 45 19t45 [...]
+<glyph unicode="&#xf094;" d="M1407 710q0 44 -7 113.5t-18 96.5q-12 30 -17 44t-9 36.5t-4 48.5q0 23 5 68.5t5 67.5q0 37 -10 55q-4 1 -13 1q-19 0 -58 -4.5t-59 -4.5q-60 0 -176 24t-175 24q-43 0 -94.5 -11.5t-85 -23.5t-89.5 -34q-137 -54 -202 -103q-96 -73 -159.5 -189.5t-88 -236t-24.5 -248.5 q0 -40 12.5 -120t12.5 -121q0 -23 -11 -66.5t-11 -65.5t12 -36.5t34 -14.5q24 0 72.5 11t73.5 11q57 0 169.5 -15.5t169.5 -15.5q181 0 284 36q129 45 235.5 152.5t166 245.5t59.5 275zM1535 712q0 -165 -70 -327.5t-196 -288t- [...]
+<glyph unicode="&#xf095;" horiz-adv-x="1408" d="M1408 296q0 -27 -10 -70.5t-21 -68.5q-21 -50 -122 -106q-94 -51 -186 -51q-27 0 -52.5 3.5t-57.5 12.5t-47.5 14.5t-55.5 20.5t-49 18q-98 35 -175 83q-128 79 -264.5 215.5t-215.5 264.5q-48 77 -83 175q-3 9 -18 49t-20.5 55.5t-14.5 47.5t-12.5 57.5t-3.5 52.5 q0 92 51 186q56 101 106 122q25 11 68.5 21t70.5 10q14 0 21 -3q18 -6 53 -76q11 -19 30 -54t35 -63.5t31 -53.5q3 -4 17.5 -25t21.5 -35.5t7 -28.5q0 -20 -28.5 -50t-62 -55t-62 -53t-28.5 -46q0 -9 5 -22.5t8.5  [...]
+<glyph unicode="&#xf096;" horiz-adv-x="1408" d="M1120 1280h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113v832q0 66 -47 113t-113 47zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832 q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf097;" horiz-adv-x="1280" d="M1152 1280h-1024v-1242l423 406l89 85l89 -85l423 -406v1242zM1164 1408q23 0 44 -9q33 -13 52.5 -41t19.5 -62v-1289q0 -34 -19.5 -62t-52.5 -41q-19 -8 -44 -8q-48 0 -83 32l-441 424l-441 -424q-36 -33 -83 -33q-23 0 -44 9q-33 13 -52.5 41t-19.5 62v1289 q0 34 19.5 62t52.5 41q21 9 44 9h1048z" />
+<glyph unicode="&#xf098;" d="M1280 343q0 11 -2 16q-3 8 -38.5 29.5t-88.5 49.5l-53 29q-5 3 -19 13t-25 15t-21 5q-18 0 -47 -32.5t-57 -65.5t-44 -33q-7 0 -16.5 3.5t-15.5 6.5t-17 9.5t-14 8.5q-99 55 -170.5 126.5t-126.5 170.5q-2 3 -8.5 14t-9.5 17t-6.5 15.5t-3.5 16.5q0 13 20.5 33.5t45 38.5 t45 39.5t20.5 36.5q0 10 -5 21t-15 25t-13 19q-3 6 -15 28.5t-25 45.5t-26.5 47.5t-25 40.5t-16.5 18t-16 2q-48 0 -101 -22q-46 -21 -80 -94.5t-34 -130.5q0 -16 2.5 -34t5 -30.5t9 -33t10 -29.5t12.5 -33t11 -30q60 -164 216. [...]
+<glyph unicode="&#xf099;" horiz-adv-x="1664" d="M1620 1128q-67 -98 -162 -167q1 -14 1 -42q0 -130 -38 -259.5t-115.5 -248.5t-184.5 -210.5t-258 -146t-323 -54.5q-271 0 -496 145q35 -4 78 -4q225 0 401 138q-105 2 -188 64.5t-114 159.5q33 -5 61 -5q43 0 85 11q-112 23 -185.5 111.5t-73.5 205.5v4q68 -38 146 -41 q-66 44 -105 115t-39 154q0 88 44 163q121 -149 294.5 -238.5t371.5 -99.5q-8 38 -8 74q0 134 94.5 228.5t228.5 94.5q140 0 236 -102q109 21 205 78q-37 -115 -142 -178q93 10 186 50z" />
+<glyph unicode="&#xf09a;" horiz-adv-x="1024" d="M959 1524v-264h-157q-86 0 -116 -36t-30 -108v-189h293l-39 -296h-254v-759h-306v759h-255v296h255v218q0 186 104 288.5t277 102.5q147 0 228 -12z" />
+<glyph unicode="&#xf09b;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5q0 -251 -146.5 -451.5t-378.5 -277.5q-27 -5 -40 7t-13 30q0 3 0.5 76.5t0.5 134.5q0 97 -52 142q57 6 102.5 18t94 39t81 66.5t53 105t20.5 150.5q0 119 -79 206q37 91 -8 204q-28 9 -81 -11t-92 -44l-38 -24 q-93 26 -192 26t-192 -26q-16 11 -42.5 27t-83.5 38.5t-85 13.5q-45 -113 -8 -204q-79 -87 -79 -206q0 -85 20.5 -150t52.5 -105t80.5 -67t94 -39t102.5 -18q-39 -36 -49 -103q-21 -10 -45 -15t-57 -5t-65.5 21.5t-55.5 62.5q-19 32 -4 [...]
+<glyph unicode="&#xf09c;" horiz-adv-x="1664" d="M1664 960v-256q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-192h96q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h672v192q0 185 131.5 316.5t316.5 131.5 t316.5 -131.5t131.5 -316.5z" />
+<glyph unicode="&#xf09d;" horiz-adv-x="1920" d="M1760 1408q66 0 113 -47t47 -113v-1216q0 -66 -47 -113t-113 -47h-1600q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1600zM160 1280q-13 0 -22.5 -9.5t-9.5 -22.5v-224h1664v224q0 13 -9.5 22.5t-22.5 9.5h-1600zM1760 0q13 0 22.5 9.5t9.5 22.5v608h-1664v-608 q0 -13 9.5 -22.5t22.5 -9.5h1600zM256 128v128h256v-128h-256zM640 128v128h384v-128h-384z" />
+<glyph unicode="&#xf09e;" horiz-adv-x="1408" d="M384 192q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM896 69q2 -28 -17 -48q-18 -21 -47 -21h-135q-25 0 -43 16.5t-20 41.5q-22 229 -184.5 391.5t-391.5 184.5q-25 2 -41.5 20t-16.5 43v135q0 29 21 47q17 17 43 17h5q160 -13 306 -80.5 t259 -181.5q114 -113 181.5 -259t80.5 -306zM1408 67q2 -27 -18 -47q-18 -20 -46 -20h-143q-26 0 -44.5 17.5t-19.5 42.5q-12 215 -101 408.5t-231.5 336t-336 231.5t-408.5 102q-25 1 -42.5 19.5t-17.5 43.5 [...]
+<glyph unicode="&#xf0a0;" d="M1040 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1296 320q0 -33 -23.5 -56.5t-56.5 -23.5t-56.5 23.5t-23.5 56.5t23.5 56.5t56.5 23.5t56.5 -23.5t23.5 -56.5zM1408 160v320q0 13 -9.5 22.5t-22.5 9.5 h-1216q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h1216q13 0 22.5 9.5t9.5 22.5zM178 640h1180l-157 482q-4 13 -16 21.5t-26 8.5h-782q-14 0 -26 -8.5t-16 -21.5zM1536 480v-320q0 -66 -47 -113t-113 -47h-1216q- [...]
+<glyph unicode="&#xf0a1;" horiz-adv-x="1792" d="M1664 896q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5v-384q0 -52 -38 -90t-90 -38q-417 347 -812 380q-58 -19 -91 -66t-31 -100.5t40 -92.5q-20 -33 -23 -65.5t6 -58t33.5 -55t48 -50t61.5 -50.5q-29 -58 -111.5 -83t-168.5 -11.5t-132 55.5q-7 23 -29.5 87.5 t-32 94.5t-23 89t-15 101t3.5 98.5t22 110.5h-122q-66 0 -113 47t-47 113v192q0 66 47 113t113 47h480q435 0 896 384q52 0 90 -38t38 -90v-384zM1536 292v954q-394 -302 -768 -343v-270q377 -42 768 -341z" />
+<glyph unicode="&#xf0a2;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM246 128h1300q-266 300 -266 832q0 51 -24 105t-69 103t-121.5 80.5t-169.5 31.5t-169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -532 -266 -832z M1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 4 [...]
+<glyph unicode="&#xf0a3;" d="M1376 640l138 -135q30 -28 20 -70q-12 -41 -52 -51l-188 -48l53 -186q12 -41 -19 -70q-29 -31 -70 -19l-186 53l-48 -188q-10 -40 -51 -52q-12 -2 -19 -2q-31 0 -51 22l-135 138l-135 -138q-28 -30 -70 -20q-41 11 -51 52l-48 188l-186 -53q-41 -12 -70 19q-31 29 -19 70 l53 186l-188 48q-40 10 -52 51q-10 42 20 70l138 135l-138 135q-30 28 -20 70q12 41 52 51l188 48l-53 186q-12 41 19 70q29 31 70 19l186 -53l48 188q10 41 51 51q41 12 70 -19l135 -139l135 139q29 30 70 19q41 -10 51 -51l48 [...]
+<glyph unicode="&#xf0a4;" horiz-adv-x="1792" d="M256 192q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1664 768q0 51 -39 89.5t-89 38.5h-576q0 20 15 48.5t33 55t33 68t15 84.5q0 67 -44.5 97.5t-115.5 30.5q-24 0 -90 -139q-24 -44 -37 -65q-40 -64 -112 -145q-71 -81 -101 -106 q-69 -57 -140 -57h-32v-640h32q72 0 167 -32t193.5 -64t179.5 -32q189 0 189 167q0 26 -5 56q30 16 47.5 52.5t17.5 73.5t-18 69q53 50 53 119q0 25 -10 55.5t-25 47.5h331q52 0 90 38t38 90zM1792 769q0 -105 -75.5 -181t-1 [...]
+<glyph unicode="&#xf0a5;" horiz-adv-x="1792" d="M1376 128h32v640h-32q-35 0 -67.5 12t-62.5 37t-50 46t-49 54q-2 3 -3.5 4.5t-4 4.5t-4.5 5q-72 81 -112 145q-14 22 -38 68q-1 3 -10.5 22.5t-18.5 36t-20 35.5t-21.5 30.5t-18.5 11.5q-71 0 -115.5 -30.5t-44.5 -97.5q0 -43 15 -84.5t33 -68t33 -55t15 -48.5h-576 q-50 0 -89 -38.5t-39 -89.5q0 -52 38 -90t90 -38h331q-15 -17 -25 -47.5t-10 -55.5q0 -69 53 -119q-18 -32 -18 -69t17.5 -73.5t47.5 -52.5q-4 -24 -4 -56q0 -85 48.5 -126t135.5 -41q84 0 183 32t194 64t167 32z [...]
+<glyph unicode="&#xf0a6;" d="M1280 -64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 700q0 189 -167 189q-26 0 -56 -5q-16 30 -52.5 47.5t-73.5 17.5t-69 -18q-50 53 -119 53q-25 0 -55.5 -10t-47.5 -25v331q0 52 -38 90t-90 38q-51 0 -89.5 -39t-38.5 -89v-576 q-20 0 -48.5 15t-55 33t-68 33t-84.5 15q-67 0 -97.5 -44.5t-30.5 -115.5q0 -24 139 -90q44 -24 65 -37q64 -40 145 -112q81 -71 106 -101q57 -69 57 -140v-32h640v32q0 72 32 167t64 193.5t32 179.5zM1536 705q0 -133 -69 -322q-59 -164 - [...]
+<glyph unicode="&#xf0a7;" d="M1408 576q0 84 -32 183t-64 194t-32 167v32h-640v-32q0 -35 -12 -67.5t-37 -62.5t-46 -50t-54 -49q-9 -8 -14 -12q-81 -72 -145 -112q-22 -14 -68 -38q-3 -1 -22.5 -10.5t-36 -18.5t-35.5 -20t-30.5 -21.5t-11.5 -18.5q0 -71 30.5 -115.5t97.5 -44.5q43 0 84.5 15t68 33 t55 33t48.5 15v-576q0 -50 38.5 -89t89.5 -39q52 0 90 38t38 90v331q46 -35 103 -35q69 0 119 53q32 -18 69 -18t73.5 17.5t52.5 47.5q24 -4 56 -4q85 0 126 48.5t41 135.5zM1280 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -4 [...]
+<glyph unicode="&#xf0a8;" d="M1280 576v128q0 26 -19 45t-45 19h-502l189 189q19 19 19 45t-19 45l-91 91q-18 18 -45 18t-45 -18l-362 -362l-91 -91q-18 -18 -18 -45t18 -45l91 -91l362 -362q18 -18 45 -18t45 18l91 91q18 18 18 45t-18 45l-189 189h502q26 0 45 19t19 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0a9;" d="M1285 640q0 27 -18 45l-91 91l-362 362q-18 18 -45 18t-45 -18l-91 -91q-18 -18 -18 -45t18 -45l189 -189h-502q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h502l-189 -189q-19 -19 -19 -45t19 -45l91 -91q18 -18 45 -18t45 18l362 362l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0aa;" d="M1284 641q0 27 -18 45l-362 362l-91 91q-18 18 -45 18t-45 -18l-91 -91l-362 -362q-18 -18 -18 -45t18 -45l91 -91q18 -18 45 -18t45 18l189 189v-502q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v502l189 -189q19 -19 45 -19t45 19l91 91q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ab;" d="M1284 639q0 27 -18 45l-91 91q-18 18 -45 18t-45 -18l-189 -189v502q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-502l-189 189q-19 19 -45 19t-45 -19l-91 -91q-18 -18 -18 -45t18 -45l362 -362l91 -91q18 -18 45 -18t45 18l91 91l362 362q18 18 18 45zM1536 640 q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf0ac;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1042 887q-2 -1 -9.5 -9.5t-13.5 -9.5q2 0 4.5 5t5 11t3.5 7q6 7 22 15q14 6 52 12q34 8 51 -11 q-2 2 9.5 13t14.5 12q3 2 15 4.5t15 7.5l2 22q-12 -1 -17.5 7t-6.5 21q0 -2 -6 -8q0 7 -4.5 8t-11.5 -1t-9 -1q-10 3 -15 7.5t-8 16.5t-4 15q-2 5 -9.5 10.5t-9.5 10.5q-1 2 -2.5 5.5t-3 6.5t-4 5.5t-5.5 2.5t-7 -5t-7.5 -10t-4.5 -5 [...]
+<glyph unicode="&#xf0ad;" horiz-adv-x="1664" d="M384 64q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1028 484l-682 -682q-37 -37 -90 -37q-52 0 -91 37l-106 108q-38 36 -38 90q0 53 38 91l681 681q39 -98 114.5 -173.5t173.5 -114.5zM1662 919q0 -39 -23 -106q-47 -134 -164.5 -217.5 t-258.5 -83.5q-185 0 -316.5 131.5t-131.5 316.5t131.5 316.5t316.5 131.5q58 0 121.5 -16.5t107.5 -46.5q16 -11 16 -28t-16 -28l-293 -169v-224l193 -107q5 3 79 48.5t135.5 81t70.5 35.5q15 0 23.5 -10t8.5 -25z" />
+<glyph unicode="&#xf0ae;" horiz-adv-x="1792" d="M1024 128h640v128h-640v-128zM640 640h1024v128h-1024v-128zM1280 1152h384v128h-384v-128zM1792 320v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 832v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19 t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45zM1792 1344v-256q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1664q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0b0;" horiz-adv-x="1408" d="M1403 1241q17 -41 -14 -70l-493 -493v-742q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-256 256q-19 19 -19 45v486l-493 493q-31 29 -14 70q17 39 59 39h1280q42 0 59 -39z" />
+<glyph unicode="&#xf0b1;" horiz-adv-x="1792" d="M640 1280h512v128h-512v-128zM1792 640v-480q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v480h672v-160q0 -26 19 -45t45 -19h320q26 0 45 19t19 45v160h672zM1024 640v-128h-256v128h256zM1792 1120v-384h-1792v384q0 66 47 113t113 47h352v160q0 40 28 68 t68 28h576q40 0 68 -28t28 -68v-160h352q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf0b2;" d="M1283 995l-355 -355l355 -355l144 144q29 31 70 14q39 -17 39 -59v-448q0 -26 -19 -45t-45 -19h-448q-42 0 -59 40q-17 39 14 69l144 144l-355 355l-355 -355l144 -144q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l144 -144 l355 355l-355 355l-144 -144q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v448q0 26 19 45t45 19h448q42 0 59 -40q17 -39 -14 -69l-144 -144l355 -355l355 355l-144 144q-31 30 -14 69q17 40 59 40h448q26 0 45 -19t19 -45v-448q0  [...]
+<glyph unicode="&#xf0c0;" horiz-adv-x="1920" d="M593 640q-162 -5 -265 -128h-134q-82 0 -138 40.5t-56 118.5q0 353 124 353q6 0 43.5 -21t97.5 -42.5t119 -21.5q67 0 133 23q-5 -37 -5 -66q0 -139 81 -256zM1664 3q0 -120 -73 -189.5t-194 -69.5h-874q-121 0 -194 69.5t-73 189.5q0 53 3.5 103.5t14 109t26.5 108.5 t43 97.5t62 81t85.5 53.5t111.5 20q10 0 43 -21.5t73 -48t107 -48t135 -21.5t135 21.5t107 48t73 48t43 21.5q61 0 111.5 -20t85.5 -53.5t62 -81t43 -97.5t26.5 -108.5t14 -109t3.5 -103.5zM640 1280q0 -106 -7 [...]
+<glyph unicode="&#xf0c1;" horiz-adv-x="1664" d="M1456 320q0 40 -28 68l-208 208q-28 28 -68 28q-42 0 -72 -32q3 -3 19 -18.5t21.5 -21.5t15 -19t13 -25.5t3.5 -27.5q0 -40 -28 -68t-68 -28q-15 0 -27.5 3.5t-25.5 13t-19 15t-21.5 21.5t-18.5 19q-33 -31 -33 -73q0 -40 28 -68l206 -207q27 -27 68 -27q40 0 68 26 l147 146q28 28 28 67zM753 1025q0 40 -28 68l-206 207q-28 28 -68 28q-39 0 -68 -27l-147 -146q-28 -28 -28 -67q0 -40 28 -68l208 -208q27 -27 68 -27q42 0 72 31q-3 3 -19 18.5t-21.5 21.5t-15 19t-13 25.5t-3. [...]
+<glyph unicode="&#xf0c2;" horiz-adv-x="1920" d="M1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088q-185 0 -316.5 131.5t-131.5 316.5q0 132 71 241.5t187 163.5q-2 28 -2 43q0 212 150 362t362 150q158 0 286.5 -88t187.5 -230q70 62 166 62q106 0 181 -75t75 -181q0 -75 -41 -138q129 -30 213 -134.5t84 -239.5z " />
+<glyph unicode="&#xf0c3;" horiz-adv-x="1664" d="M1527 88q56 -89 21.5 -152.5t-140.5 -63.5h-1152q-106 0 -140.5 63.5t21.5 152.5l503 793v399h-64q-26 0 -45 19t-19 45t19 45t45 19h512q26 0 45 -19t19 -45t-19 -45t-45 -19h-64v-399zM748 813l-272 -429h712l-272 429l-20 31v37v399h-128v-399v-37z" />
+<glyph unicode="&#xf0c4;" horiz-adv-x="1792" d="M960 640q26 0 45 -19t19 -45t-19 -45t-45 -19t-45 19t-19 45t19 45t45 19zM1260 576l507 -398q28 -20 25 -56q-5 -35 -35 -51l-128 -64q-13 -7 -29 -7q-17 0 -31 8l-690 387l-110 -66q-8 -4 -12 -5q14 -49 10 -97q-7 -77 -56 -147.5t-132 -123.5q-132 -84 -277 -84 q-136 0 -222 78q-90 84 -79 207q7 76 56 147t131 124q132 84 278 84q83 0 151 -31q9 13 22 22l122 73l-122 73q-13 9 -22 22q-68 -31 -151 -31q-146 0 -278 84q-82 53 -131 124t-56 147q-5 59 15.5 113t63.5 93q85 [...]
+<glyph unicode="&#xf0c5;" horiz-adv-x="1792" d="M1696 1152q40 0 68 -28t28 -68v-1216q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v288h-544q-40 0 -68 28t-28 68v672q0 40 20 88t48 76l408 408q28 28 76 48t88 20h416q40 0 68 -28t28 -68v-328q68 40 128 40h416zM1152 939l-299 -299h299v299zM512 1323l-299 -299 h299v299zM708 676l316 316v416h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h512v256q0 40 20 88t48 76zM1664 -128v1152h-384v-416q0 -40 -28 -68t-68 -28h-416v-640h896z" />
+<glyph unicode="&#xf0c6;" horiz-adv-x="1408" d="M1404 151q0 -117 -79 -196t-196 -79q-135 0 -235 100l-777 776q-113 115 -113 271q0 159 110 270t269 111q158 0 273 -113l605 -606q10 -10 10 -22q0 -16 -30.5 -46.5t-46.5 -30.5q-13 0 -23 10l-606 607q-79 77 -181 77q-106 0 -179 -75t-73 -181q0 -105 76 -181 l776 -777q63 -63 145 -63q64 0 106 42t42 106q0 82 -63 145l-581 581q-26 24 -60 24q-29 0 -48 -19t-19 -48q0 -32 25 -59l410 -410q10 -10 10 -22q0 -16 -31 -47t-47 -31q-12 0 -22 10l-410 410q-63 61 -63 149q0  [...]
+<glyph unicode="&#xf0c7;" d="M384 0h768v384h-768v-384zM1280 0h128v896q0 14 -10 38.5t-20 34.5l-281 281q-10 10 -34 20t-39 10v-416q0 -40 -28 -68t-68 -28h-576q-40 0 -68 28t-28 68v416h-128v-1280h128v416q0 40 28 68t68 28h832q40 0 68 -28t28 -68v-416zM896 928v320q0 13 -9.5 22.5t-22.5 9.5 h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-320q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5zM1536 896v-928q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h928q40 0 88 -20t76 -48l280 -280q28 [...]
+<glyph unicode="&#xf0c8;" d="M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0c9;" d="M1536 192v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 704v-128q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1536 1216v-128q0 -26 -19 -45 t-45 -19h-1408q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0ca;" horiz-adv-x="1792" d="M384 128q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM384 640q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 224v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5 t22.5 9.5h1216q13 0 22.5 -9.5t9.5 -22.5zM384 1152q0 -80 -56 -136t-136 -56t-136 56t-56 136t56 136t136 56t136 -56t56 -136zM1792 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1216q-13 0 -22.5 9.5t-9.5 22. [...]
+<glyph unicode="&#xf0cb;" horiz-adv-x="1792" d="M381 -84q0 -80 -54.5 -126t-135.5 -46q-106 0 -172 66l57 88q49 -45 106 -45q29 0 50.5 14.5t21.5 42.5q0 64 -105 56l-26 56q8 10 32.5 43.5t42.5 54t37 38.5v1q-16 0 -48.5 -1t-48.5 -1v-53h-106v152h333v-88l-95 -115q51 -12 81 -49t30 -88zM383 543v-159h-362 q-6 36 -6 54q0 51 23.5 93t56.5 68t66 47.5t56.5 43.5t23.5 45q0 25 -14.5 38.5t-39.5 13.5q-46 0 -81 -58l-85 59q24 51 71.5 79.5t105.5 28.5q73 0 123 -41.5t50 -112.5q0 -50 -34 -91.5t-75 -64.5t-75.5 -50.5t- [...]
+<glyph unicode="&#xf0cc;" horiz-adv-x="1792" d="M1760 640q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1728q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h1728zM483 704q-28 35 -51 80q-48 97 -48 188q0 181 134 309q133 127 393 127q50 0 167 -19q66 -12 177 -48q10 -38 21 -118q14 -123 14 -183q0 -18 -5 -45l-12 -3l-84 6 l-14 2q-50 149 -103 205q-88 91 -210 91q-114 0 -182 -59q-67 -58 -67 -146q0 -73 66 -140t279 -129q69 -20 173 -66q58 -28 95 -52h-743zM990 448h411q7 -39 7 -92q0 -111 -41 -212q-23 -55 -71 -104q-37 -3 [...]
+<glyph unicode="&#xf0cd;" d="M48 1313q-37 2 -45 4l-3 88q13 1 40 1q60 0 112 -4q132 -7 166 -7q86 0 168 3q116 4 146 5q56 0 86 2l-1 -14l2 -64v-9q-60 -9 -124 -9q-60 0 -79 -25q-13 -14 -13 -132q0 -13 0.5 -32.5t0.5 -25.5l1 -229l14 -280q6 -124 51 -202q35 -59 96 -92q88 -47 177 -47 q104 0 191 28q56 18 99 51q48 36 65 64q36 56 53 114q21 73 21 229q0 79 -3.5 128t-11 122.5t-13.5 159.5l-4 59q-5 67 -24 88q-34 35 -77 34l-100 -2l-14 3l2 86h84l205 -10q76 -3 196 10l18 -2q6 -38 6 -51q0 -7 -4 -31q-45 -12 -84 -1 [...]
+<glyph unicode="&#xf0ce;" horiz-adv-x="1664" d="M512 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 160v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23 v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM512 928v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h320q14 0 23 9t9 23zM1024 544v192q0 14 -9 23t-23 9h-320q-14 0 -23 -9t-9 -2 [...]
+<glyph unicode="&#xf0d0;" horiz-adv-x="1664" d="M1190 955l293 293l-107 107l-293 -293zM1637 1248q0 -27 -18 -45l-1286 -1286q-18 -18 -45 -18t-45 18l-198 198q-18 18 -18 45t18 45l1286 1286q18 18 45 18t45 -18l198 -198q18 -18 18 -45zM286 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM636 1276 l196 -60l-196 -60l-60 -196l-60 196l-196 60l196 60l60 196zM1566 798l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98zM926 1438l98 -30l-98 -30l-30 -98l-30 98l-98 30l98 30l30 98z" />
+<glyph unicode="&#xf0d1;" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5  [...]
+<glyph unicode="&#xf0d2;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11 [...]
+<glyph unicode="&#xf0d3;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 - [...]
+<glyph unicode="&#xf0d4;" d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585 h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0d5;" horiz-adv-x="2304" d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62 q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
+<glyph unicode="&#xf0d6;" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45  [...]
+<glyph unicode="&#xf0d7;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0d8;" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0d9;" horiz-adv-x="640" d="M640 1088v-896q0 -26 -19 -45t-45 -19t-45 19l-448 448q-19 19 -19 45t19 45l448 448q19 19 45 19t45 -19t19 -45z" />
+<glyph unicode="&#xf0da;" horiz-adv-x="640" d="M576 640q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19t-19 45v896q0 26 19 45t45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0db;" horiz-adv-x="1664" d="M160 0h608v1152h-640v-1120q0 -13 9.5 -22.5t22.5 -9.5zM1536 32v1120h-640v-1152h608q13 0 22.5 9.5t9.5 22.5zM1664 1248v-1216q0 -66 -47 -113t-113 -47h-1344q-66 0 -113 47t-47 113v1216q0 66 47 113t113 47h1344q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf0dc;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45zM1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0dd;" horiz-adv-x="1024" d="M1024 448q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf0de;" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
+<glyph unicode="&#xf0e0;" horiz-adv-x="1792" d="M1792 826v-794q0 -66 -47 -113t-113 -47h-1472q-66 0 -113 47t-47 113v794q44 -49 101 -87q362 -246 497 -345q57 -42 92.5 -65.5t94.5 -48t110 -24.5h1h1q51 0 110 24.5t94.5 48t92.5 65.5q170 123 498 345q57 39 100 87zM1792 1120q0 -79 -49 -151t-122 -123 q-376 -261 -468 -325q-10 -7 -42.5 -30.5t-54 -38t-52 -32.5t-57.5 -27t-50 -9h-1h-1q-23 0 -50 9t-57.5 27t-52 32.5t-54 38t-42.5 30.5q-91 64 -262 182.5t-205 142.5q-62 42 -117 115.5t-55 136.5q0 78 41.5 130t11 [...]
+<glyph unicode="&#xf0e1;" d="M349 911v-991h-330v991h330zM370 1217q1 -73 -50.5 -122t-135.5 -49h-2q-82 0 -132 49t-50 122q0 74 51.5 122.5t134.5 48.5t133 -48.5t51 -122.5zM1536 488v-568h-329v530q0 105 -40.5 164.5t-126.5 59.5q-63 0 -105.5 -34.5t-63.5 -85.5q-11 -30 -11 -81v-553h-329 q2 399 2 647t-1 296l-1 48h329v-144h-2q20 32 41 56t56.5 52t87 43.5t114.5 15.5q171 0 275 -113.5t104 -332.5z" />
+<glyph unicode="&#xf0e2;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 - [...]
+<glyph unicode="&#xf0e3;" horiz-adv-x="1792" d="M1771 0q0 -53 -37 -90l-107 -108q-39 -37 -91 -37q-53 0 -90 37l-363 364q-38 36 -38 90q0 53 43 96l-256 256l-126 -126q-14 -14 -34 -14t-34 14q2 -2 12.5 -12t12.5 -13t10 -11.5t10 -13.5t6 -13.5t5.5 -16.5t1.5 -18q0 -38 -28 -68q-3 -3 -16.5 -18t-19 -20.5 t-18.5 -16.5t-22 -15.5t-22 -9t-26 -4.5q-40 0 -68 28l-408 408q-28 28 -28 68q0 13 4.5 26t9 22t15.5 22t16.5 18.5t20.5 19t18 16.5q30 28 68 28q10 0 18 -1.5t16.5 -5.5t13.5 -6t13.5 -10t11.5 -10t13 -12.5t12 - [...]
+<glyph unicode="&#xf0e4;" horiz-adv-x="1792" d="M384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM576 832q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1004 351l101 382q6 26 -7.5 48.5t-38.5 29.5 t-48 -6.5t-30 -39.5l-101 -382q-60 -5 -107 -43.5t-63 -98.5q-20 -77 20 -146t117 -89t146 20t89 117q16 60 -6 117t-72 91zM1664 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37 [...]
+<glyph unicode="&#xf0e5;" horiz-adv-x="1792" d="M896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171l43 38l57 -6q69 -8 130 -8q204 0 381.5 69.5t282 187.5t104.5 255t-104.5 255t-282 187.5t-381.5 69.5zM1792 640 q0 -174 -120 -321.5t-326 -233t-450 -85.5q-70 0 -145 8q-198 -175 -460 -242q-49 -14 -114 -22h-5q-15 0 -27 10.5t-16 27.5v1q-3 4 -0.5 12t2 10t4.5 9.5l6 9t7 8.5t8 9q7 8 31 34.5t34.5 38t31 39.5t32.5 51t27 59t26  [...]
+<glyph unicode="&#xf0e6;" horiz-adv-x="1792" d="M704 1152q-153 0 -286 -52t-211.5 -141t-78.5 -191q0 -82 53 -158t149 -132l97 -56l-35 -84q34 20 62 39l44 31l53 -10q78 -14 153 -14q153 0 286 52t211.5 141t78.5 191t-78.5 191t-211.5 141t-286 52zM704 1280q191 0 353.5 -68.5t256.5 -186.5t94 -257t-94 -257 t-256.5 -186.5t-353.5 -68.5q-86 0 -176 16q-124 -88 -278 -128q-36 -9 -86 -16h-3q-11 0 -20.5 8t-11.5 21q-1 3 -1 6.5t0.5 6.5t2 6l2.5 5t3.5 5.5t4 5t4.5 5t4 4.5q5 6 23 25t26 29.5t22.5 29t25 38.5t20.5 44q [...]
+<glyph unicode="&#xf0e7;" horiz-adv-x="896" d="M885 970q18 -20 7 -44l-540 -1157q-13 -25 -42 -25q-4 0 -14 2q-17 5 -25.5 19t-4.5 30l197 808l-406 -101q-4 -1 -12 -1q-18 0 -31 11q-18 15 -13 39l201 825q4 14 16 23t28 9h328q19 0 32 -12.5t13 -29.5q0 -8 -5 -18l-171 -463l396 98q8 2 12 2q19 0 34 -15z" />
+<glyph unicode="&#xf0e8;" horiz-adv-x="1792" d="M1792 288v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192h-512v-192h96q40 0 68 -28t28 -68v-320 q0 -40 -28 -68t-68 -28h-320q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h96v192q0 52 38 90t90 38h512v192h-96q-40 0 -68 28t-28 68v320q0 40 28 68t68 28h320q40 0 68 -28t28 -68v-320q0 -40 -28 -68t-68 -28h-96v-192h [...]
+<glyph unicode="&#xf0e9;" horiz-adv-x="1664" d="M896 708v-580q0 -104 -76 -180t-180 -76t-180 76t-76 180q0 26 19 45t45 19t45 -19t19 -45q0 -50 39 -89t89 -39t89 39t39 89v580q33 11 64 11t64 -11zM1664 681q0 -13 -9.5 -22.5t-22.5 -9.5q-11 0 -23 10q-49 46 -93 69t-102 23q-68 0 -128 -37t-103 -97 q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -28 -17q-18 0 -29 17q-4 6 -14.5 24t-17.5 28q-43 60 -102.5 97t-127.5 37t-127.5 -37t-102.5 -97q-7 -10 -17.5 -28t-14.5 -24q-11 -17 -29 -17q-17 0 -28 17q-4 6 -14.5 24t-17.5 2 [...]
+<glyph unicode="&#xf0ea;" horiz-adv-x="1792" d="M768 -128h896v640h-416q-40 0 -68 28t-28 68v416h-384v-1152zM1024 1312v64q0 13 -9.5 22.5t-22.5 9.5h-704q-13 0 -22.5 -9.5t-9.5 -22.5v-64q0 -13 9.5 -22.5t22.5 -9.5h704q13 0 22.5 9.5t9.5 22.5zM1280 640h299l-299 299v-299zM1792 512v-672q0 -40 -28 -68t-68 -28 h-960q-40 0 -68 28t-28 68v160h-544q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1088q40 0 68 -28t28 -68v-328q21 -13 36 -28l408 -408q28 -28 48 -76t20 -88z" />
+<glyph unicode="&#xf0eb;" horiz-adv-x="1024" d="M736 960q0 -13 -9.5 -22.5t-22.5 -9.5t-22.5 9.5t-9.5 22.5q0 46 -54 71t-106 25q-13 0 -22.5 9.5t-9.5 22.5t9.5 22.5t22.5 9.5q50 0 99.5 -16t87 -54t37.5 -90zM896 960q0 72 -34.5 134t-90 101.5t-123 62t-136.5 22.5t-136.5 -22.5t-123 -62t-90 -101.5t-34.5 -134 q0 -101 68 -180q10 -11 30.5 -33t30.5 -33q128 -153 141 -298h228q13 145 141 298q10 11 30.5 33t30.5 33q68 79 68 180zM1024 960q0 -155 -103 -268q-45 -49 -74.5 -87t-59.5 -95.5t-34 -107.5q47 -28 47 -82q [...]
+<glyph unicode="&#xf0ec;" horiz-adv-x="1792" d="M1792 352v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-1376v-192q0 -13 -9.5 -22.5t-22.5 -9.5q-12 0 -24 10l-319 320q-9 9 -9 22q0 14 9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h1376q13 0 22.5 -9.5t9.5 -22.5zM1792 896q0 -14 -9 -23l-320 -320q-9 -9 -23 -9 q-13 0 -22.5 9.5t-9.5 22.5v192h-1376q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h1376v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23z" />
+<glyph unicode="&#xf0ed;" horiz-adv-x="1920" d="M1280 608q0 14 -9 23t-23 9h-224v352q0 13 -9.5 22.5t-22.5 9.5h-192q-13 0 -22.5 -9.5t-9.5 -22.5v-352h-224q-13 0 -22.5 -9.5t-9.5 -22.5q0 -14 9 -23l352 -352q9 -9 23 -9t23 9l351 351q10 12 10 24zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+<glyph unicode="&#xf0ee;" horiz-adv-x="1920" d="M1280 672q0 14 -9 23l-352 352q-9 9 -23 9t-23 -9l-351 -351q-10 -12 -10 -24q0 -14 9 -23t23 -9h224v-352q0 -13 9.5 -22.5t22.5 -9.5h192q13 0 22.5 9.5t9.5 22.5v352h224q13 0 22.5 9.5t9.5 22.5zM1920 384q0 -159 -112.5 -271.5t-271.5 -112.5h-1088 q-185 0 -316.5 131.5t-131.5 316.5q0 130 70 240t188 165q-2 30 -2 43q0 212 150 362t362 150q156 0 285.5 -87t188.5 -231q71 62 166 62q106 0 181 -75t75 -181q0 -76 -41 -138q130 -31 213.5 -135.5t83.5 -238.5z" />
+<glyph unicode="&#xf0f0;" horiz-adv-x="1408" d="M384 192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM1408 131q0 -121 -73 -190t-194 -69h-874q-121 0 -194 69t-73 190q0 68 5.5 131t24 138t47.5 132.5t81 103t120 60.5q-22 -52 -22 -120v-203q-58 -20 -93 -70t-35 -111q0 -80 56 -136t136 -56 t136 56t56 136q0 61 -35.5 111t-92.5 70v203q0 62 25 93q132 -104 295 -104t295 104q25 -31 25 -93v-64q-106 0 -181 -75t-75 -181v-89q-32 -29 -32 -71q0 -40 28 -68t68 -28t68 28t28 68q0 42 -32 71v89q0 52 [...]
+<glyph unicode="&#xf0f1;" horiz-adv-x="1408" d="M1280 832q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 832q0 -62 -35.5 -111t-92.5 -70v-395q0 -159 -131.5 -271.5t-316.5 -112.5t-316.5 112.5t-131.5 271.5v132q-164 20 -274 128t-110 252v512q0 26 19 45t45 19q6 0 16 -2q17 30 47 48 t65 18q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5q-33 0 -64 18v-402q0 -106 94 -181t226 -75t226 75t94 181v402q-31 -18 -64 -18q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5q35 0 65 -18t47 - [...]
+<glyph unicode="&#xf0f2;" horiz-adv-x="1792" d="M640 1152h512v128h-512v-128zM288 1152v-1280h-64q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h64zM1408 1152v-1280h-1024v1280h128v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h128zM1792 928v-832q0 -92 -66 -158t-158 -66h-64v1280h64q92 0 158 -66 t66 -158z" />
+<glyph unicode="&#xf0f3;" horiz-adv-x="1792" d="M912 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM1728 128q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-181 75t-75 181h-448q-52 0 -90 38t-38 90q50 42 91 88t85 119.5t74.5 158.5 t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68 28t68 -28t28 -68q0 -20 -8 -39q190 -28 307 -158.5t117 -282.5q0 -139 19.5 -260t50 -206t74.5 -158.5t85 -119.5t91 -88z" />
+<glyph unicode="&#xf0f4;" horiz-adv-x="1920" d="M1664 896q0 80 -56 136t-136 56h-64v-384h64q80 0 136 56t56 136zM0 128h1792q0 -106 -75 -181t-181 -75h-1280q-106 0 -181 75t-75 181zM1856 896q0 -159 -112.5 -271.5t-271.5 -112.5h-64v-32q0 -92 -66 -158t-158 -66h-704q-92 0 -158 66t-66 158v736q0 26 19 45 t45 19h1152q159 0 271.5 -112.5t112.5 -271.5z" />
+<glyph unicode="&#xf0f5;" horiz-adv-x="1408" d="M640 1472v-640q0 -61 -35.5 -111t-92.5 -70v-779q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v779q-57 20 -92.5 70t-35.5 111v640q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45v-416q0 -26 19 -45 t45 -19t45 19t19 45v416q0 26 19 45t45 19t45 -19t19 -45zM1408 1472v-1600q0 -52 -38 -90t-90 -38h-128q-52 0 -90 38t-38 90v512h-224q-13 0 -22.5 9.5t-9.5 22.5v800q0 132 94 226t226 94h256q26 0 45 -19t1 [...]
+<glyph unicode="&#xf0f6;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M384 736q0 14 9 23t23 9h704q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64zM1120 512q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-704q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h704zM1120 256q14 0 23 -9t9 [...]
+<glyph unicode="&#xf0f7;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22 [...]
+<glyph unicode="&#xf0f8;" horiz-adv-x="1408" d="M384 224v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5z M640 480v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22.5v64q0 13 9.5 22.5t22.5 9.5h64q13 0 22.5 -9.5t9.5 -22.5zM384 736v-64q0 -13 -9.5 -22.5t-22.5 -9.5h-64q-13 0 -22.5 9.5t-9.5 22 [...]
+<glyph unicode="&#xf0f9;" horiz-adv-x="1920" d="M640 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM256 640h384v256h-158q-14 -2 -22 -9l-195 -195q-7 -12 -9 -22v-30zM1536 128q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5zM1664 800v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23  [...]
+<glyph unicode="&#xf0fa;" horiz-adv-x="1792" d="M1280 416v192q0 14 -9 23t-23 9h-224v224q0 14 -9 23t-23 9h-192q-14 0 -23 -9t-9 -23v-224h-224q-14 0 -23 -9t-9 -23v-192q0 -14 9 -23t23 -9h224v-224q0 -14 9 -23t23 -9h192q14 0 23 9t9 23v224h224q14 0 23 9t9 23zM640 1152h512v128h-512v-128zM256 1152v-1280h-32 q-92 0 -158 66t-66 158v832q0 92 66 158t158 66h32zM1440 1152v-1280h-1088v1280h160v160q0 40 28 68t68 28h576q40 0 68 -28t28 -68v-160h160zM1792 928v-832q0 -92 -66 -158t-158 -66h-32v1280h32q92 0 15 [...]
+<glyph unicode="&#xf0fb;" horiz-adv-x="1920" d="M1920 576q-1 -32 -288 -96l-352 -32l-224 -64h-64l-293 -352h69q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-96h-160h-64v32h64v416h-160l-192 -224h-96l-32 32v192h32v32h128v8l-192 24v128l192 24v8h-128v32h-32v192l32 32h96l192 -224h160v416h-64v32h64h160h96 q26 0 45 -4.5t19 -11.5t-19 -11.5t-45 -4.5h-69l293 -352h64l224 -64l352 -32q261 -58 287 -93z" />
+<glyph unicode="&#xf0fc;" horiz-adv-x="1664" d="M640 640v384h-256v-256q0 -53 37.5 -90.5t90.5 -37.5h128zM1664 192v-192h-1152v192l128 192h-128q-159 0 -271.5 112.5t-112.5 271.5v320l-64 64l32 128h480l32 128h960l32 -192l-64 -32v-800z" />
+<glyph unicode="&#xf0fd;" d="M1280 192v896q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-512v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-896q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h512v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf0fe;" d="M1280 576v128q0 26 -19 45t-45 19h-320v320q0 26 -19 45t-45 19h-128q-26 0 -45 -19t-19 -45v-320h-320q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h320v-320q0 -26 19 -45t45 -19h128q26 0 45 19t19 45v320h320q26 0 45 19t19 45zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf100;" horiz-adv-x="1024" d="M627 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23zM1011 160q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23z" />
+<glyph unicode="&#xf101;" horiz-adv-x="1024" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM979 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23 l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf102;" horiz-adv-x="1152" d="M1075 224q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23zM1075 608q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393 q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf103;" horiz-adv-x="1152" d="M1075 672q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23zM1075 1056q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23 t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf104;" horiz-adv-x="640" d="M627 992q0 -13 -10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf105;" horiz-adv-x="640" d="M595 576q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf106;" horiz-adv-x="1152" d="M1075 352q0 -13 -10 -23l-50 -50q-10 -10 -23 -10t-23 10l-393 393l-393 -393q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l466 -466q10 -10 10 -23z" />
+<glyph unicode="&#xf107;" horiz-adv-x="1152" d="M1075 800q0 -13 -10 -23l-466 -466q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l393 -393l393 393q10 10 23 10t23 -10l50 -50q10 -10 10 -23z" />
+<glyph unicode="&#xf108;" horiz-adv-x="1920" d="M1792 544v832q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-832q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1376v-1088q0 -66 -47 -113t-113 -47h-544q0 -37 16 -77.5t32 -71t16 -43.5q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19 t-19 45q0 14 16 44t32 70t16 78h-544q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf109;" horiz-adv-x="1920" d="M416 256q-66 0 -113 47t-47 113v704q0 66 47 113t113 47h1088q66 0 113 -47t47 -113v-704q0 -66 -47 -113t-113 -47h-1088zM384 1120v-704q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5v704q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5z M1760 192h160v-96q0 -40 -47 -68t-113 -28h-1600q-66 0 -113 28t-47 68v96h160h1600zM1040 96q16 0 16 16t-16 16h-160q-16 0 -16 -16t16 -16h160z" />
+<glyph unicode="&#xf10a;" horiz-adv-x="1152" d="M640 128q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1024 288v960q0 13 -9.5 22.5t-22.5 9.5h-832q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h832q13 0 22.5 9.5t9.5 22.5zM1152 1248v-1088q0 -66 -47 -113t-113 -47h-832 q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h832q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf10b;" horiz-adv-x="768" d="M464 128q0 33 -23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t23.5 -56.5t56.5 -23.5t56.5 23.5t23.5 56.5zM672 288v704q0 13 -9.5 22.5t-22.5 9.5h-512q-13 0 -22.5 -9.5t-9.5 -22.5v-704q0 -13 9.5 -22.5t22.5 -9.5h512q13 0 22.5 9.5t9.5 22.5zM480 1136 q0 16 -16 16h-160q-16 0 -16 -16t16 -16h160q16 0 16 16zM768 1152v-1024q0 -52 -38 -90t-90 -38h-512q-52 0 -90 38t-38 90v1024q0 52 38 90t90 38h512q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf10c;" d="M768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103 t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf10d;" horiz-adv-x="1664" d="M768 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75 -181v-32q0 -40 28 -68t68 -28h224q80 0 136 -56t56 -136z M1664 576v-384q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v704q0 104 40.5 198.5t109.5 163.5t163.5 109.5t198.5 40.5h64q26 0 45 -19t19 -45v-128q0 -26 -19 -45t-45 -19h-64q-106 0 -181 -75t-75  [...]
+<glyph unicode="&#xf10e;" horiz-adv-x="1664" d="M768 1216v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 56 136t136 56h384q80 0 136 -56t56 -136zM1664 1216 v-704q0 -104 -40.5 -198.5t-109.5 -163.5t-163.5 -109.5t-198.5 -40.5h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64q106 0 181 75t75 181v32q0 40 -28 68t-68 28h-224q-80 0 -136 56t-56 136v384q0 80 [...]
+<glyph unicode="&#xf110;" horiz-adv-x="1792" d="M526 142q0 -53 -37.5 -90.5t-90.5 -37.5q-52 0 -90 38t-38 90q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 -64q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM320 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1522 142q0 -52 -38 -90t-90 -38q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM558 1138q0 -66 -47 -113t-11 [...]
+<glyph unicode="&#xf111;" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf112;" horiz-adv-x="1792" d="M1792 416q0 -166 -127 -451q-3 -7 -10.5 -24t-13.5 -30t-13 -22q-12 -17 -28 -17q-15 0 -23.5 10t-8.5 25q0 9 2.5 26.5t2.5 23.5q5 68 5 123q0 101 -17.5 181t-48.5 138.5t-80 101t-105.5 69.5t-133 42.5t-154 21.5t-175.5 6h-224v-256q0 -26 -19 -45t-45 -19t-45 19 l-512 512q-19 19 -19 45t19 45l512 512q19 19 45 19t45 -19t19 -45v-256h224q713 0 875 -403q53 -134 53 -333z" />
+<glyph unicode="&#xf113;" horiz-adv-x="1664" d="M640 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1280 320q0 -40 -12.5 -82t-43 -76t-72.5 -34t-72.5 34t-43 76t-12.5 82t12.5 82t43 76t72.5 34t72.5 -34t43 -76t12.5 -82zM1440 320 q0 120 -69 204t-187 84q-41 0 -195 -21q-71 -11 -157 -11t-157 11q-152 21 -195 21q-118 0 -187 -84t-69 -204q0 -88 32 -153.5t81 -103t122 -60t140 -29.5t149 -7h168q82 0 149 7t140 29.5t122 60t81 103t32 153.5zM16 [...]
+<glyph unicode="&#xf114;" horiz-adv-x="1664" d="M1536 224v704q0 40 -28 68t-68 28h-704q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68v-960q0 -40 28 -68t68 -28h1216q40 0 68 28t28 68zM1664 928v-704q0 -92 -66 -158t-158 -66h-1216q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320 q92 0 158 -66t66 -158v-32h672q92 0 158 -66t66 -158z" />
+<glyph unicode="&#xf115;" horiz-adv-x="1920" d="M1781 605q0 35 -53 35h-1088q-40 0 -85.5 -21.5t-71.5 -52.5l-294 -363q-18 -24 -18 -40q0 -35 53 -35h1088q40 0 86 22t71 53l294 363q18 22 18 39zM640 768h768v160q0 40 -28 68t-68 28h-576q-40 0 -68 28t-28 68v64q0 40 -28 68t-68 28h-320q-40 0 -68 -28t-28 -68 v-853l256 315q44 53 116 87.5t140 34.5zM1909 605q0 -62 -46 -120l-295 -363q-43 -53 -116 -87.5t-140 -34.5h-1088q-92 0 -158 66t-66 158v960q0 92 66 158t158 66h320q92 0 158 -66t66 -158v-32h544q92 0 158 [...]
+<glyph unicode="&#xf116;" horiz-adv-x="1792" />
+<glyph unicode="&#xf117;" horiz-adv-x="1792" />
+<glyph unicode="&#xf118;" d="M1134 461q-37 -121 -138 -195t-228 -74t-228 74t-138 195q-8 25 4 48.5t38 31.5q25 8 48.5 -4t31.5 -38q25 -80 92.5 -129.5t151.5 -49.5t151.5 49.5t92.5 129.5q8 26 32 38t49 4t37 -31.5t4 -48.5zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-2 [...]
+<glyph unicode="&#xf119;" d="M1134 307q8 -25 -4 -48.5t-37 -31.5t-49 4t-32 38q-25 80 -92.5 129.5t-151.5 49.5t-151.5 -49.5t-92.5 -129.5q-8 -26 -31.5 -38t-48.5 -4q-26 8 -38 31.5t-4 48.5q37 121 138 195t228 74t228 -74t138 -195zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248 [...]
+<glyph unicode="&#xf11a;" d="M1152 448q0 -26 -19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h640q26 0 45 -19t19 -45zM640 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1152 896q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5 t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136. [...]
+<glyph unicode="&#xf11b;" horiz-adv-x="1920" d="M832 448v128q0 14 -9 23t-23 9h-192v192q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-192h-192q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h192v-192q0 -14 9 -23t23 -9h128q14 0 23 9t9 23v192h192q14 0 23 9t9 23zM1408 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1664 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1920 512q0 -212 -150 -362t-362 -1 [...]
+<glyph unicode="&#xf11c;" horiz-adv-x="1920" d="M384 368v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM512 624v-96q0 -16 -16 -16h-224q-16 0 -16 16v96q0 16 16 16h224q16 0 16 -16zM384 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM1408 368v-96q0 -16 -16 -16 h-864q-16 0 -16 16v96q0 16 16 16h864q16 0 16 -16zM768 624v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16zM640 880v-96q0 -16 -16 -16h-96q-16 0 -16 16v96q0 16 16 16h96q16 0 16 -16z [...]
+<glyph unicode="&#xf11d;" horiz-adv-x="1792" d="M1664 491v616q-169 -91 -306 -91q-82 0 -145 32q-100 49 -184 76.5t-178 27.5q-173 0 -403 -127v-599q245 113 433 113q55 0 103.5 -7.5t98 -26t77 -31t82.5 -39.5l28 -14q44 -22 101 -22q120 0 293 92zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q0 -14 -9 -23t-23 -9 h-64q-14 0 -23 9t-9 23v1266q-29 17 -46.5 46t-17.5 64q0 53 37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1792 1216v-763q0 -39 -35 -57q-10 -5 -17 -9q-218 -116 -369 -116q-88 0 -158 35l-28 14q-64 33 -9 [...]
+<glyph unicode="&#xf11e;" horiz-adv-x="1792" d="M832 536v192q-181 -16 -384 -117v-185q205 96 384 110zM832 954v197q-172 -8 -384 -126v-189q215 111 384 118zM1664 491v184q-235 -116 -384 -71v224q-20 6 -39 15q-5 3 -33 17t-34.5 17t-31.5 15t-34.5 15.5t-32.5 13t-36 12.5t-35 8.5t-39.5 7.5t-39.5 4t-44 2 q-23 0 -49 -3v-222h19q102 0 192.5 -29t197.5 -82q19 -9 39 -15v-188q42 -17 91 -17q120 0 293 92zM1664 918v189q-169 -91 -306 -91q-45 0 -78 8v-196q148 -42 384 90zM320 1280q0 -35 -17.5 -64t-46.5 -46v-1266q [...]
+<glyph unicode="&#xf120;" horiz-adv-x="1664" d="M585 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10t23 -10l466 -466q10 -10 10 -23t-10 -23zM1664 96v-64q0 -14 -9 -23t-23 -9h-960q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h960q14 0 23 -9 t9 -23z" />
+<glyph unicode="&#xf121;" horiz-adv-x="1920" d="M617 137l-50 -50q-10 -10 -23 -10t-23 10l-466 466q-10 10 -10 23t10 23l466 466q10 10 23 10t23 -10l50 -50q10 -10 10 -23t-10 -23l-393 -393l393 -393q10 -10 10 -23t-10 -23zM1208 1204l-373 -1291q-4 -13 -15.5 -19.5t-23.5 -2.5l-62 17q-13 4 -19.5 15.5t-2.5 24.5 l373 1291q4 13 15.5 19.5t23.5 2.5l62 -17q13 -4 19.5 -15.5t2.5 -24.5zM1865 553l-466 -466q-10 -10 -23 -10t-23 10l-50 50q-10 10 -10 23t10 23l393 393l-393 393q-10 10 -10 23t10 23l50 50q10 10 23 10 [...]
+<glyph unicode="&#xf122;" horiz-adv-x="1792" d="M640 454v-70q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-69l-397 -398q-19 -19 -19 -45t19 -45zM1792 416q0 -58 -17 -133.5t-38.5 -138t-48 -125t-40.5 -90.5l-20 -40q-8 -17 -28 -17q-6 0 -9 1 q-25 8 -23 34q43 400 -106 565q-64 71 -170.5 110.5t-267.5 52.5v-251q0 -42 -39 -59q-13 -5 -25 -5q-27 0 -45 19l-512 512q-19 19 -19 45t19 45l512 512q29 31 70 14q39 -17 39 -59v-262q411 -28 599 -221q169 - [...]
+<glyph unicode="&#xf123;" horiz-adv-x="1664" d="M1186 579l257 250l-356 52l-66 10l-30 60l-159 322v-963l59 -31l318 -168l-60 355l-12 66zM1638 841l-363 -354l86 -500q5 -33 -6 -51.5t-34 -18.5q-17 0 -40 12l-449 236l-449 -236q-23 -12 -40 -12q-23 0 -34 18.5t-6 51.5l86 500l-364 354q-32 32 -23 59.5t54 34.5 l502 73l225 455q20 41 49 41q28 0 49 -41l225 -455l502 -73q45 -7 54 -34.5t-24 -59.5z" />
+<glyph unicode="&#xf124;" horiz-adv-x="1408" d="M1401 1187l-640 -1280q-17 -35 -57 -35q-5 0 -15 2q-22 5 -35.5 22.5t-13.5 39.5v576h-576q-22 0 -39.5 13.5t-22.5 35.5t4 42t29 30l1280 640q13 7 29 7q27 0 45 -19q15 -14 18.5 -34.5t-6.5 -39.5z" />
+<glyph unicode="&#xf125;" horiz-adv-x="1664" d="M557 256h595v595zM512 301l595 595h-595v-595zM1664 224v-192q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v224h-864q-14 0 -23 9t-9 23v864h-224q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h224v224q0 14 9 23t23 9h192q14 0 23 -9t9 -23 v-224h851l246 247q10 9 23 9t23 -9q9 -10 9 -23t-9 -23l-247 -246v-851h224q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf126;" horiz-adv-x="1024" d="M288 64q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM288 1216q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM928 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1024 1088q0 -52 -26 -96.5t-70 -69.5 q-2 -287 -226 -414q-68 -38 -203 -81q-128 -40 -169.5 -71t-41.5 -100v-26q44 -25 70 -69.5t26 -96.5q0 -80 -56 -136t-136 -56t-136 56t-56 136q0 52 26 96.5t70 69.5v820q-44 25 -70 69.5t-26 96.5q0 80 56 13 [...]
+<glyph unicode="&#xf127;" horiz-adv-x="1664" d="M439 265l-256 -256q-10 -9 -23 -9q-12 0 -23 9q-9 10 -9 23t9 23l256 256q10 9 23 9t23 -9q9 -10 9 -23t-9 -23zM608 224v-320q0 -14 -9 -23t-23 -9t-23 9t-9 23v320q0 14 9 23t23 9t23 -9t9 -23zM384 448q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23t9 23t23 9h320 q14 0 23 -9t9 -23zM1648 320q0 -120 -85 -203l-147 -146q-83 -83 -203 -83q-121 0 -204 85l-334 335q-21 21 -42 56l239 18l273 -274q27 -27 68 -27.5t68 26.5l147 146q28 28 28 67q0 40 -28 68l-274 275l18 239 [...]
+<glyph unicode="&#xf128;" horiz-adv-x="1024" d="M704 280v-240q0 -16 -12 -28t-28 -12h-240q-16 0 -28 12t-12 28v240q0 16 12 28t28 12h240q16 0 28 -12t12 -28zM1020 880q0 -54 -15.5 -101t-35 -76.5t-55 -59.5t-57.5 -43.5t-61 -35.5q-41 -23 -68.5 -65t-27.5 -67q0 -17 -12 -32.5t-28 -15.5h-240q-15 0 -25.5 18.5 t-10.5 37.5v45q0 83 65 156.5t143 108.5q59 27 84 56t25 76q0 42 -46.5 74t-107.5 32q-65 0 -108 -29q-35 -25 -107 -115q-13 -16 -31 -16q-12 0 -25 8l-164 125q-13 10 -15.5 25t5.5 28q160 266 464 266q80 0 [...]
+<glyph unicode="&#xf129;" horiz-adv-x="640" d="M640 192v-128q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h64v384h-64q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h384q26 0 45 -19t19 -45v-576h64q26 0 45 -19t19 -45zM512 1344v-192q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v192 q0 26 19 45t45 19h256q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf12a;" horiz-adv-x="640" d="M512 288v-224q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v224q0 26 19 45t45 19h256q26 0 45 -19t19 -45zM542 1344l-28 -768q-1 -26 -20.5 -45t-45.5 -19h-256q-26 0 -45.5 19t-20.5 45l-28 768q-1 26 17.5 45t44.5 19h320q26 0 44.5 -19t17.5 -45z" />
+<glyph unicode="&#xf12b;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1534 846v-206h-514l-3 27 q-4 28 -4 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q83 65 188 65q110 0 178 -59.5t68 -158.5q0 -56 -24.5 -103t-62 -76.5t-81.5 -58.5t- [...]
+<glyph unicode="&#xf12c;" d="M897 167v-167h-248l-159 252l-24 42q-8 9 -11 21h-3l-9 -21q-10 -20 -25 -44l-155 -250h-258v167h128l197 291l-185 272h-137v168h276l139 -228q2 -4 23 -42q8 -9 11 -21h3q3 9 11 21l25 42l140 228h257v-168h-125l-184 -267l204 -296h109zM1536 -50v-206h-514l-4 27 q-3 45 -3 46q0 64 26 117t65 86.5t84 65t84 54.5t65 54t26 64q0 38 -29.5 62.5t-70.5 24.5q-51 0 -97 -39q-14 -11 -36 -38l-105 92q26 37 63 66q80 65 188 65q110 0 178 -59.5t68 -158.5q0 -66 -34.5 -118.5t-84 -86t-99.5 -62.5t- [...]
+<glyph unicode="&#xf12d;" horiz-adv-x="1920" d="M896 128l336 384h-768l-336 -384h768zM1909 1205q15 -34 9.5 -71.5t-30.5 -65.5l-896 -1024q-38 -44 -96 -44h-768q-38 0 -69.5 20.5t-47.5 54.5q-15 34 -9.5 71.5t30.5 65.5l896 1024q38 44 96 44h768q38 0 69.5 -20.5t47.5 -54.5z" />
+<glyph unicode="&#xf12e;" horiz-adv-x="1664" d="M1664 438q0 -81 -44.5 -135t-123.5 -54q-41 0 -77.5 17.5t-59 38t-56.5 38t-71 17.5q-110 0 -110 -124q0 -39 16 -115t15 -115v-5q-22 0 -33 -1q-34 -3 -97.5 -11.5t-115.5 -13.5t-98 -5q-61 0 -103 26.5t-42 83.5q0 37 17.5 71t38 56.5t38 59t17.5 77.5q0 79 -54 123.5 t-135 44.5q-84 0 -143 -45.5t-59 -127.5q0 -43 15 -83t33.5 -64.5t33.5 -53t15 -50.5q0 -45 -46 -89q-37 -35 -117 -35q-95 0 -245 24q-9 2 -27.5 4t-27.5 4l-13 2q-1 0 -3 1q-2 0 -2 1v1024q2 -1 17.5 -3.5t [...]
+<glyph unicode="&#xf130;" horiz-adv-x="1152" d="M1152 832v-128q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-217 24 -364.5 187.5t-147.5 384.5v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -185 131.5 -316.5t316.5 -131.5 t316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45zM896 1216v-512q0 -132 -94 -226t-226 -94t-226 94t-94 226v512q0 132 94 226t226 94t226 -94t94 -226z" />
+<glyph unicode="&#xf131;" horiz-adv-x="1408" d="M271 591l-101 -101q-42 103 -42 214v128q0 26 19 45t45 19t45 -19t19 -45v-128q0 -53 15 -113zM1385 1193l-361 -361v-128q0 -132 -94 -226t-226 -94q-55 0 -109 19l-96 -96q97 -51 205 -51q185 0 316.5 131.5t131.5 316.5v128q0 26 19 45t45 19t45 -19t19 -45v-128 q0 -221 -147.5 -384.5t-364.5 -187.5v-132h256q26 0 45 -19t19 -45t-19 -45t-45 -19h-640q-26 0 -45 19t-19 45t19 45t45 19h256v132q-125 13 -235 81l-254 -254q-10 -10 -23 -10t-23 10l-82 82q-10 10 -10 23t10 [...]
+<glyph unicode="&#xf132;" horiz-adv-x="1280" d="M1088 576v640h-448v-1137q119 63 213 137q235 184 235 360zM1280 1344v-768q0 -86 -33.5 -170.5t-83 -150t-118 -127.5t-126.5 -103t-121 -77.5t-89.5 -49.5t-42.5 -20q-12 -6 -26 -6t-26 6q-16 7 -42.5 20t-89.5 49.5t-121 77.5t-126.5 103t-118 127.5t-83 150 t-33.5 170.5v768q0 26 19 45t45 19h1152q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf133;" horiz-adv-x="1664" d="M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280 q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128q52 0 90 -38t38 -90z" />
+<glyph unicode="&#xf134;" horiz-adv-x="1408" d="M512 1344q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1408 1376v-320q0 -16 -12 -25q-8 -7 -20 -7q-4 0 -7 1l-448 96q-11 2 -18 11t-7 20h-256v-102q111 -23 183.5 -111t72.5 -203v-800q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v800 q0 106 62.5 190.5t161.5 114.5v111h-32q-59 0 -115 -23.5t-91.5 -53t-66 -66.5t-40.5 -53.5t-14 -24.5q-17 -35 -57 -35q-16 0 -29 7q-23 12 -31.5 37t3.5 49q5 10 14.5 26t37.5 53.5t60.5 70t85 67t108.5 52.5q-2 [...]
+<glyph unicode="&#xf135;" horiz-adv-x="1664" d="M1440 1088q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1664 1376q0 -249 -75.5 -430.5t-253.5 -360.5q-81 -80 -195 -176l-20 -379q-2 -16 -16 -26l-384 -224q-7 -4 -16 -4q-12 0 -23 9l-64 64q-13 14 -8 32l85 276l-281 281l-276 -85q-3 -1 -9 -1 q-14 0 -23 9l-64 64q-17 19 -5 39l224 384q10 14 26 16l379 20q96 114 176 195q188 187 358 258t431 71q14 0 24 -9.5t10 -22.5z" />
+<glyph unicode="&#xf136;" horiz-adv-x="1792" d="M1745 763l-164 -763h-334l178 832q13 56 -15 88q-27 33 -83 33h-169l-204 -953h-334l204 953h-286l-204 -953h-334l204 953l-153 327h1276q101 0 189.5 -40.5t147.5 -113.5q60 -73 81 -168.5t0 -194.5z" />
+<glyph unicode="&#xf137;" d="M909 141l102 102q19 19 19 45t-19 45l-307 307l307 307q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf138;" d="M717 141l454 454q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l307 -307l-307 -307q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf139;" d="M1165 397l102 102q19 19 19 45t-19 45l-454 454q-19 19 -45 19t-45 -19l-454 -454q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l307 307l307 -307q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf13a;" d="M813 237l454 454q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-307 -307l-307 307q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l454 -454q19 -19 45 -19t45 19zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5 t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf13b;" horiz-adv-x="1408" d="M1130 939l16 175h-884l47 -534h612l-22 -228l-197 -53l-196 53l-13 140h-175l22 -278l362 -100h4v1l359 99l50 544h-644l-15 181h674zM0 1408h1408l-128 -1438l-578 -162l-574 162z" />
+<glyph unicode="&#xf13c;" horiz-adv-x="1792" d="M275 1408h1505l-266 -1333l-804 -267l-698 267l71 356h297l-29 -147l422 -161l486 161l68 339h-1208l58 297h1209l38 191h-1208z" />
+<glyph unicode="&#xf13d;" horiz-adv-x="1792" d="M960 1280q0 26 -19 45t-45 19t-45 -19t-19 -45t19 -45t45 -19t45 19t19 45zM1792 352v-352q0 -22 -20 -30q-8 -2 -12 -2q-13 0 -23 9l-93 93q-119 -143 -318.5 -226.5t-429.5 -83.5t-429.5 83.5t-318.5 226.5l-93 -93q-9 -9 -23 -9q-4 0 -12 2q-20 8 -20 30v352 q0 14 9 23t23 9h352q22 0 30 -20q8 -19 -7 -35l-100 -100q67 -91 189.5 -153.5t271.5 -82.5v647h-192q-26 0 -45 19t-19 45v128q0 26 19 45t45 19h192v163q-58 34 -93 92.5t-35 128.5q0 106 75 181t181 75t181 -75t75 [...]
+<glyph unicode="&#xf13e;" horiz-adv-x="1152" d="M1056 768q40 0 68 -28t28 -68v-576q0 -40 -28 -68t-68 -28h-960q-40 0 -68 28t-28 68v576q0 40 28 68t68 28h32v320q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -26 -19 -45t-45 -19h-64q-26 0 -45 19t-19 45q0 106 -75 181t-181 75t-181 -75t-75 -181 v-320h736z" />
+<glyph unicode="&#xf140;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM1152 640q0 159 -112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5t271.5 -112.5t271.5 112.5t112.5 271.5zM1280 640q0 -212 -150 -362t-362 -150t-362 150 t-150 362t150 362t362 150t362 -150t150 -362zM1408 640q0 130 -51 248.5t-136.5 204t-204 136.5t-248.5 51t-248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 2 [...]
+<glyph unicode="&#xf141;" horiz-adv-x="1408" d="M384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM896 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM1408 800v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf142;" horiz-adv-x="384" d="M384 288v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 800v-192q0 -40 -28 -68t-68 -28h-192q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68zM384 1312v-192q0 -40 -28 -68t-68 -28h-192 q-40 0 -68 28t-28 68v192q0 40 28 68t68 28h192q40 0 68 -28t28 -68z" />
+<glyph unicode="&#xf143;" d="M512 256q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM863 162q-13 232 -177 396t-396 177q-14 1 -24 -9t-10 -23v-128q0 -13 8.5 -22t21.5 -10q154 -11 264 -121t121 -264q1 -13 10 -21.5t22 -8.5h128q13 0 23 10 t9 24zM1247 161q-5 154 -56 297.5t-139.5 260t-205 205t-260 139.5t-297.5 56q-14 1 -23 -9q-10 -10 -10 -23v-128q0 -13 9 -22t22 -10q204 -7 378 -111.5t278.5 -278.5t111.5 -378q1 -13 10 -22t22 -9h128q13 0 23 10q11 9 9 23z [...]
+<glyph unicode="&#xf144;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM1152 585q32 18 32 55t-32 55l-544 320q-31 19 -64 1q-32 -19 -32 -56v-640q0 -37 32 -56 q16 -8 32 -8q17 0 32 9z" />
+<glyph unicode="&#xf145;" horiz-adv-x="1792" d="M1024 1084l316 -316l-572 -572l-316 316zM813 105l618 618q19 19 19 45t-19 45l-362 362q-18 18 -45 18t-45 -18l-618 -618q-19 -19 -19 -45t19 -45l362 -362q18 -18 45 -18t45 18zM1702 742l-907 -908q-37 -37 -90.5 -37t-90.5 37l-126 126q56 56 56 136t-56 136 t-136 56t-136 -56l-125 126q-37 37 -37 90.5t37 90.5l907 906q37 37 90.5 37t90.5 -37l125 -125q-56 -56 -56 -136t56 -136t136 -56t136 56l126 -125q37 -37 37 -90.5t-37 -90.5z" />
+<glyph unicode="&#xf146;" d="M1280 576v128q0 26 -19 45t-45 19h-896q-26 0 -45 -19t-19 -45v-128q0 -26 19 -45t45 -19h896q26 0 45 19t19 45zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
+<glyph unicode="&#xf147;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h832q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5 t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf148;" horiz-adv-x="1024" d="M1018 933q-18 -37 -58 -37h-192v-864q0 -14 -9 -23t-23 -9h-704q-21 0 -29 18q-8 20 4 35l160 192q9 11 25 11h320v640h-192q-40 0 -58 37q-17 37 9 68l320 384q18 22 49 22t49 -22l320 -384q27 -32 9 -68z" />
+<glyph unicode="&#xf149;" horiz-adv-x="1024" d="M32 1280h704q13 0 22.5 -9.5t9.5 -23.5v-863h192q40 0 58 -37t-9 -69l-320 -384q-18 -22 -49 -22t-49 22l-320 384q-26 31 -9 69q18 37 58 37h192v640h-320q-14 0 -25 11l-160 192q-13 14 -4 34q9 19 29 19z" />
+<glyph unicode="&#xf14a;" d="M685 237l614 614q19 19 19 45t-19 45l-102 102q-19 19 -45 19t-45 -19l-467 -467l-211 211q-19 19 -45 19t-45 -19l-102 -102q-19 -19 -19 -45t19 -45l358 -358q19 -19 45 -19t45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5 t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14b;" d="M404 428l152 -152l-52 -52h-56v96h-96v56zM818 818q14 -13 -3 -30l-291 -291q-17 -17 -30 -3q-14 13 3 30l291 291q17 17 30 3zM544 128l544 544l-288 288l-544 -544v-288h288zM1152 736l92 92q28 28 28 68t-28 68l-152 152q-28 28 -68 28t-68 -28l-92 -92zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14c;" d="M1280 608v480q0 26 -19 45t-45 19h-480q-42 0 -59 -39q-17 -41 14 -70l144 -144l-534 -534q-19 -19 -19 -45t19 -45l102 -102q19 -19 45 -19t45 19l534 534l144 -144q18 -19 45 -19q12 0 25 5q39 17 39 59zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960 q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14d;" d="M1005 435l352 352q19 19 19 45t-19 45l-352 352q-30 31 -69 14q-40 -17 -40 -59v-160q-119 0 -216 -19.5t-162.5 -51t-114 -79t-76.5 -95.5t-44.5 -109t-21.5 -111.5t-5 -110.5q0 -181 167 -404q10 -12 25 -12q7 0 13 3q22 9 19 33q-44 354 62 473q46 52 130 75.5 t224 23.5v-160q0 -42 40 -59q12 -5 24 -5q26 0 45 19zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf14e;" d="M640 448l256 128l-256 128v-256zM1024 1039v-542l-512 -256v542zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf150;" d="M1145 861q18 -35 -5 -66l-320 -448q-19 -27 -52 -27t-52 27l-320 448q-23 31 -5 66q17 35 57 35h640q40 0 57 -35zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120 v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf151;" d="M1145 419q-17 -35 -57 -35h-640q-40 0 -57 35q-18 35 5 66l320 448q19 27 52 27t52 -27l320 -448q23 -31 5 -66zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5zM1536 1120v-960 q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf152;" d="M1088 640q0 -33 -27 -52l-448 -320q-31 -23 -66 -5q-35 17 -35 57v640q0 40 35 57q35 18 66 -5l448 -320q27 -19 27 -52zM1280 160v960q0 14 -9 23t-23 9h-960q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h960q14 0 23 9t9 23zM1536 1120v-960q0 -119 -84.5 -203.5 t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf153;" horiz-adv-x="1024" d="M976 229l35 -159q3 -12 -3 -22.5t-17 -14.5l-5 -1q-4 -2 -10.5 -3.5t-16 -4.5t-21.5 -5.5t-25.5 -5t-30 -5t-33.5 -4.5t-36.5 -3t-38.5 -1q-234 0 -409 130.5t-238 351.5h-95q-13 0 -22.5 9.5t-9.5 22.5v113q0 13 9.5 22.5t22.5 9.5h66q-2 57 1 105h-67q-14 0 -23 9 t-9 23v114q0 14 9 23t23 9h98q67 210 243.5 338t400.5 128q102 0 194 -23q11 -3 20 -15q6 -11 3 -24l-43 -159q-3 -13 -14 -19.5t-24 -2.5l-4 1q-4 1 -11.5 2.5l-17.5 3.5t-22.5 3.5t-26 3t-29 2.5t-29.5 1q-126  [...]
+<glyph unicode="&#xf154;" horiz-adv-x="1024" d="M1020 399v-367q0 -14 -9 -23t-23 -9h-956q-14 0 -23 9t-9 23v150q0 13 9.5 22.5t22.5 9.5h97v383h-95q-14 0 -23 9.5t-9 22.5v131q0 14 9 23t23 9h95v223q0 171 123.5 282t314.5 111q185 0 335 -125q9 -8 10 -20.5t-7 -22.5l-103 -127q-9 -11 -22 -12q-13 -2 -23 7 q-5 5 -26 19t-69 32t-93 18q-85 0 -137 -47t-52 -123v-215h305q13 0 22.5 -9t9.5 -23v-131q0 -13 -9.5 -22.5t-22.5 -9.5h-305v-379h414v181q0 13 9 22.5t23 9.5h162q14 0 23 -9.5t9 -22.5z" />
+<glyph unicode="&#xf155;" horiz-adv-x="1024" d="M978 351q0 -153 -99.5 -263.5t-258.5 -136.5v-175q0 -14 -9 -23t-23 -9h-135q-13 0 -22.5 9.5t-9.5 22.5v175q-66 9 -127.5 31t-101.5 44.5t-74 48t-46.5 37.5t-17.5 18q-17 21 -2 41l103 135q7 10 23 12q15 2 24 -9l2 -2q113 -99 243 -125q37 -8 74 -8q81 0 142.5 43 t61.5 122q0 28 -15 53t-33.5 42t-58.5 37.5t-66 32t-80 32.5q-39 16 -61.5 25t-61.5 26.5t-62.5 31t-56.5 35.5t-53.5 42.5t-43.5 49t-35.5 58t-21 66.5t-8.5 78q0 138 98 242t255 134v180q0 13 9.5 22.5t22.5  [...]
+<glyph unicode="&#xf156;" horiz-adv-x="898" d="M898 1066v-102q0 -14 -9 -23t-23 -9h-168q-23 -144 -129 -234t-276 -110q167 -178 459 -536q14 -16 4 -34q-8 -18 -29 -18h-195q-16 0 -25 12q-306 367 -498 571q-9 9 -9 22v127q0 13 9.5 22.5t22.5 9.5h112q132 0 212.5 43t102.5 125h-427q-14 0 -23 9t-9 23v102 q0 14 9 23t23 9h413q-57 113 -268 113h-145q-13 0 -22.5 9.5t-9.5 22.5v133q0 14 9 23t23 9h832q14 0 23 -9t9 -23v-102q0 -14 -9 -23t-23 -9h-233q47 -61 64 -144h171q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf157;" horiz-adv-x="1027" d="M603 0h-172q-13 0 -22.5 9t-9.5 23v330h-288q-13 0 -22.5 9t-9.5 23v103q0 13 9.5 22.5t22.5 9.5h288v85h-288q-13 0 -22.5 9t-9.5 23v104q0 13 9.5 22.5t22.5 9.5h214l-321 578q-8 16 0 32q10 16 28 16h194q19 0 29 -18l215 -425q19 -38 56 -125q10 24 30.5 68t27.5 61 l191 420q8 19 29 19h191q17 0 27 -16q9 -14 1 -31l-313 -579h215q13 0 22.5 -9.5t9.5 -22.5v-104q0 -14 -9.5 -23t-22.5 -9h-290v-85h290q13 0 22.5 -9.5t9.5 -22.5v-103q0 -14 -9.5 -23t-22.5 -9h-290v-330q [...]
+<glyph unicode="&#xf158;" horiz-adv-x="1280" d="M1043 971q0 100 -65 162t-171 62h-320v-448h320q106 0 171 62t65 162zM1280 971q0 -193 -126.5 -315t-326.5 -122h-340v-118h505q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-505v-192q0 -14 -9.5 -23t-22.5 -9h-167q-14 0 -23 9t-9 23v192h-224q-14 0 -23 9t-9 23v128 q0 14 9 23t23 9h224v118h-224q-14 0 -23 9t-9 23v149q0 13 9 22.5t23 9.5h224v629q0 14 9 23t23 9h539q200 0 326.5 -122t126.5 -315z" />
+<glyph unicode="&#xf159;" horiz-adv-x="1792" d="M514 341l81 299h-159l75 -300q1 -1 1 -3t1 -3q0 1 0.5 3.5t0.5 3.5zM630 768l35 128h-292l32 -128h225zM822 768h139l-35 128h-70zM1271 340l78 300h-162l81 -299q0 -1 0.5 -3.5t1.5 -3.5q0 1 0.5 3t0.5 3zM1382 768l33 128h-297l34 -128h230zM1792 736v-64q0 -14 -9 -23 t-23 -9h-213l-164 -616q-7 -24 -31 -24h-159q-24 0 -31 24l-166 616h-209l-167 -616q-7 -24 -31 -24h-159q-11 0 -19.5 7t-10.5 17l-160 616h-208q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h175l-33 128h-142q-1 [...]
+<glyph unicode="&#xf15a;" horiz-adv-x="1280" d="M1167 896q18 -182 -131 -258q117 -28 175 -103t45 -214q-7 -71 -32.5 -125t-64.5 -89t-97 -58.5t-121.5 -34.5t-145.5 -15v-255h-154v251q-80 0 -122 1v-252h-154v255q-18 0 -54 0.5t-55 0.5h-200l31 183h111q50 0 58 51v402h16q-6 1 -16 1v287q-13 68 -89 68h-111v164 l212 -1q64 0 97 1v252h154v-247q82 2 122 2v245h154v-252q79 -7 140 -22.5t113 -45t82.5 -78t36.5 -114.5zM952 351q0 36 -15 64t-37 46t-57.5 30.5t-65.5 18.5t-74 9t-69 3t-64.5 -1t-47.5 -1v-338q8 0 37 -0 [...]
+<glyph unicode="&#xf15b;" d="M1024 1024v472q22 -14 36 -28l408 -408q14 -14 28 -36h-472zM896 992q0 -40 28 -68t68 -28h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544z" />
+<glyph unicode="&#xf15c;" d="M1468 1060q14 -14 28 -36h-472v472q22 -14 36 -28zM992 896h544v-1056q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h800v-544q0 -40 28 -68t68 -28zM1152 160v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704 q14 0 23 9t9 23zM1152 416v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23zM1152 672v64q0 14 -9 23t-23 9h-704q-14 0 -23 -9t-9 -23v-64q0 -14 9 -23t23 -9h704q14 0 23 9t9 23z" />
+<glyph unicode="&#xf15d;" horiz-adv-x="1664" d="M1191 1128h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1572 -23 v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567v-89l-369 -530q-6 -8 -21 -26l-11 -11v-2l14 2q9 2 30 2h248v119h121zM1661 874v-106h-288v106h75l- [...]
+<glyph unicode="&#xf15e;" horiz-adv-x="1664" d="M1191 104h177l-72 218l-12 47q-2 16 -2 20h-4l-3 -20q0 -1 -3.5 -18t-7.5 -29zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1661 -150 v-106h-288v106h75l-47 144h-243l-47 -144h75v-106h-287v106h70l230 662h162l230 -662h70zM1572 1001v-233h-584v90l369 529q12 18 21 27l11 9v3q-2 0 -6.5 -0.5t-7.5 -0.5q-12 -3 -30 -3h-232v-115h-120v229h567 [...]
+<glyph unicode="&#xf160;" horiz-adv-x="1792" d="M736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23zM1792 -32v-192q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h832 q14 0 23 -9t9 -23zM1600 480v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14 0 23 -9t9 -23zM1408 992v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14  [...]
+<glyph unicode="&#xf161;" horiz-adv-x="1792" d="M1216 -32v-192q0 -14 -9 -23t-23 -9h-256q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h256q14 0 23 -9t9 -23zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192 q14 0 23 -9t9 -23zM1408 480v-192q0 -14 -9 -23t-23 -9h-448q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h448q14 0 23 -9t9 -23zM1600 992v-192q0 -14 -9 -23t-23 -9h-640q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h640q14  [...]
+<glyph unicode="&#xf162;" d="M1346 223q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9t9 -23 zM1486 165q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -42 15l39 113q15 -7 31 -11q37 -13 75 -13q84 0 134.5 58.5t66.5 145.5h-2q-21 -23 -61.5 -37t-84.5 -14q-106 0 -173 71.5t-67 [...]
+<glyph unicode="&#xf163;" d="M1346 1247q0 63 -44 116t-103 53q-52 0 -83 -37t-31 -94t36.5 -95t104.5 -38q50 0 85 27t35 68zM736 96q0 -12 -10 -24l-319 -319q-10 -9 -23 -9q-12 0 -23 9l-320 320q-15 16 -7 35q8 20 30 20h192v1376q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1376h192q14 0 23 -9 t9 -23zM1456 -142v-114h-469v114h167v432q0 7 0.5 19t0.5 17v16h-2l-7 -12q-8 -13 -26 -31l-62 -58l-82 86l192 185h123v-654h165zM1486 1189q0 -62 -13 -121.5t-41 -114t-68 -95.5t-98.5 -65.5t-127.5 -24.5q-62 0 -108 16q-24 8 -4 [...]
+<glyph unicode="&#xf164;" horiz-adv-x="1664" d="M256 192q0 26 -19 45t-45 19q-27 0 -45.5 -19t-18.5 -45q0 -27 18.5 -45.5t45.5 -18.5q26 0 45 18.5t19 45.5zM416 704v-640q0 -26 -19 -45t-45 -19h-288q-26 0 -45 19t-19 45v640q0 26 19 45t45 19h288q26 0 45 -19t19 -45zM1600 704q0 -86 -55 -149q15 -44 15 -76 q3 -76 -43 -137q17 -56 0 -117q-15 -57 -54 -94q9 -112 -49 -181q-64 -76 -197 -78h-36h-76h-17q-66 0 -144 15.5t-121.5 29t-120.5 39.5q-123 43 -158 44q-26 1 -45 19.5t-19 44.5v641q0 25 18 43.5t43 20.5q24  [...]
+<glyph unicode="&#xf165;" horiz-adv-x="1664" d="M256 960q0 -26 -19 -45t-45 -19q-27 0 -45.5 19t-18.5 45q0 27 18.5 45.5t45.5 18.5q26 0 45 -18.5t19 -45.5zM416 448v640q0 26 -19 45t-45 19h-288q-26 0 -45 -19t-19 -45v-640q0 -26 19 -45t45 -19h288q26 0 45 19t19 45zM1545 597q55 -61 55 -149q-1 -78 -57.5 -135 t-134.5 -57h-277q4 -14 8 -24t11 -22t10 -18q18 -37 27 -57t19 -58.5t10 -76.5q0 -24 -0.5 -39t-5 -45t-12 -50t-24 -45t-40 -40.5t-60 -26t-82.5 -10.5q-26 0 -45 19q-20 20 -34 50t-19.5 52t-12.5 61q-9 42 [...]
+<glyph unicode="&#xf166;" d="M919 233v157q0 50 -29 50q-17 0 -33 -16v-224q16 -16 33 -16q29 0 29 49zM1103 355h66v34q0 51 -33 51t-33 -51v-34zM532 621v-70h-80v-423h-74v423h-78v70h232zM733 495v-367h-67v40q-39 -45 -76 -45q-33 0 -42 28q-6 16 -6 54v290h66v-270q0 -24 1 -26q1 -15 15 -15 q20 0 42 31v280h67zM985 384v-146q0 -52 -7 -73q-12 -42 -53 -42q-35 0 -68 41v-36h-67v493h67v-161q32 40 68 40q41 0 53 -42q7 -21 7 -74zM1236 255v-9q0 -29 -2 -43q-3 -22 -15 -40q-27 -40 -80 -40q-52 0 -81 38q-21 27 -21 86 [...]
+<glyph unicode="&#xf167;" d="M971 292v-211q0 -67 -39 -67q-23 0 -45 22v301q22 22 45 22q39 0 39 -67zM1309 291v-46h-90v46q0 68 45 68t45 -68zM343 509h107v94h-312v-94h105v-569h100v569zM631 -60h89v494h-89v-378q-30 -42 -57 -42q-18 0 -21 21q-1 3 -1 35v364h-89v-391q0 -49 8 -73 q12 -37 58 -37q48 0 102 61v-54zM1060 88v197q0 73 -9 99q-17 56 -71 56q-50 0 -93 -54v217h-89v-663h89v48q45 -55 93 -55q54 0 71 55q9 27 9 100zM1398 98v13h-91q0 -51 -2 -61q-7 -36 -40 -36q-46 0 -46 69v87h179v103q0 79 -27 116q-39  [...]
+<glyph unicode="&#xf168;" horiz-adv-x="1408" d="M597 869q-10 -18 -257 -456q-27 -46 -65 -46h-239q-21 0 -31 17t0 36l253 448q1 0 0 1l-161 279q-12 22 -1 37q9 15 32 15h239q40 0 66 -45zM1403 1511q11 -16 0 -37l-528 -934v-1l336 -615q11 -20 1 -37q-10 -15 -32 -15h-239q-42 0 -66 45l-339 622q18 32 531 942 q25 45 64 45h241q22 0 31 -15z" />
+<glyph unicode="&#xf169;" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf16a;" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
+<glyph unicode="&#xf16b;" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
+<glyph unicode="&#xf16c;" d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
+<glyph unicode="&#xf16d;" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-11 [...]
+<glyph unicode="&#xf16e;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
+<glyph unicode="&#xf170;" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf171;" horiz-adv-x="1408" d="M815 677q8 -63 -50.5 -101t-111.5 -6q-39 17 -53.5 58t-0.5 82t52 58q36 18 72.5 12t64 -35.5t27.5 -67.5zM926 698q-14 107 -113 164t-197 13q-63 -28 -100.5 -88.5t-34.5 -129.5q4 -91 77.5 -155t165.5 -56q91 8 152 84t50 168zM1165 1240q-20 27 -56 44.5t-58 22 t-71 12.5q-291 47 -566 -2q-43 -7 -66 -12t-55 -22t-50 -43q30 -28 76 -45.5t73.5 -22t87.5 -11.5q228 -29 448 -1q63 8 89.5 12t72.5 21.5t75 46.5zM1222 205q-8 -26 -15.5 -76.5t-14 -84t-28.5 -70t-58 -56.5q- [...]
+<glyph unicode="&#xf172;" d="M848 666q0 43 -41 66t-77 1q-43 -20 -42.5 -72.5t43.5 -70.5q39 -23 81 4t36 72zM928 682q8 -66 -36 -121t-110 -61t-119 40t-56 113q-2 49 25.5 93t72.5 64q70 31 141.5 -10t81.5 -118zM1100 1073q-20 -21 -53.5 -34t-53 -16t-63.5 -8q-155 -20 -324 0q-44 6 -63 9.5 t-52.5 16t-54.5 32.5q13 19 36 31t40 15.5t47 8.5q198 35 408 1q33 -5 51 -8.5t43 -16t39 -31.5zM1142 327q0 7 5.5 26.5t3 32t-17.5 16.5q-161 -106 -365 -106t-366 106l-12 -6l-5 -12q26 -154 41 -210q47 -81 204 -108q249 -46 4 [...]
+<glyph unicode="&#xf173;" horiz-adv-x="1024" d="M944 207l80 -237q-23 -35 -111 -66t-177 -32q-104 -2 -190.5 26t-142.5 74t-95 106t-55.5 120t-16.5 118v544h-168v215q72 26 129 69.5t91 90t58 102t34 99t15 88.5q1 5 4.5 8.5t7.5 3.5h244v-424h333v-252h-334v-518q0 -30 6.5 -56t22.5 -52.5t49.5 -41.5t81.5 -14 q78 2 134 29z" />
+<glyph unicode="&#xf174;" d="M1136 75l-62 183q-44 -22 -103 -22q-36 -1 -62 10.5t-38.5 31.5t-17.5 40.5t-5 43.5v398h257v194h-256v326h-188q-8 0 -9 -10q-5 -44 -17.5 -87t-39 -95t-77 -95t-118.5 -68v-165h130v-418q0 -57 21.5 -115t65 -111t121 -85.5t176.5 -30.5q69 1 136.5 25t85.5 50z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf175;" horiz-adv-x="768" d="M765 237q8 -19 -5 -35l-350 -384q-10 -10 -23 -10q-14 0 -24 10l-355 384q-13 16 -5 35q9 19 29 19h224v1248q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-1248h224q21 0 29 -19z" />
+<glyph unicode="&#xf176;" horiz-adv-x="768" d="M765 1043q-9 -19 -29 -19h-224v-1248q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v1248h-224q-21 0 -29 19t5 35l350 384q10 10 23 10q14 0 24 -10l355 -384q13 -16 5 -35z" />
+<glyph unicode="&#xf177;" horiz-adv-x="1792" d="M1792 736v-192q0 -14 -9 -23t-23 -9h-1248v-224q0 -21 -19 -29t-35 5l-384 350q-10 10 -10 23q0 14 10 24l384 354q16 14 35 6q19 -9 19 -29v-224h1248q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf178;" horiz-adv-x="1792" d="M1728 643q0 -14 -10 -24l-384 -354q-16 -14 -35 -6q-19 9 -19 29v224h-1248q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h1248v224q0 21 19 29t35 -5l384 -350q10 -10 10 -23z" />
+<glyph unicode="&#xf179;" horiz-adv-x="1408" d="M1393 321q-39 -125 -123 -250q-129 -196 -257 -196q-49 0 -140 32q-86 32 -151 32q-61 0 -142 -33q-81 -34 -132 -34q-152 0 -301 259q-147 261 -147 503q0 228 113 374q112 144 284 144q72 0 177 -30q104 -30 138 -30q45 0 143 34q102 34 173 34q119 0 213 -65 q52 -36 104 -100q-79 -67 -114 -118q-65 -94 -65 -207q0 -124 69 -223t158 -126zM1017 1494q0 -61 -29 -136q-30 -75 -93 -138q-54 -54 -108 -72q-37 -11 -104 -17q3 149 78 257q74 107 250 148q1 -3 2.5 -11t2.5 -11 [...]
+<glyph unicode="&#xf17a;" horiz-adv-x="1664" d="M682 530v-651l-682 94v557h682zM682 1273v-659h-682v565zM1664 530v-786l-907 125v661h907zM1664 1408v-794h-907v669z" />
+<glyph unicode="&#xf17b;" horiz-adv-x="1408" d="M493 1053q16 0 27.5 11.5t11.5 27.5t-11.5 27.5t-27.5 11.5t-27 -11.5t-11 -27.5t11 -27.5t27 -11.5zM915 1053q16 0 27 11.5t11 27.5t-11 27.5t-27 11.5t-27.5 -11.5t-11.5 -27.5t11.5 -27.5t27.5 -11.5zM103 869q42 0 72 -30t30 -72v-430q0 -43 -29.5 -73t-72.5 -30 t-73 30t-30 73v430q0 42 30 72t73 30zM1163 850v-666q0 -46 -32 -78t-77 -32h-75v-227q0 -43 -30 -73t-73 -30t-73 30t-30 73v227h-138v-227q0 -43 -30 -73t-73 -30q-42 0 -72 30t-30 73l-1 227h-74q-46 0 -78  [...]
+<glyph unicode="&#xf17c;" d="M663 1125q-11 -1 -15.5 -10.5t-8.5 -9.5q-5 -1 -5 5q0 12 19 15h10zM750 1111q-4 -1 -11.5 6.5t-17.5 4.5q24 11 32 -2q3 -6 -3 -9zM399 684q-4 1 -6 -3t-4.5 -12.5t-5.5 -13.5t-10 -13q-7 -10 -1 -12q4 -1 12.5 7t12.5 18q1 3 2 7t2 6t1.5 4.5t0.5 4v3t-1 2.5t-3 2z M1254 325q0 18 -55 42q4 15 7.5 27.5t5 26t3 21.5t0.5 22.5t-1 19.5t-3.5 22t-4 20.5t-5 25t-5.5 26.5q-10 48 -47 103t-72 75q24 -20 57 -83q87 -162 54 -278q-11 -40 -50 -42q-31 -4 -38.5 18.5t-8 83.5t-11.5 107q-9 39 -19.5 69 [...]
+<glyph unicode="&#xf17d;" d="M1024 36q-42 241 -140 498h-2l-2 -1q-16 -6 -43 -16.5t-101 -49t-137 -82t-131 -114.5t-103 -148l-15 11q184 -150 418 -150q132 0 256 52zM839 643q-21 49 -53 111q-311 -93 -673 -93q-1 -7 -1 -21q0 -124 44 -236.5t124 -201.5q50 89 123.5 166.5t142.5 124.5t130.5 81 t99.5 48l37 13q4 1 13 3.5t13 4.5zM732 855q-120 213 -244 378q-138 -65 -234 -186t-128 -272q302 0 606 80zM1416 536q-210 60 -409 29q87 -239 128 -469q111 75 185 189.5t96 250.5zM611 1277q-1 0 -2 -1q1 1 2 1zM1201 1132q [...]
+<glyph unicode="&#xf17e;" d="M1173 473q0 50 -19.5 91.5t-48.5 68.5t-73 49t-82.5 34t-87.5 23l-104 24q-30 7 -44 10.5t-35 11.5t-30 16t-16.5 21t-7.5 30q0 77 144 77q43 0 77 -12t54 -28.5t38 -33.5t40 -29t48 -12q47 0 75.5 32t28.5 77q0 55 -56 99.5t-142 67.5t-182 23q-68 0 -132 -15.5 t-119.5 -47t-89 -87t-33.5 -128.5q0 -61 19 -106.5t56 -75.5t80 -48.5t103 -32.5l146 -36q90 -22 112 -36q32 -20 32 -60q0 -39 -40 -64.5t-105 -25.5q-51 0 -91.5 16t-65 38.5t-45.5 45t-46 38.5t-54 16q-50 0 -75.5 -30t-25.5 -75q0 - [...]
+<glyph unicode="&#xf180;" horiz-adv-x="1280" d="M1000 1102l37 194q5 23 -9 40t-35 17h-712q-23 0 -38.5 -17t-15.5 -37v-1101q0 -7 6 -1l291 352q23 26 38 33.5t48 7.5h239q22 0 37 14.5t18 29.5q24 130 37 191q4 21 -11.5 40t-36.5 19h-294q-29 0 -48 19t-19 48v42q0 29 19 47.5t48 18.5h346q18 0 35 13.5t20 29.5z M1227 1324q-15 -73 -53.5 -266.5t-69.5 -350t-35 -173.5q-6 -22 -9 -32.5t-14 -32.5t-24.5 -33t-38.5 -21t-58 -10h-271q-13 0 -22 -10q-8 -9 -426 -494q-22 -25 -58.5 -28.5t-48.5 5.5q-55 22 -55 98v1410q0 5 [...]
+<glyph unicode="&#xf181;" d="M704 192v1024q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-1024q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1376 576v640q0 14 -9 23t-23 9h-480q-14 0 -23 -9t-9 -23v-640q0 -14 9 -23t23 -9h480q14 0 23 9t9 23zM1536 1344v-1408q0 -26 -19 -45t-45 -19h-1408 q-26 0 -45 19t-19 45v1408q0 26 19 45t45 19h1408q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf182;" horiz-adv-x="1280" d="M1280 480q0 -40 -28 -68t-68 -28q-51 0 -80 43l-227 341h-45v-132l247 -411q9 -15 9 -33q0 -26 -19 -45t-45 -19h-192v-272q0 -46 -33 -79t-79 -33h-160q-46 0 -79 33t-33 79v272h-192q-26 0 -45 19t-19 45q0 18 9 33l247 411v132h-45l-227 -341q-29 -43 -80 -43 q-40 0 -68 28t-28 68q0 29 16 53l256 384q73 107 176 107h384q103 0 176 -107l256 -384q16 -24 16 -53zM864 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65. [...]
+<glyph unicode="&#xf183;" horiz-adv-x="1024" d="M1024 832v-416q0 -40 -28 -68t-68 -28t-68 28t-28 68v352h-64v-912q0 -46 -33 -79t-79 -33t-79 33t-33 79v464h-64v-464q0 -46 -33 -79t-79 -33t-79 33t-33 79v912h-64v-352q0 -40 -28 -68t-68 -28t-68 28t-28 68v416q0 80 56 136t136 56h640q80 0 136 -56t56 -136z M736 1280q0 -93 -65.5 -158.5t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf184;" d="M773 234l350 473q16 22 24.5 59t-6 85t-61.5 79q-40 26 -83 25.5t-73.5 -17.5t-54.5 -45q-36 -40 -96 -40q-59 0 -95 40q-24 28 -54.5 45t-73.5 17.5t-84 -25.5q-46 -31 -60.5 -79t-6 -85t24.5 -59zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf185;" horiz-adv-x="1792" d="M1472 640q0 117 -45.5 223.5t-123 184t-184 123t-223.5 45.5t-223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5t45.5 -223.5t123 -184t184 -123t223.5 -45.5t223.5 45.5t184 123t123 184t45.5 223.5zM1748 363q-4 -15 -20 -20l-292 -96v-306q0 -16 -13 -26q-15 -10 -29 -4 l-292 94l-180 -248q-10 -13 -26 -13t-26 13l-180 248l-292 -94q-14 -6 -29 4q-13 10 -13 26v306l-292 96q-16 5 -20 20q-5 17 4 29l180 248l-180 248q-9 13 -4 29q4 15 20 20l292 96v306q0 16 13 26q15 10 2 [...]
+<glyph unicode="&#xf186;" d="M1262 233q-54 -9 -110 -9q-182 0 -337 90t-245 245t-90 337q0 192 104 357q-201 -60 -328.5 -229t-127.5 -384q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51q144 0 273.5 61.5t220.5 171.5zM1465 318q-94 -203 -283.5 -324.5t-413.5 -121.5q-156 0 -298 61 t-245 164t-164 245t-61 298q0 153 57.5 292.5t156 241.5t235.5 164.5t290 68.5q44 2 61 -39q18 -41 -15 -72q-86 -78 -131.5 -181.5t-45.5 -218.5q0 -148 73 -273t198 -198t273 -73q118 0 228 51q41 18 72 -13q14 -14 17.5 -34t-4.5 -38z" />
+<glyph unicode="&#xf187;" horiz-adv-x="1792" d="M1088 704q0 26 -19 45t-45 19h-256q-26 0 -45 -19t-19 -45t19 -45t45 -19h256q26 0 45 19t19 45zM1664 896v-960q0 -26 -19 -45t-45 -19h-1408q-26 0 -45 19t-19 45v960q0 26 19 45t45 19h1408q26 0 45 -19t19 -45zM1728 1344v-256q0 -26 -19 -45t-45 -19h-1536 q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h1536q26 0 45 -19t19 -45z" />
+<glyph unicode="&#xf188;" horiz-adv-x="1664" d="M1632 576q0 -26 -19 -45t-45 -19h-224q0 -171 -67 -290l208 -209q19 -19 19 -45t-19 -45q-18 -19 -45 -19t-45 19l-198 197q-5 -5 -15 -13t-42 -28.5t-65 -36.5t-82 -29t-97 -13v896h-128v-896q-51 0 -101.5 13.5t-87 33t-66 39t-43.5 32.5l-15 14l-183 -207 q-20 -21 -48 -21q-24 0 -43 16q-19 18 -20.5 44.5t15.5 46.5l202 227q-58 114 -58 274h-224q-26 0 -45 19t-19 45t19 45t45 19h224v294l-173 173q-19 19 -19 45t19 45t45 19t45 -19l173 -173h844l173 173q19 19 45 19t45 [...]
+<glyph unicode="&#xf189;" horiz-adv-x="1920" d="M1917 1016q23 -64 -150 -294q-24 -32 -65 -85q-78 -100 -90 -131q-17 -41 14 -81q17 -21 81 -82h1l1 -1l1 -1l2 -2q141 -131 191 -221q3 -5 6.5 -12.5t7 -26.5t-0.5 -34t-25 -27.5t-59 -12.5l-256 -4q-24 -5 -56 5t-52 22l-20 12q-30 21 -70 64t-68.5 77.5t-61 58 t-56.5 15.5q-3 -1 -8 -3.5t-17 -14.5t-21.5 -29.5t-17 -52t-6.5 -77.5q0 -15 -3.5 -27.5t-7.5 -18.5l-4 -5q-18 -19 -53 -22h-115q-71 -4 -146 16.5t-131.5 53t-103 66t-70.5 57.5l-25 24q-10 10 -27.5 30t-71.5 91 [...]
+<glyph unicode="&#xf18a;" horiz-adv-x="1792" d="M675 252q21 34 11 69t-45 50q-34 14 -73 1t-60 -46q-22 -34 -13 -68.5t43 -50.5t74.5 -2.5t62.5 47.5zM769 373q8 13 3.5 26.5t-17.5 18.5q-14 5 -28.5 -0.5t-21.5 -18.5q-17 -31 13 -45q14 -5 29 0.5t22 18.5zM943 266q-45 -102 -158 -150t-224 -12 q-107 34 -147.5 126.5t6.5 187.5q47 93 151.5 139t210.5 19q111 -29 158.5 -119.5t2.5 -190.5zM1255 426q-9 96 -89 170t-208.5 109t-274.5 21q-223 -23 -369.5 -141.5t-132.5 -264.5q9 -96 89 -170t208.5 -109t274.5 -21q223 23 [...]
+<glyph unicode="&#xf18b;" d="M1133 -34q-171 -94 -368 -94q-196 0 -367 94q138 87 235.5 211t131.5 268q35 -144 132.5 -268t235.5 -211zM638 1394v-485q0 -252 -126.5 -459.5t-330.5 -306.5q-181 215 -181 495q0 187 83.5 349.5t229.5 269.5t325 137zM1536 638q0 -280 -181 -495 q-204 99 -330.5 306.5t-126.5 459.5v485q179 -30 325 -137t229.5 -269.5t83.5 -349.5z" />
+<glyph unicode="&#xf18c;" horiz-adv-x="1408" d="M1402 433q-32 -80 -76 -138t-91 -88.5t-99 -46.5t-101.5 -14.5t-96.5 8.5t-86.5 22t-69.5 27.5t-46 22.5l-17 10q-113 -228 -289.5 -359.5t-384.5 -132.5q-19 0 -32 13t-13 32t13 31.5t32 12.5q173 1 322.5 107.5t251.5 294.5q-36 -14 -72 -23t-83 -13t-91 2.5t-93 28.5 t-92 59t-84.5 100t-74.5 146q114 47 214 57t167.5 -7.5t124.5 -56.5t88.5 -77t56.5 -82q53 131 79 291q-7 -1 -18 -2.5t-46.5 -2.5t-69.5 0.5t-81.5 10t-88.5 23t-84 42.5t-75 65t-54.5 94.5t-28.5 127.5q70  [...]
+<glyph unicode="&#xf18d;" horiz-adv-x="1280" d="M1259 283v-66q0 -85 -57.5 -144.5t-138.5 -59.5h-57l-260 -269v269h-529q-81 0 -138.5 59.5t-57.5 144.5v66h1238zM1259 609v-255h-1238v255h1238zM1259 937v-255h-1238v255h1238zM1259 1077v-67h-1238v67q0 84 57.5 143.5t138.5 59.5h846q81 0 138.5 -59.5t57.5 -143.5z " />
+<glyph unicode="&#xf18e;" d="M1152 640q0 -14 -9 -23l-320 -320q-9 -9 -23 -9q-13 0 -22.5 9.5t-9.5 22.5v192h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v192q0 14 9 23t23 9q12 0 24 -10l319 -319q9 -9 9 -23zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf190;" d="M1152 736v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-192q0 -14 -9 -23t-23 -9q-12 0 -24 10l-319 319q-9 9 -9 23t9 23l320 320q9 9 23 9q13 0 22.5 -9.5t9.5 -22.5v-192h352q13 0 22.5 -9.5t9.5 -22.5zM1312 640q0 148 -73 273t-198 198t-273 73t-273 -73t-198 -198 t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf191;" d="M1024 960v-640q0 -26 -19 -45t-45 -19q-20 0 -37 12l-448 320q-27 19 -27 52t27 52l448 320q17 12 37 12q26 0 45 -19t19 -45zM1280 160v960q0 13 -9.5 22.5t-22.5 9.5h-960q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h960q13 0 22.5 9.5t9.5 22.5z M1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf192;" d="M1024 640q0 -106 -75 -181t-181 -75t-181 75t-75 181t75 181t181 75t181 -75t75 -181zM768 1184q-148 0 -273 -73t-198 -198t-73 -273t73 -273t198 -198t273 -73t273 73t198 198t73 273t-73 273t-198 198t-273 73zM1536 640q0 -209 -103 -385.5t-279.5 -279.5 t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf193;" horiz-adv-x="1664" d="M1023 349l102 -204q-58 -179 -210 -290t-339 -111q-156 0 -288.5 77.5t-210 210t-77.5 288.5q0 181 104.5 330t274.5 211l17 -131q-122 -54 -195 -165.5t-73 -244.5q0 -185 131.5 -316.5t316.5 -131.5q126 0 232.5 65t165 175.5t49.5 236.5zM1571 249l58 -114l-256 -128 q-13 -7 -29 -7q-40 0 -57 35l-239 477h-472q-24 0 -42.5 16.5t-21.5 40.5l-96 779q-2 16 6 42q14 51 57 82.5t97 31.5q66 0 113 -47t47 -113q0 -69 -52 -117.5t-120 -41.5l37 -289h423v-128h-407l16 -128h455 [...]
+<glyph unicode="&#xf194;" d="M1292 898q10 216 -161 222q-231 8 -312 -261q44 19 82 19q85 0 74 -96q-4 -57 -74 -167t-105 -110q-43 0 -82 169q-13 54 -45 255q-30 189 -160 177q-59 -7 -164 -100l-81 -72l-81 -72l52 -67q76 52 87 52q57 0 107 -179q15 -55 45 -164.5t45 -164.5q68 -179 164 -179 q157 0 383 294q220 283 226 444zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf195;" horiz-adv-x="1152" d="M1152 704q0 -191 -94.5 -353t-256.5 -256.5t-353 -94.5h-160q-14 0 -23 9t-9 23v611l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v93l-215 -66q-3 -1 -9 -1q-10 0 -19 6q-13 10 -13 26v128q0 23 23 31l233 71v250q0 14 9 23t23 9h160 q14 0 23 -9t9 -23v-181l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-93l375 116q15 5 28 -5t13 -26v-128q0 -23 -23 -31l-393 -121v-487q188 13 318 151t130 328q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf196;" horiz-adv-x="1408" d="M1152 736v-64q0 -14 -9 -23t-23 -9h-352v-352q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v352h-352q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h352v352q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-352h352q14 0 23 -9t9 -23zM1280 288v832q0 66 -47 113t-113 47h-832 q-66 0 -113 -47t-47 -113v-832q0 -66 47 -113t113 -47h832q66 0 113 47t47 113zM1408 1120v-832q0 -119 -84.5 -203.5t-203.5 -84.5h-832q-119 0 -203.5 84.5t-84.5 203.5v832q0 119 84.5 203.5t203.5 84.5h832q119 0 20 [...]
+<glyph unicode="&#xf197;" horiz-adv-x="2176" d="M620 416q-110 -64 -268 -64h-128v64h-64q-13 0 -22.5 23.5t-9.5 56.5q0 24 7 49q-58 2 -96.5 10.5t-38.5 20.5t38.5 20.5t96.5 10.5q-7 25 -7 49q0 33 9.5 56.5t22.5 23.5h64v64h128q158 0 268 -64h1113q42 -7 106.5 -18t80.5 -14q89 -15 150 -40.5t83.5 -47.5t22.5 -40 t-22.5 -40t-83.5 -47.5t-150 -40.5q-16 -3 -80.5 -14t-106.5 -18h-1113zM1739 668q53 -36 53 -92t-53 -92l81 -30q68 48 68 122t-68 122zM625 400h1015q-217 -38 -456 -80q-57 0 -113 -24t-83 -48l-28 -24l-2 [...]
+<glyph unicode="&#xf198;" horiz-adv-x="1664" d="M1519 760q62 0 103.5 -40.5t41.5 -101.5q0 -97 -93 -130l-172 -59l56 -167q7 -21 7 -47q0 -59 -42 -102t-101 -43q-47 0 -85.5 27t-53.5 72l-55 165l-310 -106l55 -164q8 -24 8 -47q0 -59 -42 -102t-102 -43q-47 0 -85 27t-53 72l-55 163l-153 -53q-29 -9 -50 -9 q-61 0 -101.5 40t-40.5 101q0 47 27.5 85t71.5 53l156 53l-105 313l-156 -54q-26 -8 -48 -8q-60 0 -101 40.5t-41 100.5q0 47 27.5 85t71.5 53l157 53l-53 159q-8 24 -8 47q0 60 42 102.5t102 42.5q47 0 85 -27t53 - [...]
+<glyph unicode="&#xf199;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM1280 352v436q-31 -35 -64 -55q-34 -22 -132.5 -85t-151.5 -99q-98 -69 -164 -69v0v0q-66 0 -164 69 q-46 32 -141.5 92.5t-142.5 92.5q-12 8 -33 27t-31 27v-436q0 -40 28 -68t68 -28h832q40 0 68 28t28 68zM1280 925q0 41 -27.5 70t-68.5 29h-832q-40 0 -68 -28t-28 -68q0 -37 30.5 -76.5t67.5 -64.5q47 -32 137.5 -89t129.5 -83q3 -2 [...]
+<glyph unicode="&#xf19a;" horiz-adv-x="1792" d="M127 640q0 163 67 313l367 -1005q-196 95 -315 281t-119 411zM1415 679q0 -19 -2.5 -38.5t-10 -49.5t-11.5 -44t-17.5 -59t-17.5 -58l-76 -256l-278 826q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-75 1 -202 10q-12 1 -20.5 -5t-11.5 -15t-1.5 -18.5t9 -16.5 t19.5 -8l80 -8l120 -328l-168 -504l-280 832q46 3 88 8q19 2 26 18.5t-2.5 31t-28.5 13.5l-205 -10q-7 0 -23 0.5t-26 0.5q105 160 274.5 253.5t367.5 93.5q147 0 280.5 -53t238.5 -149h-10q-55 0 -92 -40.5 [...]
+<glyph unicode="&#xf19b;" horiz-adv-x="1792" d="M1086 1536v-1536l-272 -128q-228 20 -414 102t-293 208.5t-107 272.5q0 140 100.5 263.5t275 205.5t391.5 108v-172q-217 -38 -356.5 -150t-139.5 -255q0 -152 154.5 -267t388.5 -145v1360zM1755 954l37 -390l-525 114l147 83q-119 70 -280 99v172q277 -33 481 -157z" />
+<glyph unicode="&#xf19c;" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
+<glyph unicode="&#xf19d;" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
+<glyph unicode="&#xf19e;" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
+<glyph unicode="&#xf1a0;" d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5 t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
+<glyph unicode="&#xf1a1;" horiz-adv-x="1792" d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26 t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q- [...]
+<glyph unicode="&#xf1a2;" d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54 q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42 [...]
+<glyph unicode="&#xf1a3;" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385 [...]
+<glyph unicode="&#xf1a4;" horiz-adv-x="1920" d="M1062 824v118q0 42 -30 72t-72 30t-72 -30t-30 -72v-612q0 -175 -126 -299t-303 -124q-178 0 -303.5 125.5t-125.5 303.5v266h328v-262q0 -43 30 -72.5t72 -29.5t72 29.5t30 72.5v620q0 171 126.5 292t301.5 121q176 0 302 -122t126 -294v-136l-195 -58zM1592 602h328 v-266q0 -178 -125.5 -303.5t-303.5 -125.5q-177 0 -303 124.5t-126 300.5v268l131 -61l195 58v-270q0 -42 30 -71.5t72 -29.5t72 29.5t30 71.5v275z" />
+<glyph unicode="&#xf1a5;" d="M1472 160v480h-704v704h-480q-93 0 -158.5 -65.5t-65.5 -158.5v-480h704v-704h480q93 0 158.5 65.5t65.5 158.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5 t84.5 -203.5z" />
+<glyph unicode="&#xf1a6;" horiz-adv-x="2048" d="M328 1254h204v-983h-532v697h328v286zM328 435v369h-123v-369h123zM614 968v-697h205v697h-205zM614 1254v-204h205v204h-205zM901 968h533v-942h-533v163h328v82h-328v697zM1229 435v369h-123v-369h123zM1516 968h532v-942h-532v163h327v82h-327v697zM1843 435v369h-123 v-369h123z" />
+<glyph unicode="&#xf1a7;" d="M1046 516q0 -64 -38 -109t-91 -45q-43 0 -70 15v277q28 17 70 17q53 0 91 -45.5t38 -109.5zM703 944q0 -64 -38 -109.5t-91 -45.5q-43 0 -70 15v277q28 17 70 17q53 0 91 -45t38 -109zM1265 513q0 134 -88 229t-213 95q-20 0 -39 -3q-23 -78 -78 -136q-87 -95 -211 -101 v-636l211 41v206q51 -19 117 -19q125 0 213 95t88 229zM922 940q0 134 -88.5 229t-213.5 95q-74 0 -141 -36h-186v-840l211 41v206q55 -19 116 -19q125 0 213.5 95t88.5 229zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h- [...]
+<glyph unicode="&#xf1a8;" horiz-adv-x="2038" d="M1222 607q75 3 143.5 -20.5t118 -58.5t101 -94.5t84 -108t75.5 -120.5q33 -56 78.5 -109t75.5 -80.5t99 -88.5q-48 -30 -108.5 -57.5t-138.5 -59t-114 -47.5q-44 37 -74 115t-43.5 164.5t-33 180.5t-42.5 168.5t-72.5 123t-122.5 48.5l-10 -2l-6 -4q4 -5 13 -14 q6 -5 28 -23.5t25.5 -22t19 -18t18 -20.5t11.5 -21t10.5 -27.5t4.5 -31t4 -40.5l1 -33q1 -26 -2.5 -57.5t-7.5 -52t-12.5 -58.5t-11.5 -53q-35 1 -101 -9.5t-98 -10.5q-39 0 -72 10q-2 16 -2 47q0 74 3 96q2 13 31.5  [...]
+<glyph unicode="&#xf1a9;" d="M1167 -50q-5 19 -24 5q-30 -22 -87 -39t-131 -17q-129 0 -193 49q-5 4 -13 4q-11 0 -26 -12q-7 -6 -7.5 -16t7.5 -20q34 -32 87.5 -46t102.5 -12.5t99 4.5q41 4 84.5 20.5t65 30t28.5 20.5q12 12 7 29zM1128 65q-19 47 -39 61q-23 15 -76 15q-47 0 -71 -10 q-29 -12 -78 -56q-26 -24 -12 -44q9 -8 17.5 -4.5t31.5 23.5q3 2 10.5 8.5t10.5 8.5t10 7t11.5 7t12.5 5t15 4.5t16.5 2.5t20.5 1q27 0 44.5 -7.5t23 -14.5t13.5 -22q10 -17 12.5 -20t12.5 1q23 12 14 34zM1483 346q0 22 -5 44.5t-16.5 45t-34 [...]
+<glyph unicode="&#xf1aa;" d="M1070 463l-160 -160l-151 -152l-30 -30q-65 -64 -151.5 -87t-171.5 -2q-16 -70 -72 -115t-129 -45q-85 0 -145 60.5t-60 145.5q0 72 44.5 128t113.5 72q-22 86 1 173t88 152l12 12l151 -152l-11 -11q-37 -37 -37 -89t37 -90q37 -37 89 -37t89 37l30 30l151 152l161 160z M729 1145l12 -12l-152 -152l-12 12q-37 37 -89 37t-89 -37t-37 -89.5t37 -89.5l29 -29l152 -152l160 -160l-151 -152l-161 160l-151 152l-30 30q-68 67 -90 159.5t5 179.5q-70 15 -115 71t-45 129q0 85 60 145.5t145 60.5q76 0 1 [...]
+<glyph unicode="&#xf1ab;" d="M654 458q-1 -3 -12.5 0.5t-31.5 11.5l-20 9q-44 20 -87 49q-7 5 -41 31.5t-38 28.5q-67 -103 -134 -181q-81 -95 -105 -110q-4 -2 -19.5 -4t-18.5 0q6 4 82 92q21 24 85.5 115t78.5 118q17 30 51 98.5t36 77.5q-8 1 -110 -33q-8 -2 -27.5 -7.5t-34.5 -9.5t-17 -5 q-2 -2 -2 -10.5t-1 -9.5q-5 -10 -31 -15q-23 -7 -47 0q-18 4 -28 21q-4 6 -5 23q6 2 24.5 5t29.5 6q58 16 105 32q100 35 102 35q10 2 43 19.5t44 21.5q9 3 21.5 8t14.5 5.5t6 -0.5q2 -12 -1 -33q0 -2 -12.5 -27t-26.5 -53.5t-17 -33.5q [...]
+<glyph unicode="&#xf1ac;" horiz-adv-x="1792" d="M288 1152q66 0 113 -47t47 -113v-1088q0 -66 -47 -113t-113 -47h-128q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h128zM1664 989q58 -34 93 -93t35 -128v-768q0 -106 -75 -181t-181 -75h-864q-66 0 -113 47t-47 113v1536q0 40 28 68t68 28h672q40 0 88 -20t76 -48 l152 -152q28 -28 48 -76t20 -88v-163zM928 0v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 -14 9 -23t23 -9h128q14 0 23 9t9 23zM928 256v128q0 14 -9 23t-23 9h-128q-14 0 -23 -9t-9 -23v-128q0 - [...]
+<glyph unicode="&#xf1ad;" d="M1344 1536q26 0 45 -19t19 -45v-1664q0 -26 -19 -45t-45 -19h-1280q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h1280zM512 1248v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 992v-64q0 -14 9 -23t23 -9h64q14 0 23 9 t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 736v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM512 480v-64q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v64q0 14 -9 23t-23 9h-6 [...]
+<glyph unicode="&#xf1ae;" horiz-adv-x="1280" d="M1188 988l-292 -292v-824q0 -46 -33 -79t-79 -33t-79 33t-33 79v384h-64v-384q0 -46 -33 -79t-79 -33t-79 33t-33 79v824l-292 292q-28 28 -28 68t28 68t68 28t68 -28l228 -228h368l228 228q28 28 68 28t68 -28t28 -68t-28 -68zM864 1152q0 -93 -65.5 -158.5 t-158.5 -65.5t-158.5 65.5t-65.5 158.5t65.5 158.5t158.5 65.5t158.5 -65.5t65.5 -158.5z" />
+<glyph unicode="&#xf1b0;" horiz-adv-x="1664" d="M780 1064q0 -60 -19 -113.5t-63 -92.5t-105 -39q-76 0 -138 57.5t-92 135.5t-30 151q0 60 19 113.5t63 92.5t105 39q77 0 138.5 -57.5t91.5 -135t30 -151.5zM438 581q0 -80 -42 -139t-119 -59q-76 0 -141.5 55.5t-100.5 133.5t-35 152q0 80 42 139.5t119 59.5 q76 0 141.5 -55.5t100.5 -134t35 -152.5zM832 608q118 0 255 -97.5t229 -237t92 -254.5q0 -46 -17 -76.5t-48.5 -45t-64.5 -20t-76 -5.5q-68 0 -187.5 45t-182.5 45q-66 0 -192.5 -44.5t-200.5 -44.5q-183 0 -183 146q0 [...]
+<glyph unicode="&#xf1b1;" horiz-adv-x="768" d="M704 1008q0 -145 -57 -243.5t-152 -135.5l45 -821q2 -26 -16 -45t-44 -19h-192q-26 0 -44 19t-16 45l45 821q-95 37 -152 135.5t-57 243.5q0 128 42.5 249.5t117.5 200t160 78.5t160 -78.5t117.5 -200t42.5 -249.5z" />
+<glyph unicode="&#xf1b2;" horiz-adv-x="1792" d="M896 -93l640 349v636l-640 -233v-752zM832 772l698 254l-698 254l-698 -254zM1664 1024v-768q0 -35 -18 -65t-49 -47l-704 -384q-28 -16 -61 -16t-61 16l-704 384q-31 17 -49 47t-18 65v768q0 40 23 73t61 47l704 256q22 8 44 8t44 -8l704 -256q38 -14 61 -47t23 -73z " />
+<glyph unicode="&#xf1b3;" horiz-adv-x="2304" d="M640 -96l384 192v314l-384 -164v-342zM576 358l404 173l-404 173l-404 -173zM1664 -96l384 192v314l-384 -164v-342zM1600 358l404 173l-404 173l-404 -173zM1152 651l384 165v266l-384 -164v-267zM1088 1030l441 189l-441 189l-441 -189zM2176 512v-416q0 -36 -19 -67 t-52 -47l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-5 2 -7 4q-2 -2 -7 -4l-448 -224q-25 -14 -57 -14t-57 14l-448 224q-33 16 -52 47t-19 67v416q0 38 21.5 70t56.5 48l434 186v400q0 38 21.5 70t56.5 48l [...]
+<glyph unicode="&#xf1b4;" horiz-adv-x="2048" d="M1848 1197h-511v-124h511v124zM1596 771q-90 0 -146 -52.5t-62 -142.5h408q-18 195 -200 195zM1612 186q63 0 122 32t76 87h221q-100 -307 -427 -307q-214 0 -340.5 132t-126.5 347q0 208 130.5 345.5t336.5 137.5q138 0 240.5 -68t153 -179t50.5 -248q0 -17 -2 -47h-658 q0 -111 57.5 -171.5t166.5 -60.5zM277 236h296q205 0 205 167q0 180 -199 180h-302v-347zM277 773h281q78 0 123.5 36.5t45.5 113.5q0 144 -190 144h-260v-294zM0 1282h594q87 0 155 -14t126.5 -47.5t90 -96 [...]
+<glyph unicode="&#xf1b5;" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM499 1041h-371v-787h382q117 0 197 57.5t80 170.5q0 158 -143 200q107 52 107 164q0 57 -19.5 96.5 t-56.5 60.5t-79 29.5t-97 8.5zM477 723h-176v184h163q119 0 119 -90q0 -94 -106 -94zM486 388h-185v217h189q124 0 124 -113q0 -104 -128 -104zM1136 356q-68 0 -104 38t-36 107h411q1 10 1 30q0 132 -74.5 220.5t-203.5 88.5q-128 0 - [...]
+<glyph unicode="&#xf1b6;" horiz-adv-x="1792" d="M1582 954q0 -101 -71.5 -172.5t-172.5 -71.5t-172.5 71.5t-71.5 172.5t71.5 172.5t172.5 71.5t172.5 -71.5t71.5 -172.5zM812 212q0 104 -73 177t-177 73q-27 0 -54 -6l104 -42q77 -31 109.5 -106.5t1.5 -151.5q-31 -77 -107 -109t-152 -1q-21 8 -62 24.5t-61 24.5 q32 -60 91 -96.5t130 -36.5q104 0 177 73t73 177zM1642 953q0 126 -89.5 215.5t-215.5 89.5q-127 0 -216.5 -89.5t-89.5 -215.5q0 -127 89.5 -216t216.5 -89q126 0 215.5 89t89.5 216zM1792 953q0 -189 -133.5 -32 [...]
+<glyph unicode="&#xf1b7;" d="M1242 889q0 80 -57 136.5t-137 56.5t-136.5 -57t-56.5 -136q0 -80 56.5 -136.5t136.5 -56.5t137 56.5t57 136.5zM632 301q0 -83 -58 -140.5t-140 -57.5q-56 0 -103 29t-72 77q52 -20 98 -40q60 -24 120 1.5t85 86.5q24 60 -1.5 120t-86.5 84l-82 33q22 5 42 5 q82 0 140 -57.5t58 -140.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v153l172 -69q20 -92 93.5 -152t168.5 -60q104 0 181 70t87 173l345 252q150 0 255.5 105.5t105.5 254.5q0 150 -105.5 2 [...]
+<glyph unicode="&#xf1b8;" horiz-adv-x="1792" d="M836 367l-15 -368l-2 -22l-420 29q-36 3 -67 31.5t-47 65.5q-11 27 -14.5 55t4 65t12 55t21.5 64t19 53q78 -12 509 -28zM449 953l180 -379l-147 92q-63 -72 -111.5 -144.5t-72.5 -125t-39.5 -94.5t-18.5 -63l-4 -21l-190 357q-17 26 -18 56t6 47l8 18q35 63 114 188 l-140 86zM1680 436l-188 -359q-12 -29 -36.5 -46.5t-43.5 -20.5l-18 -4q-71 -7 -219 -12l8 -164l-230 367l211 362l7 -173q170 -16 283 -5t170 33zM895 1360q-47 -63 -265 -435l-317 187l-19 12l225 356q20 31 6 [...]
+<glyph unicode="&#xf1b9;" horiz-adv-x="2048" d="M480 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM516 768h1016l-89 357q-2 8 -14 17.5t-21 9.5h-768q-9 0 -21 -9.5t-14 -17.5zM1888 448q0 66 -47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47t113 47t47 113zM2048 544v-384 q0 -14 -9 -23t-23 -9h-96v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-1024v-128q0 -80 -56 -136t-136 -56t-136 56t-56 136v128h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94  [...]
+<glyph unicode="&#xf1ba;" horiz-adv-x="2048" d="M1824 640q93 0 158.5 -65.5t65.5 -158.5v-384q0 -14 -9 -23t-23 -9h-96v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-1024v-64q0 -80 -56 -136t-136 -56t-136 56t-56 136v64h-96q-14 0 -23 9t-9 23v384q0 93 65.5 158.5t158.5 65.5h28l105 419q23 94 104 157.5 t179 63.5h128v224q0 14 9 23t23 9h448q14 0 23 -9t9 -23v-224h128q98 0 179 -63.5t104 -157.5l105 -419h28zM320 160q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM516 640h1016l-89 [...]
+<glyph unicode="&#xf1bb;" d="M1504 64q0 -26 -19 -45t-45 -19h-462q1 -17 6 -87.5t5 -108.5q0 -25 -18 -42.5t-43 -17.5h-320q-25 0 -43 17.5t-18 42.5q0 38 5 108.5t6 87.5h-462q-26 0 -45 19t-19 45t19 45l402 403h-229q-26 0 -45 19t-19 45t19 45l402 403h-197q-26 0 -45 19t-19 45t19 45l384 384 q19 19 45 19t45 -19l384 -384q19 -19 19 -45t-19 -45t-45 -19h-197l402 -403q19 -19 19 -45t-19 -45t-45 -19h-229l402 -403q19 -19 19 -45z" />
+<glyph unicode="&#xf1bc;" d="M1127 326q0 32 -30 51q-193 115 -447 115q-133 0 -287 -34q-42 -9 -42 -52q0 -20 13.5 -34.5t35.5 -14.5q5 0 37 8q132 27 243 27q226 0 397 -103q19 -11 33 -11q19 0 33 13.5t14 34.5zM1223 541q0 40 -35 61q-237 141 -548 141q-153 0 -303 -42q-48 -13 -48 -64 q0 -25 17.5 -42.5t42.5 -17.5q7 0 37 8q122 33 251 33q279 0 488 -124q24 -13 38 -13q25 0 42.5 17.5t17.5 42.5zM1331 789q0 47 -40 70q-126 73 -293 110.5t-343 37.5q-204 0 -364 -47q-23 -7 -38.5 -25.5t-15.5 -48.5q0 -31 20.5 -52t [...]
+<glyph unicode="&#xf1bd;" horiz-adv-x="1024" d="M1024 1233l-303 -582l24 -31h279v-415h-507l-44 -30l-142 -273l-30 -30h-301v303l303 583l-24 30h-279v415h507l44 30l142 273l30 30h301v-303z" />
+<glyph unicode="&#xf1be;" horiz-adv-x="2304" d="M784 164l16 241l-16 523q-1 10 -7.5 17t-16.5 7q-9 0 -16 -7t-7 -17l-14 -523l14 -241q1 -10 7.5 -16.5t15.5 -6.5q22 0 24 23zM1080 193l11 211l-12 586q0 16 -13 24q-8 5 -16 5t-16 -5q-13 -8 -13 -24l-1 -6l-10 -579q0 -1 11 -236v-1q0 -10 6 -17q9 -11 23 -11 q11 0 20 9q9 7 9 20zM35 533l20 -128l-20 -126q-2 -9 -9 -9t-9 9l-17 126l17 128q2 9 9 9t9 -9zM121 612l26 -207l-26 -203q-2 -9 -10 -9q-9 0 -9 10l-23 202l23 207q0 9 9 9q8 0 10 -9zM401 159zM213 650l25 -245l [...]
+<glyph unicode="&#xf1c0;" d="M768 768q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 0q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127 t443 -43zM768 384q237 0 443 43t325 127v-170q0 -69 -103 -128t-280 -93.5t-385 -34.5t-385 34.5t-280 93.5t-103 128v170q119 -84 325 -127t443 -43zM768 1536q208 0 385 -34.5t280 -93.5t103 -128v-128q0 -69 -103 -128t-280  [...]
+<glyph unicode="&#xf1c1;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M894 465q33 -26 84 -56q59 7 117 7q147 0 177 -49q16 -22 2 -52q0 -1 -1 -2l-2 -2v-1q-6 -38 -71 -38q-48 0 -115 20t-130 53q-221 -24 -392 -83q-153 -262 -242 -262q-15 0 -28 7l-24 12q-1 1 -6 5q-10 10 -6 36q9 40 56 91.5t13 [...]
+<glyph unicode="&#xf1c2;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M233 768v-107h70l164 -661h159l128 485q7 20 10 46q2 16 2 24h4l3 -24q1 -3 3.5 -20t5.5 -26l128 -485h159l164 661h70v107h-300v-107h90l-99 -438q-5 -20 -7 -46l-2 -21h-4l-3 21q-1 5 -4 21t-5 25l-144 545h-114l-144 -545q-2 - [...]
+<glyph unicode="&#xf1c3;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M429 106v-106h281v106h-75l103 161q5 7 10 16.5t7.5 13.5t3.5 4h2q1 -4 5 -10q2 -4 4.5 -7.5t6 -8t6.5 -8.5l107 -161h-76v-106h291v106h-68l-192 273l195 282h67v107h-279v-107h74l-103 -159q-4 -7 -10 -16.5t-9 -13.5l-2 -3h-2q [...]
+<glyph unicode="&#xf1c4;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M416 106v-106h327v106h-93v167h137q76 0 118 15q67 23 106.5 87t39.5 146q0 81 -37 141t-100 87q-48 19 -130 19h-368v-107h92v-555h-92zM769 386h-119v268h120q52 0 83 -18q56 -33 56 -115q0 -89 -62 -120q-31 -15 -78 -15z" />
+<glyph unicode="&#xf1c5;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M1280 320v-320h-1024v192l192 192l128 -128l384 384zM448 512q-80 0 -136 56t-56 136t56 136t136 56t136 -56t56 -136t-56 -136t-136 -56z" />
+<glyph unicode="&#xf1c6;" d="M640 1152v128h-128v-128h128zM768 1024v128h-128v-128h128zM640 896v128h-128v-128h128zM768 768v128h-128v-128h128zM1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400 v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-128v-128h-128v128h-512v-1536h1280zM781 593l107 -349q8 -27 8 -52q0 -83 -72.5 -137.5t-183.5 -54.5t-183.5 54.5t-72.5 137. [...]
+<glyph unicode="&#xf1c7;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M620 686q20 -8 20 -30v-544q0 -22 -20 -30q-8 -2 -12 -2q-12 0 -23 9l-166 167h-131q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h131l166 167q16 15 35 7zM1037 -3q31 0 50 24q129 159 129 363t-129 363q-16 21 -43 24t-47 -14q-21 -1 [...]
+<glyph unicode="&#xf1c8;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M768 768q52 0 90 -38t38 -90v-384q0 -52 -38 -90t-90 -38h-384q-52 0 -90 38t-38 90v384q0 52 38 90t90 38h384zM1260 766q20 -8 20 -30v-576q0 -22 -20 -30q-8 -2 -12 -2q-14 0 -23 9l-265 266v90l265 266q9 9 23 9q4 0 12 -2z" />
+<glyph unicode="&#xf1c9;" d="M1468 1156q28 -28 48 -76t20 -88v-1152q0 -40 -28 -68t-68 -28h-1344q-40 0 -68 28t-28 68v1600q0 40 28 68t68 28h896q40 0 88 -20t76 -48zM1024 1400v-376h376q-10 29 -22 41l-313 313q-12 12 -41 22zM1408 -128v1024h-416q-40 0 -68 28t-28 68v416h-768v-1536h1280z M480 768q8 11 21 12.5t24 -6.5l51 -38q11 -8 12.5 -21t-6.5 -24l-182 -243l182 -243q8 -11 6.5 -24t-12.5 -21l-51 -38q-11 -8 -24 -6.5t-21 12.5l-226 301q-14 19 0 38zM1282 467q14 -19 0 -38l-226 -301q-8 -11 -21 -12.5t-24 6 [...]
+<glyph unicode="&#xf1ca;" d="M1497 709v-198q-101 -23 -198 -23q-65 -136 -165.5 -271t-181.5 -215.5t-128 -106.5q-80 -45 -162 3q-28 17 -60.5 43.5t-85 83.5t-102.5 128.5t-107.5 184t-105.5 244t-91.5 314.5t-70.5 390h283q26 -218 70 -398.5t104.5 -317t121.5 -235.5t140 -195q169 169 287 406 q-142 72 -223 220t-81 333q0 192 104 314.5t284 122.5q178 0 273 -105.5t95 -297.5q0 -159 -58 -286q-7 -1 -19.5 -3t-46 -2t-63 6t-62 25.5t-50.5 51.5q31 103 31 184q0 87 -29 132t-79 45q-53 0 -85 -49.5t-32 -140.5q0 -186 10 [...]
+<glyph unicode="&#xf1cb;" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
+<glyph unicode="&#xf1cc;" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44  [...]
+<glyph unicode="&#xf1cd;" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-2 [...]
+<glyph unicode="&#xf1ce;" horiz-adv-x="1792" d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5 t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
+<glyph unicode="&#xf1d0;" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115 [...]
+<glyph unicode="&#xf1d1;" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241 [...]
+<glyph unicode="&#xf1d2;" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387 [...]
+<glyph unicode="&#xf1d3;" horiz-adv-x="1792" d="M595 22q0 100 -165 100q-158 0 -158 -104q0 -101 172 -101q151 0 151 105zM536 777q0 61 -30 102t-89 41q-124 0 -124 -145q0 -135 124 -135q119 0 119 137zM805 1101v-202q-36 -12 -79 -22q16 -43 16 -84q0 -127 -73 -216.5t-197 -112.5q-40 -8 -59.5 -27t-19.5 -58 q0 -31 22.5 -51.5t58 -32t78.5 -22t86 -25.5t78.5 -37.5t58 -64t22.5 -98.5q0 -304 -363 -304q-69 0 -130 12.5t-116 41t-87.5 82t-32.5 127.5q0 165 182 225v4q-67 41 -67 126q0 109 63 137v4q-72 24 -119.5 10 [...]
+<glyph unicode="&#xf1d4;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
+<glyph unicode="&#xf1d5;" horiz-adv-x="1280" d="M842 964q0 -80 -57 -136.5t-136 -56.5q-60 0 -111 35q-62 -67 -115 -146q-247 -371 -202 -859q1 -22 -12.5 -38.5t-34.5 -18.5h-5q-20 0 -35 13.5t-17 33.5q-14 126 -3.5 247.5t29.5 217t54 186t69 155.5t74 125q61 90 132 165q-16 35 -16 77q0 80 56.5 136.5t136.5 56.5 t136.5 -56.5t56.5 -136.5zM1223 953q0 -158 -78 -292t-212.5 -212t-292.5 -78q-64 0 -131 14q-21 5 -32.5 23.5t-6.5 39.5q5 20 23 31.5t39 7.5q51 -13 108 -13q97 0 186 38t153 102t102 153t38 186t-38 186 [...]
+<glyph unicode="&#xf1d6;" horiz-adv-x="1792" d="M270 730q-8 19 -8 52q0 20 11 49t24 45q-1 22 7.5 53t22.5 43q0 139 92.5 288.5t217.5 209.5q139 66 324 66q133 0 266 -55q49 -21 90 -48t71 -56t55 -68t42 -74t32.5 -84.5t25.5 -89.5t22 -98l1 -5q55 -83 55 -150q0 -14 -9 -40t-9 -38q0 -1 1.5 -3.5t3.5 -5t2 -3.5 q77 -114 120.5 -214.5t43.5 -208.5q0 -43 -19.5 -100t-55.5 -57q-9 0 -19.5 7.5t-19 17.5t-19 26t-16 26.5t-13.5 26t-9 17.5q-1 1 -3 1l-5 -4q-59 -154 -132 -223q20 -20 61.5 -38.5t69 -41.5t35.5 -65q-2 -4 - [...]
+<glyph unicode="&#xf1d7;" horiz-adv-x="2048" d="M580 1075q0 41 -25 66t-66 25q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 66 24.5t25 65.5zM1323 568q0 28 -25.5 50t-65.5 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q40 0 65.5 22t25.5 51zM1087 1075q0 41 -24.5 66t-65.5 25 q-43 0 -76 -25.5t-33 -65.5q0 -39 33 -64.5t76 -25.5q41 0 65.5 24.5t24.5 65.5zM1722 568q0 28 -26 50t-65 22q-27 0 -49.5 -22.5t-22.5 -49.5q0 -28 22.5 -50.5t49.5 -22.5q39 0 65 22t26 51zM1456 965q-31 4 -7 [...]
+<glyph unicode="&#xf1d8;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-453 185l-242 -295q-18 -23 -49 -23q-13 0 -22 4q-19 7 -30.5 23.5t-11.5 36.5v349l864 1059l-1069 -925l-395 162q-37 14 -40 55q-2 40 32 59l1664 960q15 9 32 9q20 0 36 -11z" />
+<glyph unicode="&#xf1d9;" horiz-adv-x="1792" d="M1764 1525q33 -24 27 -64l-256 -1536q-5 -29 -32 -45q-14 -8 -31 -8q-11 0 -24 5l-527 215l-298 -327q-18 -21 -47 -21q-14 0 -23 4q-19 7 -30 23.5t-11 36.5v452l-472 193q-37 14 -40 55q-3 39 32 59l1664 960q35 21 68 -2zM1422 26l221 1323l-1434 -827l336 -137 l863 639l-478 -797z" />
+<glyph unicode="&#xf1da;" d="M1536 640q0 -156 -61 -298t-164 -245t-245 -164t-298 -61q-172 0 -327 72.5t-264 204.5q-7 10 -6.5 22.5t8.5 20.5l137 138q10 9 25 9q16 -2 23 -12q73 -95 179 -147t225 -52q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5 t-163.5 109.5t-198.5 40.5q-98 0 -188 -35.5t-160 -101.5l137 -138q31 -30 14 -69q-17 -40 -59 -40h-448q-26 0 -45 19t-19 45v448q0 42 40 59q39 17 69 -14l130 -129q107 101 244.5 156.5t284.5 55.5q156 0 298 -61t245 -164t164 -245t61 - [...]
+<glyph unicode="&#xf1db;" d="M768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5t-51 248.5t-136.5 204t-204 136.5t-248.5 51zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103 t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf1dc;" horiz-adv-x="1792" d="M1682 -128q-44 0 -132.5 3.5t-133.5 3.5q-44 0 -132 -3.5t-132 -3.5q-24 0 -37 20.5t-13 45.5q0 31 17 46t39 17t51 7t45 15q33 21 33 140l-1 391q0 21 -1 31q-13 4 -50 4h-675q-38 0 -51 -4q-1 -10 -1 -31l-1 -371q0 -142 37 -164q16 -10 48 -13t57 -3.5t45 -15 t20 -45.5q0 -26 -12.5 -48t-36.5 -22q-47 0 -139.5 3.5t-138.5 3.5q-43 0 -128 -3.5t-127 -3.5q-23 0 -35.5 21t-12.5 45q0 30 15.5 45t36 17.5t47.5 7.5t42 15q33 23 33 143l-1 57v813q0 3 0.5 26t0 36.5t-1.5 38.5 [...]
+<glyph unicode="&#xf1dd;" horiz-adv-x="1280" d="M1278 1347v-73q0 -29 -18.5 -61t-42.5 -32q-50 0 -54 -1q-26 -6 -32 -31q-3 -11 -3 -64v-1152q0 -25 -18 -43t-43 -18h-108q-25 0 -43 18t-18 43v1218h-143v-1218q0 -25 -17.5 -43t-43.5 -18h-108q-26 0 -43.5 18t-17.5 43v496q-147 12 -245 59q-126 58 -192 179 q-64 117 -64 259q0 166 88 286q88 118 209 159q111 37 417 37h479q25 0 43 -18t18 -43z" />
+<glyph unicode="&#xf1de;" d="M352 128v-128h-352v128h352zM704 256q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM864 640v-128h-864v128h864zM224 1152v-128h-224v128h224zM1536 128v-128h-736v128h736zM576 1280q26 0 45 -19t19 -45v-256 q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1216 768q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-256q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h256zM1536 640v-128h-224v128h224zM1536 1 [...]
+<glyph unicode="&#xf1e0;" d="M1216 512q133 0 226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5t-226.5 93.5t-93.5 226.5q0 12 2 34l-360 180q-92 -86 -218 -86q-133 0 -226.5 93.5t-93.5 226.5t93.5 226.5t226.5 93.5q126 0 218 -86l360 180q-2 22 -2 34q0 133 93.5 226.5t226.5 93.5 t226.5 -93.5t93.5 -226.5t-93.5 -226.5t-226.5 -93.5q-126 0 -218 86l-360 -180q2 -22 2 -34t-2 -34l360 -180q92 86 218 86z" />
+<glyph unicode="&#xf1e1;" d="M1280 341q0 88 -62.5 151t-150.5 63q-84 0 -145 -58l-241 120q2 16 2 23t-2 23l241 120q61 -58 145 -58q88 0 150.5 63t62.5 151t-62.5 150.5t-150.5 62.5t-151 -62.5t-63 -150.5q0 -7 2 -23l-241 -120q-62 57 -145 57q-88 0 -150.5 -62.5t-62.5 -150.5t62.5 -150.5 t150.5 -62.5q83 0 145 57l241 -120q-2 -16 -2 -23q0 -88 63 -150.5t151 -62.5t150.5 62.5t62.5 150.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960 [...]
+<glyph unicode="&#xf1e2;" horiz-adv-x="1792" d="M571 947q-10 25 -34 35t-49 0q-108 -44 -191 -127t-127 -191q-10 -25 0 -49t35 -34q13 -5 24 -5q42 0 60 40q34 84 98.5 148.5t148.5 98.5q25 11 35 35t0 49zM1513 1303l46 -46l-244 -243l68 -68q19 -19 19 -45.5t-19 -45.5l-64 -64q89 -161 89 -343q0 -143 -55.5 -273.5 t-150 -225t-225 -150t-273.5 -55.5t-273.5 55.5t-225 150t-150 225t-55.5 273.5t55.5 273.5t150 225t225 150t273.5 55.5q182 0 343 -89l64 64q19 19 45.5 19t45.5 -19l68 -68zM1521 1359q-10 -10 -22 -10q- [...]
+<glyph unicode="&#xf1e3;" horiz-adv-x="1792" d="M609 720l287 208l287 -208l-109 -336h-355zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM1515 186q149 203 149 454v3l-102 -89l-240 224l63 323 l134 -12q-150 206 -389 282l53 -124l-287 -159l-287 159l53 124q-239 -76 -389 -282l135 12l62 -323l-240 -224l-102 89v-3q0 -251 149 -454l30 132l326 -40l139 -298l-116 -69q117 -39 240 -39t240 39l-116 69l13 [...]
+<glyph unicode="&#xf1e4;" horiz-adv-x="1792" d="M448 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM256 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM832 224v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23 v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM640 608v-192q0 -14 -9 -23t-23 -9h-192q-14 0 -23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23 -9t9 -23zM66 768q-28 0 -47 19t-19 46v129h514v-129q0 -27 -19 -46t [...]
+<glyph unicode="&#xf1e5;" horiz-adv-x="1792" d="M704 1216v-768q0 -26 -19 -45t-45 -19v-576q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v512l249 873q7 23 31 23h424zM1024 1216v-704h-256v704h256zM1792 320v-512q0 -26 -19 -45t-45 -19h-512q-26 0 -45 19t-19 45v576q-26 0 -45 19t-19 45v768h424q24 0 31 -23z M736 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23zM1408 1504v-224h-352v224q0 14 9 23t23 9h288q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf1e6;" horiz-adv-x="1792" d="M1755 1083q37 -37 37 -90t-37 -91l-401 -400l150 -150l-160 -160q-163 -163 -389.5 -186.5t-411.5 100.5l-362 -362h-181v181l362 362q-124 185 -100.5 411.5t186.5 389.5l160 160l150 -150l400 401q38 37 91 37t90 -37t37 -90.5t-37 -90.5l-400 -401l234 -234l401 400 q38 37 91 37t90 -37z" />
+<glyph unicode="&#xf1e7;" horiz-adv-x="1792" d="M873 796q0 -83 -63.5 -142.5t-152.5 -59.5t-152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59t152.5 -59t63.5 -143zM1375 796q0 -83 -63 -142.5t-153 -59.5q-89 0 -152.5 59.5t-63.5 142.5q0 84 63.5 143t152.5 59q90 0 153 -59t63 -143zM1600 616v667q0 87 -32 123.5 t-111 36.5h-1112q-83 0 -112.5 -34t-29.5 -126v-673q43 -23 88.5 -40t81 -28t81 -18.5t71 -11t70 -4t58.5 -0.5t56.5 2t44.5 2q68 1 95 -27q6 -6 10 -9q26 -25 61 -51q7 91 118 87q5 0 36.5 -1.5t43 -2t45.5 -1 [...]
+<glyph unicode="&#xf1e8;" horiz-adv-x="1792" d="M896 1102v-434h-145v434h145zM1294 1102v-434h-145v434h145zM1294 342l253 254v795h-1194v-1049h326v-217l217 217h398zM1692 1536v-1013l-434 -434h-326l-217 -217h-217v217h-398v1158l109 289h1483z" />
+<glyph unicode="&#xf1e9;" d="M773 217v-127q-1 -292 -6 -305q-12 -32 -51 -40q-54 -9 -181.5 38t-162.5 89q-13 15 -17 36q-1 12 4 26q4 10 34 47t181 216q1 0 60 70q15 19 39.5 24.5t49.5 -3.5q24 -10 37.5 -29t12.5 -42zM624 468q-3 -55 -52 -70l-120 -39q-275 -88 -292 -88q-35 2 -54 36 q-12 25 -17 75q-8 76 1 166.5t30 124.5t56 32q13 0 202 -77q70 -29 115 -47l84 -34q23 -9 35.5 -30.5t11.5 -48.5zM1450 171q-7 -54 -91.5 -161t-135.5 -127q-37 -14 -63 7q-14 10 -184 287l-47 77q-14 21 -11.5 46t19.5 46q35 43 83 26q1 [...]
+<glyph unicode="&#xf1ea;" horiz-adv-x="2048" d="M1024 1024h-384v-384h384v384zM1152 384v-128h-640v128h640zM1152 1152v-640h-640v640h640zM1792 384v-128h-512v128h512zM1792 640v-128h-512v128h512zM1792 896v-128h-512v128h512zM1792 1152v-128h-512v128h512zM256 192v960h-128v-960q0 -26 19 -45t45 -19t45 19 t19 45zM1920 192v1088h-1536v-1088q0 -33 -11 -64h1483q26 0 45 19t19 45zM2048 1408v-1216q0 -80 -56 -136t-136 -56h-1664q-80 0 -136 56t-56 136v1088h256v128h1792z" />
+<glyph unicode="&#xf1eb;" horiz-adv-x="2048" d="M1024 13q-20 0 -93 73.5t-73 93.5q0 32 62.5 54t103.5 22t103.5 -22t62.5 -54q0 -20 -73 -93.5t-93 -73.5zM1294 284q-2 0 -40 25t-101.5 50t-128.5 25t-128.5 -25t-101 -50t-40.5 -25q-18 0 -93.5 75t-75.5 93q0 13 10 23q78 77 196 121t233 44t233 -44t196 -121 q10 -10 10 -23q0 -18 -75.5 -93t-93.5 -75zM1567 556q-11 0 -23 8q-136 105 -252 154.5t-268 49.5q-85 0 -170.5 -22t-149 -53t-113.5 -62t-79 -53t-31 -22q-17 0 -92 75t-75 93q0 12 10 22q132 132 320 205t380 73 [...]
+<glyph unicode="&#xf1ec;" horiz-adv-x="1792" d="M384 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM384 384q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5 t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1152 0q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM768 384q0 53 -37.5 90.5t-90.5 37.5t-90. [...]
+<glyph unicode="&#xf1ed;" d="M1519 890q18 -84 -4 -204q-87 -444 -565 -444h-44q-25 0 -44 -16.5t-24 -42.5l-4 -19l-55 -346l-2 -15q-5 -26 -24.5 -42.5t-44.5 -16.5h-251q-21 0 -33 15t-9 36q9 56 26.5 168t26.5 168t27 167.5t27 167.5q5 37 43 37h131q133 -2 236 21q175 39 287 144q102 95 155 246 q24 70 35 133q1 6 2.5 7.5t3.5 1t6 -3.5q79 -59 98 -162zM1347 1172q0 -107 -46 -236q-80 -233 -302 -315q-113 -40 -252 -42q0 -1 -90 -1l-90 1q-100 0 -118 -96q-2 -8 -85 -530q-1 -10 -12 -10h-295q-22 0 -36.5 16.5t-11.5 3 [...]
+<glyph unicode="&#xf1ee;" horiz-adv-x="1792" d="M441 864q32 0 52 -26q266 -364 362 -774h-446q-127 441 -367 749q-12 16 -3 33.5t29 17.5h373zM1000 507q-49 -199 -125 -393q-79 310 -256 594q40 221 44 449q211 -340 337 -650zM1099 1216q235 -324 384.5 -698.5t184.5 -773.5h-451q-41 665 -553 1472h435zM1792 640 q0 -424 -101 -812q-67 560 -359 1083q-25 301 -106 584q-4 16 5.5 28.5t25.5 12.5h359q21 0 38.5 -13t22.5 -33q115 -409 115 -850z" />
+<glyph unicode="&#xf1f0;" horiz-adv-x="2304" d="M1975 546h-138q14 37 66 179l3 9q4 10 10 26t9 26l12 -55zM531 611l-58 295q-11 54 -75 54h-268l-2 -13q311 -79 403 -336zM710 960l-162 -438l-17 89q-26 70 -85 129.5t-131 88.5l135 -510h175l261 641h-176zM849 318h166l104 642h-166zM1617 944q-69 27 -149 27 q-123 0 -201 -59t-79 -153q-1 -102 145 -174q48 -23 67 -41t19 -39q0 -30 -30 -46t-69 -16q-86 0 -156 33l-22 11l-23 -144q74 -34 185 -34q130 -1 208.5 59t80.5 160q0 106 -140 174q-49 25 -71 42t-22 38q0 22 24 [...]
+<glyph unicode="&#xf1f1;" horiz-adv-x="2304" d="M671 603h-13q-47 0 -47 -32q0 -22 20 -22q17 0 28 15t12 39zM1066 639h62v3q1 4 0.5 6.5t-1 7t-2 8t-4.5 6.5t-7.5 5t-11.5 2q-28 0 -36 -38zM1606 603h-12q-48 0 -48 -32q0 -22 20 -22q17 0 28 15t12 39zM1925 629q0 41 -30 41q-19 0 -31 -20t-12 -51q0 -42 28 -42 q20 0 32.5 20t12.5 52zM480 770h87l-44 -262h-56l32 201l-71 -201h-39l-4 200l-34 -200h-53l44 262h81l2 -163zM733 663q0 -6 -4 -42q-16 -101 -17 -113h-47l1 22q-20 -26 -58 -26q-23 0 -37.5 16t-14.5 42q0 39  [...]
+<glyph unicode="&#xf1f2;" horiz-adv-x="2304" d="M313 759q0 -51 -36 -84q-29 -26 -89 -26h-17v220h17q61 0 89 -27q36 -31 36 -83zM2089 824q0 -52 -64 -52h-19v101h20q63 0 63 -49zM380 759q0 74 -50 120.5t-129 46.5h-95v-333h95q74 0 119 38q60 51 60 128zM410 593h65v333h-65v-333zM730 694q0 40 -20.5 62t-75.5 42 q-29 10 -39.5 19t-10.5 23q0 16 13.5 26.5t34.5 10.5q29 0 53 -27l34 44q-41 37 -98 37q-44 0 -74 -27.5t-30 -67.5q0 -35 18 -55.5t64 -36.5q37 -13 45 -19q19 -12 19 -34q0 -20 -14 -33.5t-36 -13.5q-48 0  [...]
+<glyph unicode="&#xf1f3;" horiz-adv-x="2304" d="M119 854h89l-45 108zM740 328l74 79l-70 79h-163v-49h142v-55h-142v-54h159zM898 406l99 -110v217zM1186 453q0 33 -40 33h-84v-69h83q41 0 41 36zM1475 457q0 29 -42 29h-82v-61h81q43 0 43 32zM1197 923q0 29 -42 29h-82v-60h81q43 0 43 31zM1656 854h89l-44 108z M699 1009v-271h-66v212l-94 -212h-57l-94 212v-212h-132l-25 60h-135l-25 -60h-70l116 271h96l110 -257v257h106l85 -184l77 184h108zM1255 453q0 -20 -5.5 -35t-14 -25t-22.5 -16.5t-26 -10t-31.5 -4.5t-31.5 -1 [...]
+<glyph unicode="&#xf1f4;" horiz-adv-x="2304" d="M745 630q0 -37 -25.5 -61.5t-62.5 -24.5q-29 0 -46.5 16t-17.5 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM1530 779q0 -42 -22 -57t-66 -15l-32 -1l17 107q2 11 13 11h18q22 0 35 -2t25 -12.5t12 -30.5zM1881 630q0 -36 -25.5 -61t-61.5 -25q-29 0 -47 16 t-18 44q0 37 25 62.5t62 25.5q28 0 46.5 -16.5t18.5 -45.5zM513 801q0 59 -38.5 85.5t-100.5 26.5h-160q-19 0 -21 -19l-65 -408q-1 -6 3 -11t10 -5h76q20 0 22 19l18 110q1 8 7 13t15 6.5t17 1.5t19 -1t14 -1q [...]
+<glyph unicode="&#xf1f5;" horiz-adv-x="2304" d="M1597 633q0 -69 -21 -106q-19 -35 -52 -35q-23 0 -41 9v224q29 30 57 30q57 0 57 -122zM2035 669h-110q6 98 56 98q51 0 54 -98zM476 534q0 59 -33 91.5t-101 57.5q-36 13 -52 24t-16 25q0 26 38 26q58 0 124 -33l18 112q-67 32 -149 32q-77 0 -123 -38q-48 -39 -48 -109 q0 -58 32.5 -90.5t99.5 -56.5q39 -14 54.5 -25.5t15.5 -27.5q0 -31 -48 -31q-29 0 -70 12.5t-72 30.5l-18 -113q72 -41 168 -41q81 0 129 37q51 41 51 117zM771 749l19 111h-96v135l-129 -21l-18 -114l-46 - [...]
+<glyph unicode="&#xf1f6;" horiz-adv-x="2048" d="M1558 684q61 -356 298 -556q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5zM1024 -176q16 0 16 16t-16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5zM2026 1424q8 -10 7.5 -23.5t-10.5 -22.5 l-1872 -1622q-10 -8 -23.5 -7t-21.5 11l-84 96q-8 10 -7.5 23.5t10.5 21.5l186 161q-19 32 -19 66q50 42 91 88t85 119.5t74.5 158.5t50 206t19.5 260q0 152 117 282.5t307 158.5q-8 19 -8 39q0 40 28 68t68  [...]
+<glyph unicode="&#xf1f7;" horiz-adv-x="2048" d="M1040 -160q0 16 -16 16q-59 0 -101.5 42.5t-42.5 101.5q0 16 -16 16t-16 -16q0 -73 51.5 -124.5t124.5 -51.5q16 0 16 16zM503 315l877 760q-42 88 -132.5 146.5t-223.5 58.5q-93 0 -169.5 -31.5t-121.5 -80.5t-69 -103t-24 -105q0 -384 -137 -645zM1856 128 q0 -52 -38 -90t-90 -38h-448q0 -106 -75 -181t-181 -75t-180.5 74.5t-75.5 180.5l149 129h757q-166 187 -227 459l111 97q61 -356 298 -556zM1942 1520l84 -96q8 -10 7.5 -23.5t-10.5 -22.5l-1872 -1622q-10 -8 -23.5 -7 [...]
+<glyph unicode="&#xf1f8;" horiz-adv-x="1408" d="M512 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM768 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1024 160v704q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-704 q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM480 1152h448l-48 117q-7 9 -17 11h-317q-10 -2 -17 -11zM1408 1120v-64q0 -14 -9 -23t-23 -9h-96v-948q0 -83 -47 -143.5t-113 -60.5h-832q-66 0 -113 58.5t-47 141.5v [...]
+<glyph unicode="&#xf1f9;" d="M1150 462v-109q0 -50 -36.5 -89t-94 -60.5t-118 -32.5t-117.5 -11q-205 0 -342.5 139t-137.5 346q0 203 136 339t339 136q34 0 75.5 -4.5t93 -18t92.5 -34t69 -56.5t28 -81v-109q0 -16 -16 -16h-118q-16 0 -16 16v70q0 43 -65.5 67.5t-137.5 24.5q-140 0 -228.5 -91.5 t-88.5 -237.5q0 -151 91.5 -249.5t233.5 -98.5q68 0 138 24t70 66v70q0 7 4.5 11.5t10.5 4.5h119q6 0 11 -4.5t5 -11.5zM768 1280q-130 0 -248.5 -51t-204 -136.5t-136.5 -204t-51 -248.5t51 -248.5t136.5 -204t204 -136.5t248.5 - [...]
+<glyph unicode="&#xf1fa;" d="M972 761q0 108 -53.5 169t-147.5 61q-63 0 -124 -30.5t-110 -84.5t-79.5 -137t-30.5 -180q0 -112 53.5 -173t150.5 -61q96 0 176 66.5t122.5 166t42.5 203.5zM1536 640q0 -111 -37 -197t-98.5 -135t-131.5 -74.5t-145 -27.5q-6 0 -15.5 -0.5t-16.5 -0.5q-95 0 -142 53 q-28 33 -33 83q-52 -66 -131.5 -110t-173.5 -44q-161 0 -249.5 95.5t-88.5 269.5q0 157 66 290t179 210.5t246 77.5q87 0 155 -35.5t106 -99.5l2 19l11 56q1 6 5.5 12t9.5 6h118q5 0 13 -11q5 -5 3 -16l-120 -614q-5 -24 -5 -48q0  [...]
+<glyph unicode="&#xf1fb;" horiz-adv-x="1792" d="M1698 1442q94 -94 94 -226.5t-94 -225.5l-225 -223l104 -104q10 -10 10 -23t-10 -23l-210 -210q-10 -10 -23 -10t-23 10l-105 105l-603 -603q-37 -37 -90 -37h-203l-256 -128l-64 64l128 256v203q0 53 37 90l603 603l-105 105q-10 10 -10 23t10 23l210 210q10 10 23 10 t23 -10l104 -104l223 225q93 94 225.5 94t226.5 -94zM512 64l576 576l-192 192l-576 -576v-192h192z" />
+<glyph unicode="&#xf1fc;" horiz-adv-x="1792" d="M1615 1536q70 0 122.5 -46.5t52.5 -116.5q0 -63 -45 -151q-332 -629 -465 -752q-97 -91 -218 -91q-126 0 -216.5 92.5t-90.5 219.5q0 128 92 212l638 579q59 54 130 54zM706 502q39 -76 106.5 -130t150.5 -76l1 -71q4 -213 -129.5 -347t-348.5 -134q-123 0 -218 46.5 t-152.5 127.5t-86.5 183t-29 220q7 -5 41 -30t62 -44.5t59 -36.5t46 -17q41 0 55 37q25 66 57.5 112.5t69.5 76t88 47.5t103 25.5t125 10.5z" />
+<glyph unicode="&#xf1fd;" horiz-adv-x="1792" d="M1792 128v-384h-1792v384q45 0 85 14t59 27.5t47 37.5q30 27 51.5 38t56.5 11t55.5 -11t52.5 -38q29 -25 47 -38t58 -27t86 -14q45 0 85 14.5t58 27t48 37.5q21 19 32.5 27t31 15t43.5 7q35 0 56.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14t85 14t59 27.5t47 37.5 q30 27 51.5 38t56.5 11q34 0 55.5 -11t51.5 -38q28 -24 47 -37.5t59 -27.5t85 -14zM1792 448v-192q-35 0 -55.5 11t-52.5 38q-29 25 -47 38t-58 27t-85 14q-46 0 -86 -14t-58 -27t-47 -38q-22 -19 -33 -27t-3 [...]
+<glyph unicode="&#xf1fe;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1664 1024l256 -896h-1664v576l448 576l576 -576z" />
+<glyph unicode="&#xf200;" horiz-adv-x="1792" d="M768 646l546 -546q-106 -108 -247.5 -168t-298.5 -60q-209 0 -385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103v-762zM955 640h773q0 -157 -60 -298.5t-168 -247.5zM1664 768h-768v768q209 0 385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf201;" horiz-adv-x="2048" d="M2048 0v-128h-2048v1536h128v-1408h1920zM1920 1248v-435q0 -21 -19.5 -29.5t-35.5 7.5l-121 121l-633 -633q-10 -10 -23 -10t-23 10l-233 233l-416 -416l-192 192l585 585q10 10 23 10t23 -10l233 -233l464 464l-121 121q-16 16 -7.5 35.5t29.5 19.5h435q14 0 23 -9 t9 -23z" />
+<glyph unicode="&#xf202;" horiz-adv-x="1792" d="M1292 832q0 -6 10 -41q10 -29 25 -49.5t41 -34t44 -20t55 -16.5q325 -91 325 -332q0 -146 -105.5 -242.5t-254.5 -96.5q-59 0 -111.5 18.5t-91.5 45.5t-77 74.5t-63 87.5t-53.5 103.5t-43.5 103t-39.5 106.5t-35.5 95q-32 81 -61.5 133.5t-73.5 96.5t-104 64t-142 20 q-96 0 -183 -55.5t-138 -144.5t-51 -185q0 -160 106.5 -279.5t263.5 -119.5q177 0 258 95q56 63 83 116l84 -152q-15 -34 -44 -70l1 -1q-131 -152 -388 -152q-147 0 -269.5 79t-190.5 207.5t-68 274.5q0 105 43. [...]
+<glyph unicode="&#xf203;" d="M1432 484q0 173 -234 239q-35 10 -53 16.5t-38 25t-29 46.5q0 2 -2 8.5t-3 12t-1 7.5q0 36 24.5 59.5t60.5 23.5q54 0 71 -15h-1q20 -15 39 -51l93 71q-39 54 -49 64q-33 29 -67.5 39t-85.5 10q-80 0 -142 -57.5t-62 -137.5q0 -7 2 -23q16 -96 64.5 -140t148.5 -73 q29 -8 49 -15.5t45 -21.5t38.5 -34.5t13.5 -46.5v-5q1 -58 -40.5 -93t-100.5 -35q-97 0 -167 144q-23 47 -51.5 121.5t-48 125.5t-54 110.5t-74 95.5t-103.5 60.5t-147 24.5q-101 0 -192 -56t-144 -148t-50 -192v-1q4 -108 50.5 -199t [...]
+<glyph unicode="&#xf204;" horiz-adv-x="2048" d="M1152 640q0 104 -40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5t198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM1920 640q0 104 -40.5 198.5 t-109.5 163.5t-163.5 109.5t-198.5 40.5h-386q119 -90 188.5 -224t69.5 -288t-69.5 -288t-188.5 -224h386q104 0 198.5 40.5t163.5 109.5t109.5 163.5t40.5 198.5zM2048 640q0 -130 -51 -248.5t-136.5 -204t-204 -13 [...]
+<glyph unicode="&#xf205;" horiz-adv-x="2048" d="M0 640q0 130 51 248.5t136.5 204t204 136.5t248.5 51h768q130 0 248.5 -51t204 -136.5t136.5 -204t51 -248.5t-51 -248.5t-136.5 -204t-204 -136.5t-248.5 -51h-768q-130 0 -248.5 51t-204 136.5t-136.5 204t-51 248.5zM1408 128q104 0 198.5 40.5t163.5 109.5 t109.5 163.5t40.5 198.5t-40.5 198.5t-109.5 163.5t-163.5 109.5t-198.5 40.5t-198.5 -40.5t-163.5 -109.5t-109.5 -163.5t-40.5 -198.5t40.5 -198.5t109.5 -163.5t163.5 -109.5t198.5 -40.5z" />
+<glyph unicode="&#xf206;" horiz-adv-x="2304" d="M762 384h-314q-40 0 -57.5 35t6.5 67l188 251q-65 31 -137 31q-132 0 -226 -94t-94 -226t94 -226t226 -94q115 0 203 72.5t111 183.5zM576 512h186q-18 85 -75 148zM1056 512l288 384h-480l-99 -132q105 -103 126 -252h165zM2176 448q0 132 -94 226t-226 94 q-60 0 -121 -24l174 -260q15 -23 10 -49t-27 -40q-15 -11 -36 -11q-35 0 -53 29l-174 260q-93 -95 -93 -225q0 -132 94 -226t226 -94t226 94t94 226zM2304 448q0 -185 -131.5 -316.5t-316.5 -131.5t-316.5 131.5t-131.5 3 [...]
+<glyph unicode="&#xf207;" d="M384 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 320q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1362 716l-72 384q-5 23 -22.5 37.5t-40.5 14.5 h-918q-23 0 -40.5 -14.5t-22.5 -37.5l-72 -384q-5 -30 14 -53t49 -23h1062q30 0 49 23t14 53zM1136 1328q0 20 -14 34t-34 14h-640q-20 0 -34 -14t-14 -34t14 -34t34 -14h640q20 0 34 14t14 34zM1536 603v-603h-128v-128q0 -53 - [...]
+<glyph unicode="&#xf208;" horiz-adv-x="2048" d="M1463 704q0 -35 -25 -60.5t-61 -25.5h-702q-36 0 -61 25.5t-25 60.5t25 60.5t61 25.5h702q36 0 61 -25.5t25 -60.5zM1677 704q0 86 -23 170h-982q-36 0 -61 25t-25 60q0 36 25 61t61 25h908q-88 143 -235 227t-320 84q-177 0 -327.5 -87.5t-238 -237.5t-87.5 -327 q0 -86 23 -170h982q36 0 61 -25t25 -60q0 -36 -25 -61t-61 -25h-908q88 -143 235.5 -227t320.5 -84q132 0 253 51.5t208 139t139 208t52 253.5zM2048 959q0 -35 -25 -60t-61 -25h-131q17 -85 17 -170q0 -167 -65.5  [...]
+<glyph unicode="&#xf209;" horiz-adv-x="1280" d="M953 1158l-114 -328l117 -21q165 451 165 518q0 56 -38 56q-57 0 -130 -225zM654 471l33 -88q37 42 71 67l-33 5.5t-38.5 7t-32.5 8.5zM362 1367q0 -98 159 -521q18 10 49 10q15 0 75 -5l-121 351q-75 220 -123 220q-19 0 -29 -17.5t-10 -37.5zM283 608q0 -36 51.5 -119 t117.5 -153t100 -70q14 0 25.5 13t11.5 27q0 24 -32 102q-13 32 -32 72t-47.5 89t-61.5 81t-62 32q-20 0 -45.5 -27t-25.5 -47zM125 273q0 -41 25 -104q59 -145 183.5 -227t281.5 -82q227 0 382 170q152 169  [...]
+<glyph unicode="&#xf20a;" horiz-adv-x="2048" d="M785 528h207q-14 -158 -98.5 -248.5t-214.5 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-203q-5 64 -35.5 99t-81.5 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t40 -51.5t66 -18q95 0 109 139zM1497 528h206 q-14 -158 -98 -248.5t-214 -90.5q-162 0 -254.5 116t-92.5 316q0 194 93 311.5t233 117.5q148 0 232 -87t97 -247h-204q-4 64 -35 99t-81 35q-57 0 -88.5 -60.5t-31.5 -177.5q0 -48 5 -84t18 -69.5t39.5 -51.5t65 [...]
+<glyph unicode="&#xf20b;" d="M992 912v-496q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v496q0 112 -80 192t-192 80h-272v-1152q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v1344q0 14 9 23t23 9h464q135 0 249 -66.5t180.5 -180.5t66.5 -249zM1376 1376v-880q0 -135 -66.5 -249t-180.5 -180.5 t-249 -66.5h-464q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h160q14 0 23 -9t9 -23v-768h272q112 0 192 80t80 192v880q0 14 9 23t23 9h160q14 0 23 -9t9 -23z" />
+<glyph unicode="&#xf20c;" d="M1311 694v-114q0 -24 -13.5 -38t-37.5 -14h-202q-24 0 -38 14t-14 38v114q0 24 14 38t38 14h202q24 0 37.5 -14t13.5 -38zM821 464v250q0 53 -32.5 85.5t-85.5 32.5h-133q-68 0 -96 -52q-28 52 -96 52h-130q-53 0 -85.5 -32.5t-32.5 -85.5v-250q0 -22 21 -22h55 q22 0 22 22v230q0 24 13.5 38t38.5 14h94q24 0 38 -14t14 -38v-230q0 -22 21 -22h54q22 0 22 22v230q0 24 14 38t38 14h97q24 0 37.5 -14t13.5 -38v-230q0 -22 22 -22h55q21 0 21 22zM1410 560v154q0 53 -33 85.5t-86 32.5h-264q-53 0 -8 [...]
+<glyph unicode="&#xf20d;" d="M915 450h-294l147 551zM1001 128h311l-324 1024h-440l-324 -1024h311l383 314zM1536 1120v-960q0 -118 -85 -203t-203 -85h-960q-118 0 -203 85t-85 203v960q0 118 85 203t203 85h960q118 0 203 -85t85 -203z" />
+<glyph unicode="&#xf20e;" horiz-adv-x="2048" d="M2048 641q0 -21 -13 -36.5t-33 -19.5l-205 -356q3 -9 3 -18q0 -20 -12.5 -35.5t-32.5 -19.5l-193 -337q3 -8 3 -16q0 -23 -16.5 -40t-40.5 -17q-25 0 -41 18h-400q-17 -20 -43 -20t-43 20h-399q-17 -20 -43 -20q-23 0 -40 16.5t-17 40.5q0 8 4 20l-193 335 q-20 4 -32.5 19.5t-12.5 35.5q0 9 3 18l-206 356q-20 5 -32.5 20.5t-12.5 35.5q0 21 13.5 36.5t33.5 19.5l199 344q0 1 -0.5 3t-0.5 3q0 36 34 51l209 363q-4 10 -4 18q0 24 17 40.5t40 16.5q26 0 44 -21h396q16 21 43 21t [...]
+<glyph unicode="&#xf210;" d="M0 856q0 131 91.5 226.5t222.5 95.5h742l352 358v-1470q0 -132 -91.5 -227t-222.5 -95h-780q-131 0 -222.5 95t-91.5 227v790zM1232 102l-176 180v425q0 46 -32 79t-78 33h-484q-46 0 -78 -33t-32 -79v-492q0 -46 32.5 -79.5t77.5 -33.5h770z" />
+<glyph unicode="&#xf211;" d="M934 1386q-317 -121 -556 -362.5t-358 -560.5q-20 89 -20 176q0 208 102.5 384.5t278.5 279t384 102.5q82 0 169 -19zM1203 1267q93 -65 164 -155q-389 -113 -674.5 -400.5t-396.5 -676.5q-93 72 -155 162q112 386 395 671t667 399zM470 -67q115 356 379.5 622t619.5 384 q40 -92 54 -195q-292 -120 -516 -345t-343 -518q-103 14 -194 52zM1536 -125q-193 50 -367 115q-135 -84 -290 -107q109 205 274 370.5t369 275.5q-21 -152 -101 -284q65 -175 115 -370z" />
+<glyph unicode="&#xf212;" horiz-adv-x="2048" d="M1893 1144l155 -1272q-131 0 -257 57q-200 91 -393 91q-226 0 -374 -148q-148 148 -374 148q-193 0 -393 -91q-128 -57 -252 -57h-5l155 1272q224 127 482 127q233 0 387 -106q154 106 387 106q258 0 482 -127zM1398 157q129 0 232 -28.5t260 -93.5l-124 1021 q-171 78 -368 78q-224 0 -374 -141q-150 141 -374 141q-197 0 -368 -78l-124 -1021q105 43 165.5 65t148.5 39.5t178 17.5q202 0 374 -108q172 108 374 108zM1438 191l-55 907q-211 -4 -359 -155q-152 155 -374 155q-17 [...]
+<glyph unicode="&#xf213;" horiz-adv-x="2048" d="M1500 165v733q0 21 -15 36t-35 15h-93q-20 0 -35 -15t-15 -36v-733q0 -20 15 -35t35 -15h93q20 0 35 15t15 35zM1216 165v531q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-531q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM924 165v429q0 20 -15 35t-35 15h-101 q-20 0 -35 -15t-15 -35v-429q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM632 165v362q0 20 -15 35t-35 15h-101q-20 0 -35 -15t-15 -35v-362q0 -20 15 -35t35 -15h101q20 0 35 15t15 35zM2048 311q0 -166 -118 - [...]
+<glyph unicode="&#xf214;" d="M0 1536h1536v-1392l-776 -338l-760 338v1392zM1436 209v926h-1336v-926l661 -294zM1436 1235v201h-1336v-201h1336zM181 937v-115h-37v115h37zM181 789v-115h-37v115h37zM181 641v-115h-37v115h37zM181 493v-115h-37v115h37zM181 345v-115h-37v115h37zM207 202l15 34 l105 -47l-15 -33zM343 142l15 34l105 -46l-15 -34zM478 82l15 34l105 -46l-15 -34zM614 23l15 33l104 -46l-15 -34zM797 10l105 46l15 -33l-105 -47zM932 70l105 46l15 -34l-105 -46zM1068 130l105 46l15 -34l-105 -46zM1203 189l10 [...]
+<glyph unicode="&#xf215;" horiz-adv-x="2048" d="M863 504q0 112 -79.5 191.5t-191.5 79.5t-191 -79.5t-79 -191.5t79 -191t191 -79t191.5 79t79.5 191zM1726 505q0 112 -79 191t-191 79t-191.5 -79t-79.5 -191q0 -113 79.5 -192t191.5 -79t191 79.5t79 191.5zM2048 1314v-1348q0 -44 -31.5 -75.5t-76.5 -31.5h-1832 q-45 0 -76.5 31.5t-31.5 75.5v1348q0 44 31.5 75.5t76.5 31.5h431q44 0 76 -31.5t32 -75.5v-161h754v161q0 44 32 75.5t76 31.5h431q45 0 76.5 -31.5t31.5 -75.5z" />
+<glyph unicode="&#xf216;" horiz-adv-x="2048" d="M1430 953zM1690 749q148 0 253 -98.5t105 -244.5q0 -157 -109 -261.5t-267 -104.5q-85 0 -162 27.5t-138 73.5t-118 106t-109 126.5t-103.5 132.5t-108.5 126t-117 106t-136 73.5t-159 27.5q-154 0 -251.5 -91.5t-97.5 -244.5q0 -157 104 -250t263 -93q100 0 208 37.5 t193 98.5q5 4 21 18.5t30 24t22 9.5q14 0 24.5 -10.5t10.5 -24.5q0 -24 -60 -77q-101 -88 -234.5 -142t-260.5 -54q-133 0 -245.5 58t-180 165t-67.5 241q0 205 141.5 341t347.5 136q120 0 226.5 -43.5t185.5 - [...]
+<glyph unicode="&#xf217;" horiz-adv-x="1664" d="M1216 832q0 26 -19 45t-45 19h-128v128q0 26 -19 45t-45 19t-45 -19t-19 -45v-128h-128q-26 0 -45 -19t-19 -45t19 -45t45 -19h128v-128q0 -26 19 -45t45 -19t45 19t19 45v128h128q26 0 45 19t19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1  [...]
+<glyph unicode="&#xf218;" horiz-adv-x="1664" d="M1280 832q0 26 -19 45t-45 19t-45 -19l-147 -146v293q0 26 -19 45t-45 19t-45 -19t-19 -45v-293l-147 146q-19 19 -45 19t-45 -19t-19 -45t19 -45l256 -256q19 -19 45 -19t45 19l256 256q19 19 19 45zM640 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5 t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1536 0q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1664 1088v-512q0 -24 -16 -42.5t-41 -21.5l-1044 -122q1 [...]
+<glyph unicode="&#xf219;" horiz-adv-x="2048" d="M212 768l623 -665l-300 665h-323zM1024 -4l349 772h-698zM538 896l204 384h-262l-288 -384h346zM1213 103l623 665h-323zM683 896h682l-204 384h-274zM1510 896h346l-288 384h-262zM1651 1382l384 -512q14 -18 13 -41.5t-17 -40.5l-960 -1024q-18 -20 -47 -20t-47 20 l-960 1024q-16 17 -17 40.5t13 41.5l384 512q18 26 51 26h1152q33 0 51 -26z" />
+<glyph unicode="&#xf21a;" horiz-adv-x="2048" d="M1811 -19q19 19 45 19t45 -19l128 -128l-90 -90l-83 83l-83 -83q-18 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-83 83l-83 -83 q-19 -19 -45 -19t-45 19l-83 83l-83 -83q-19 -19 -45 -19t-45 19l-128 128l90 90l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 45 19t45 -19l83 -83l83 83q19 19 4 [...]
+<glyph unicode="&#xf21b;" d="M576 0l96 448l-96 128l-128 64zM832 0l128 640l-128 -64l-96 -128zM992 1010q-2 4 -4 6q-10 8 -96 8q-70 0 -167 -19q-7 -2 -21 -2t-21 2q-97 19 -167 19q-86 0 -96 -8q-2 -2 -4 -6q2 -18 4 -27q2 -3 7.5 -6.5t7.5 -10.5q2 -4 7.5 -20.5t7 -20.5t7.5 -17t8.5 -17t9 -14 t12 -13.5t14 -9.5t17.5 -8t20.5 -4t24.5 -2q36 0 59 12.5t32.5 30t14.5 34.5t11.5 29.5t17.5 12.5h12q11 0 17.5 -12.5t11.5 -29.5t14.5 -34.5t32.5 -30t59 -12.5q13 0 24.5 2t20.5 4t17.5 8t14 9.5t12 13.5t9 14t8.5 17t7.5 17t7 [...]
+<glyph unicode="&#xf21c;" horiz-adv-x="2304" d="M2301 500q12 -103 -22 -198.5t-99 -163.5t-158.5 -106t-196.5 -31q-161 11 -279.5 125t-134.5 274q-12 111 27.5 210.5t118.5 170.5l-71 107q-96 -80 -151 -194t-55 -244q0 -27 -18.5 -46.5t-45.5 -19.5h-256h-69q-23 -164 -149 -274t-294 -110q-185 0 -316.5 131.5 t-131.5 316.5t131.5 316.5t316.5 131.5q76 0 152 -27l24 45q-123 110 -304 110h-64q-26 0 -45 19t-19 45t19 45t45 19h128q78 0 145 -13.5t116.5 -38.5t71.5 -39.5t51 -36.5h512h115l-85 128h-222q-30 0 -49 22.5 [...]
+<glyph unicode="&#xf21d;" d="M1408 0q0 -63 -61.5 -113.5t-164 -81t-225 -46t-253.5 -15.5t-253.5 15.5t-225 46t-164 81t-61.5 113.5q0 49 33 88.5t91 66.5t118 44.5t131 29.5q26 5 48 -10.5t26 -41.5q5 -26 -10.5 -48t-41.5 -26q-58 -10 -106 -23.5t-76.5 -25.5t-48.5 -23.5t-27.5 -19.5t-8.5 -12 q3 -11 27 -26.5t73 -33t114 -32.5t160.5 -25t201.5 -10t201.5 10t160.5 25t114 33t73 33.5t27 27.5q-1 4 -8.5 11t-27.5 19t-48.5 23.5t-76.5 25t-106 23.5q-26 4 -41.5 26t-10.5 48q4 26 26 41.5t48 10.5q71 -12 131 -29.5t118 - [...]
+<glyph unicode="&#xf21e;" horiz-adv-x="1792" d="M1280 512h305q-5 -6 -10 -10.5t-9 -7.5l-3 -4l-623 -600q-18 -18 -44 -18t-44 18l-624 602q-5 2 -21 20h369q22 0 39.5 13.5t22.5 34.5l70 281l190 -667q6 -20 23 -33t39 -13q21 0 38 13t23 33l146 485l56 -112q18 -35 57 -35zM1792 940q0 -145 -103 -300h-369l-111 221 q-8 17 -25.5 27t-36.5 8q-45 -5 -56 -46l-129 -430l-196 686q-6 20 -23.5 33t-39.5 13t-39 -13.5t-22 -34.5l-116 -464h-423q-103 155 -103 300q0 220 127 344t351 124q62 0 126.5 -21.5t120 -58t95.5 -68.5t [...]
+<glyph unicode="&#xf221;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292 q11 134 80.5 249t182 188t245.5 88q170 19 319 -54t236 -212t87 -306zM128 960q0 -185 131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5z" />
+<glyph unicode="&#xf222;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-382 -383q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5 q203 0 359 -126l382 382h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 131.5t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf223;" horiz-adv-x="1280" d="M830 1220q145 -72 233.5 -210.5t88.5 -305.5q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5 t-147.5 384.5q0 167 88.5 305.5t233.5 210.5q-165 96 -228 273q-6 16 3.5 29.5t26.5 13.5h69q21 0 29 -20q44 -106 140 -171t214 -65t214 65t140 171q8 20 37 20h61q17 0 26.5 -13.5t3.5 -29.5q-63 -177 -228 -2 [...]
+<glyph unicode="&#xf224;" d="M1024 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-149 16 -270.5 103t-186.5 223.5t-53 291.5q16 204 160 353.5t347 172.5q118 14 228 -19t198 -103l255 254h-134q-14 0 -23 9t-9 23v64zM576 256q185 0 316.5 13 [...]
+<glyph unicode="&#xf225;" horiz-adv-x="1792" d="M1280 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q126 -158 126 -359q0 -221 -147.5 -384.5t-364.5 -187.5v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64 q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-217 24 -364.5 187.5t-147.5 384.5q0 201 126 359l-52 53l-101 -111q-9 -10 -22 -10.5t-23 7.5l-48 44q-10 8 -10.5 21.5t8.5 23.5l105 115l [...]
+<glyph unicode="&#xf226;" horiz-adv-x="1792" d="M1790 1007q12 -155 -52.5 -292t-186 -224t-271.5 -103v-260h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-512v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23 t23 9h224v260q-150 16 -271.5 103t-186 224t-52.5 292q17 206 164.5 356.5t352.5 169.5q206 21 377 -94q171 115 377 94q205 -19 352.5 -169.5t164.5 -356.5zM896 647q128 131 128 313t-128 313q-128 -131 -12 [...]
+<glyph unicode="&#xf227;" horiz-adv-x="1920" d="M1536 1120q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-31 -182 -166 -312t-318 -156q-210 -29 -384.5 80t-241.5 300q-117 6 -221 57.5t-177.5 133t-113.5 192.5t-32 230 q9 135 78 252t182 191.5t248 89.5q118 14 227.5 -19t198.5 -103l255 254h-134q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q59 -7 [...]
+<glyph unicode="&#xf228;" horiz-adv-x="2048" d="M1664 1504q0 14 9 23t23 9h288q26 0 45 -19t19 -45v-288q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v134l-254 -255q76 -95 107.5 -214t9.5 -247q-32 -180 -164.5 -310t-313.5 -157q-223 -34 -409 90q-117 -78 -256 -93v-132h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23 t-23 -9h-96v-96q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v96h-96q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96v132q-155 17 -279.5 109.5t-187 237.5t-39.5 307q25 187 159.5 322.5t320.5 164.5q224 34 410 -90q1 [...]
+<glyph unicode="&#xf229;" d="M1472 1408q26 0 45 -19t19 -45v-416q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v262l-213 -214l140 -140q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-140 141l-78 -79q126 -156 126 -359q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5 t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123t223.5 45.5q203 0 359 -126l78 78l-172 172q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l172 -172l213 213h-261q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h416zM576 0q185 0 316.5 [...]
+<glyph unicode="&#xf22a;" horiz-adv-x="1280" d="M640 892q217 -24 364.5 -187.5t147.5 -384.5q0 -167 -87 -306t-236 -212t-319 -54q-133 15 -245.5 88t-182 188t-80.5 249q-12 155 52.5 292t186 224t271.5 103v132h-160q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h160v165l-92 -92q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22 t9 23l202 201q19 19 45 19t45 -19l202 -201q9 -10 9 -23t-9 -22l-46 -46q-9 -9 -22 -9t-23 9l-92 92v-165h160q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-160v-132zM576 -128q185 0 316.5 131.5t131.5 316.5t [...]
+<glyph unicode="&#xf22b;" horiz-adv-x="2048" d="M1901 621q19 -19 19 -45t-19 -45l-294 -294q-9 -10 -22.5 -10t-22.5 10l-45 45q-10 9 -10 22.5t10 22.5l185 185h-294v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-132q-24 -217 -187.5 -364.5t-384.5 -147.5q-167 0 -306 87t-212 236t-54 319q15 133 88 245.5 t188 182t249 80.5q155 12 292 -52.5t224 -186t103 -271.5h132v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224h294l-185 185q-10 9 -10 22.5t10 22.5l45 45q9 10 22.5 10t22.5 -10zM576 128q185 0 316.5 131. [...]
+<glyph unicode="&#xf22c;" horiz-adv-x="1280" d="M1152 960q0 -221 -147.5 -384.5t-364.5 -187.5v-612q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v612q-217 24 -364.5 187.5t-147.5 384.5q0 117 45.5 223.5t123 184t184 123t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5zM576 512q185 0 316.5 131.5 t131.5 316.5t-131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5z" />
+<glyph unicode="&#xf22d;" horiz-adv-x="1280" d="M1024 576q0 185 -131.5 316.5t-316.5 131.5t-316.5 -131.5t-131.5 -316.5t131.5 -316.5t316.5 -131.5t316.5 131.5t131.5 316.5zM1152 576q0 -117 -45.5 -223.5t-123 -184t-184 -123t-223.5 -45.5t-223.5 45.5t-184 123t-123 184t-45.5 223.5t45.5 223.5t123 184t184 123 t223.5 45.5t223.5 -45.5t184 -123t123 -184t45.5 -223.5z" />
+<glyph unicode="&#xf22e;" horiz-adv-x="1792" />
+<glyph unicode="&#xf22f;" horiz-adv-x="1792" />
+<glyph unicode="&#xf230;" d="M1451 1408q35 0 60 -25t25 -60v-1366q0 -35 -25 -60t-60 -25h-391v595h199l30 232h-229v148q0 56 23.5 84t91.5 28l122 1v207q-63 9 -178 9q-136 0 -217.5 -80t-81.5 -226v-171h-200v-232h200v-595h-735q-35 0 -60 25t-25 60v1366q0 35 25 60t60 25h1366z" />
+<glyph unicode="&#xf231;" horiz-adv-x="1280" d="M0 939q0 108 37.5 203.5t103.5 166.5t152 123t185 78t202 26q158 0 294 -66.5t221 -193.5t85 -287q0 -96 -19 -188t-60 -177t-100 -149.5t-145 -103t-189 -38.5q-68 0 -135 32t-96 88q-10 -39 -28 -112.5t-23.5 -95t-20.5 -71t-26 -71t-32 -62.5t-46 -77.5t-62 -86.5 l-14 -5l-9 10q-15 157 -15 188q0 92 21.5 206.5t66.5 287.5t52 203q-32 65 -32 169q0 83 52 156t132 73q61 0 95 -40.5t34 -102.5q0 -66 -44 -191t-44 -187q0 -63 45 -104.5t109 -41.5q55 0 102 25t78.5 68t56 9 [...]
+<glyph unicode="&#xf232;" d="M985 562q13 0 97.5 -44t89.5 -53q2 -5 2 -15q0 -33 -17 -76q-16 -39 -71 -65.5t-102 -26.5q-57 0 -190 62q-98 45 -170 118t-148 185q-72 107 -71 194v8q3 91 74 158q24 22 52 22q6 0 18 -1.5t19 -1.5q19 0 26.5 -6.5t15.5 -27.5q8 -20 33 -88t25 -75q0 -21 -34.5 -57.5 t-34.5 -46.5q0 -7 5 -15q34 -73 102 -137q56 -53 151 -101q12 -7 22 -7q15 0 54 48.5t52 48.5zM782 32q127 0 243.5 50t200.5 134t134 200.5t50 243.5t-50 243.5t-134 200.5t-200.5 134t-243.5 50t-243.5 -50t-200.5 -134t-134 - [...]
+<glyph unicode="&#xf233;" horiz-adv-x="1792" d="M128 128h1024v128h-1024v-128zM128 640h1024v128h-1024v-128zM1696 192q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM128 1152h1024v128h-1024v-128zM1696 704q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1696 1216 q0 40 -28 68t-68 28t-68 -28t-28 -68t28 -68t68 -28t68 28t28 68zM1792 384v-384h-1792v384h1792zM1792 896v-384h-1792v384h1792zM1792 1408v-384h-1792v384h1792z" />
+<glyph unicode="&#xf234;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1664 512h352q13 0 22.5 -9.5t9.5 -22.5v-192q0 -13 -9.5 -22.5t-22.5 -9.5h-352v-352q0 -13 -9.5 -22.5t-22.5 -9.5h-192q-13 0 -22.5 9.5 t-9.5 22.5v352h-352q-13 0 -22.5 9.5t-9.5 22.5v192q0 13 9.5 22.5t22.5 9.5h352v352q0 13 9.5 22.5t22.5 9.5h192q13 0 22.5 -9.5t9.5 -22.5v-352zM928 288q0 -52 38 -90t90 -38h256v-238q-68 -50 -171 -50h [...]
+<glyph unicode="&#xf235;" horiz-adv-x="2048" d="M704 640q-159 0 -271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5t-112.5 -271.5t-271.5 -112.5zM1781 320l249 -249q9 -9 9 -23q0 -13 -9 -22l-136 -136q-9 -9 -22 -9q-14 0 -23 9l-249 249l-249 -249q-9 -9 -23 -9q-13 0 -22 9l-136 136 q-9 9 -9 22q0 14 9 23l249 249l-249 249q-9 9 -9 23q0 13 9 22l136 136q9 9 22 9q14 0 23 -9l249 -249l249 249q9 9 23 9q13 0 22 -9l136 -136q9 -9 9 -22q0 -14 -9 -23zM1283 320l-181 -181q-37 -37 -37 -91 [...]
+<glyph unicode="&#xf236;" horiz-adv-x="2048" d="M256 512h1728q26 0 45 -19t19 -45v-448h-256v256h-1536v-256h-256v1216q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-704zM832 832q0 106 -75 181t-181 75t-181 -75t-75 -181t75 -181t181 -75t181 75t75 181zM2048 576v64q0 159 -112.5 271.5t-271.5 112.5h-704 q-26 0 -45 -19t-19 -45v-384h1152z" />
+<glyph unicode="&#xf237;" d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
+<glyph unicode="&#xf238;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56 t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
+<glyph unicode="&#xf239;" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47 t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
+<glyph unicode="&#xf23a;" horiz-adv-x="1792" d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116 q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
+<glyph unicode="&#xf23b;" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
+<glyph unicode="&#xf23c;" horiz-adv-x="2296" d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5 q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5z [...]
+<glyph unicode="&#xf23d;" horiz-adv-x="2304" d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5 t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98 [...]
+<glyph unicode="&#xf23e;" horiz-adv-x="1792" d="M896 1472q-169 0 -323 -66t-265.5 -177.5t-177.5 -265.5t-66 -323t66 -323t177.5 -265.5t265.5 -177.5t323 -66t323 66t265.5 177.5t177.5 265.5t66 323t-66 323t-177.5 265.5t-265.5 177.5t-323 66zM896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348 t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM496 704q16 0 16 -16v-480q0 -16 -16 -16h-32q-16 0 -16 16v480q0 16 16 16h32zM896 640q53 0 90.5 -37.5t37.5 - [...]
+<glyph unicode="&#xf240;" horiz-adv-x="2304" d="M1920 1024v-768h-1664v768h1664zM2048 448h128v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288zM2304 832v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113 v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160q53 0 90.5 -37.5t37.5 -90.5z" />
+<glyph unicode="&#xf241;" horiz-adv-x="2304" d="M256 256v768h1280v-768h-1280zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf242;" horiz-adv-x="2304" d="M256 256v768h896v-768h-896zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf243;" horiz-adv-x="2304" d="M256 256v768h512v-768h-512zM2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9 h-1856q-14 0 -23 -9t-9 -23v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf244;" horiz-adv-x="2304" d="M2176 960q53 0 90.5 -37.5t37.5 -90.5v-384q0 -53 -37.5 -90.5t-90.5 -37.5v-160q0 -66 -47 -113t-113 -47h-1856q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1856q66 0 113 -47t47 -113v-160zM2176 448v384h-128v288q0 14 -9 23t-23 9h-1856q-14 0 -23 -9t-9 -23 v-960q0 -14 9 -23t23 -9h1856q14 0 23 9t9 23v288h128z" />
+<glyph unicode="&#xf245;" horiz-adv-x="1280" d="M1133 493q31 -30 14 -69q-17 -40 -59 -40h-382l201 -476q10 -25 0 -49t-34 -35l-177 -75q-25 -10 -49 0t-35 34l-191 452l-312 -312q-19 -19 -45 -19q-12 0 -24 5q-40 17 -40 59v1504q0 42 40 59q12 5 24 5q27 0 45 -19z" />
+<glyph unicode="&#xf246;" horiz-adv-x="1024" d="M832 1408q-320 0 -320 -224v-416h128v-128h-128v-544q0 -224 320 -224h64v-128h-64q-272 0 -384 146q-112 -146 -384 -146h-64v128h64q320 0 320 224v544h-128v128h128v416q0 224 -320 224h-64v128h64q272 0 384 -146q112 146 384 146h64v-128h-64z" />
+<glyph unicode="&#xf247;" horiz-adv-x="2048" d="M2048 1152h-128v-1024h128v-384h-384v128h-1280v-128h-384v384h128v1024h-128v384h384v-128h1280v128h384v-384zM1792 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 -128v128h-128v-128h128zM1664 0v128h128v1024h-128v128h-1280v-128h-128v-1024h128v-128 h1280zM1920 -128v128h-128v-128h128zM1280 896h384v-768h-896v256h-384v768h896v-256zM512 512h640v512h-640v-512zM1536 256v512h-256v-384h-384v-128h640z" />
+<glyph unicode="&#xf248;" horiz-adv-x="2304" d="M2304 768h-128v-640h128v-384h-384v128h-896v-128h-384v384h128v128h-384v-128h-384v384h128v640h-128v384h384v-128h896v128h384v-384h-128v-128h384v128h384v-384zM2048 1024v-128h128v128h-128zM1408 1408v-128h128v128h-128zM128 1408v-128h128v128h-128zM256 256 v128h-128v-128h128zM1536 384h-128v-128h128v128zM384 384h896v128h128v640h-128v128h-896v-128h-128v-640h128v-128zM896 -128v128h-128v-128h128zM2176 -128v128h-128v-128h128zM2048 128v640h-128v128h-384v [...]
+<glyph unicode="&#xf249;" d="M1024 288v-416h-928q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68v-928h-416q-40 0 -68 -28t-28 -68zM1152 256h381q-15 -82 -65 -132l-184 -184q-50 -50 -132 -65v381z" />
+<glyph unicode="&#xf24a;" d="M1400 256h-248v-248q29 10 41 22l185 185q12 12 22 41zM1120 384h288v896h-1280v-1280h896v288q0 40 28 68t68 28zM1536 1312v-1024q0 -40 -20 -88t-48 -76l-184 -184q-28 -28 -76 -48t-88 -20h-1024q-40 0 -68 28t-28 68v1344q0 40 28 68t68 28h1344q40 0 68 -28t28 -68 z" />
+<glyph unicode="&#xf24b;" horiz-adv-x="2304" d="M1951 538q0 -26 -15.5 -44.5t-38.5 -23.5q-8 -2 -18 -2h-153v140h153q10 0 18 -2q23 -5 38.5 -23.5t15.5 -44.5zM1933 751q0 -25 -15 -42t-38 -21q-3 -1 -15 -1h-139v129h139q3 0 8.5 -0.5t6.5 -0.5q23 -4 38 -21.5t15 -42.5zM728 587v308h-228v-308q0 -58 -38 -94.5 t-105 -36.5q-108 0 -229 59v-112q53 -15 121 -23t109 -9l42 -1q328 0 328 217zM1442 403v113q-99 -52 -200 -59q-108 -8 -169 41t-61 142t61 142t169 41q101 -7 200 -58v112q-48 12 -100 19.5t-80 9.5l-28 2q-12 [...]
+<glyph unicode="&#xf24c;" horiz-adv-x="2304" d="M858 295v693q-106 -41 -172 -135.5t-66 -211.5t66 -211.5t172 -134.5zM1362 641q0 117 -66 211.5t-172 135.5v-694q106 41 172 135.5t66 211.5zM1577 641q0 -159 -78.5 -294t-213.5 -213.5t-294 -78.5q-119 0 -227.5 46.5t-187 125t-125 187t-46.5 227.5q0 159 78.5 294 t213.5 213.5t294 78.5t294 -78.5t213.5 -213.5t78.5 -294zM1960 634q0 139 -55.5 261.5t-147.5 205.5t-213.5 131t-252.5 48h-301q-176 0 -323.5 -81t-235 -230t-87.5 -335q0 -171 87 -317.5t236 -231.5t323  [...]
+<glyph unicode="&#xf24d;" horiz-adv-x="1792" d="M1664 -96v1088q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h1088q13 0 22.5 9.5t9.5 22.5zM1792 992v-1088q0 -66 -47 -113t-113 -47h-1088q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 -47t47 -113 zM1408 1376v-160h-128v160q0 13 -9.5 22.5t-22.5 9.5h-1088q-13 0 -22.5 -9.5t-9.5 -22.5v-1088q0 -13 9.5 -22.5t22.5 -9.5h160v-128h-160q-66 0 -113 47t-47 113v1088q0 66 47 113t113 47h1088q66 0 113 - [...]
+<glyph unicode="&#xf24e;" horiz-adv-x="2304" d="M1728 1088l-384 -704h768zM448 1088l-384 -704h768zM1269 1280q-14 -40 -45.5 -71.5t-71.5 -45.5v-1291h608q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1344q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h608v1291q-40 14 -71.5 45.5t-45.5 71.5h-491q-14 0 -23 9t-9 23v64 q0 14 9 23t23 9h491q21 57 70 92.5t111 35.5t111 -35.5t70 -92.5h491q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-491zM1088 1264q33 0 56.5 23.5t23.5 56.5t-23.5 56.5t-56.5 23.5t-56.5 -23.5t-23.5 -56.5t2 [...]
+<glyph unicode="&#xf250;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11 [...]
+<glyph unicode="&#xf251;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -66 9 -128h1006q9 61 9 128zM1280 -128q0 130 -34 249.5t-90.5 208t-126.5 152t-146 94.5h-230q-76 -31 -146 -94.5t-126.5 -1 [...]
+<glyph unicode="&#xf252;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM1280 1408h-1024q0 -206 85 -384h854q85 178 85 384zM1223 192q-54 141 -145.5 241.5t-194.5 142.5h-230q-103 -42 -194.5 -142.5t-145.5 -241.5h910z" />
+<glyph unicode="&#xf253;" d="M1408 1408q0 -261 -106.5 -461.5t-266.5 -306.5q160 -106 266.5 -306.5t106.5 -461.5h96q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h96q0 261 106.5 461.5t266.5 306.5q-160 106 -266.5 306.5t-106.5 461.5h-96q-14 0 -23 9 t-9 23v64q0 14 9 23t23 9h1472q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-96zM874 700q77 29 149 92.5t129.5 152.5t92.5 210t35 253h-1024q0 -132 35 -253t92.5 -210t129.5 -152.5t149 -92.5q19 -7 30.5 -23.5t11.5 -36.5t-11 [...]
+<glyph unicode="&#xf254;" d="M1504 -64q14 0 23 -9t9 -23v-128q0 -14 -9 -23t-23 -9h-1472q-14 0 -23 9t-9 23v128q0 14 9 23t23 9h1472zM130 0q3 55 16 107t30 95t46 87t53.5 76t64.5 69.5t66 60t70.5 55t66.5 47.5t65 43q-43 28 -65 43t-66.5 47.5t-70.5 55t-66 60t-64.5 69.5t-53.5 76t-46 87 t-30 95t-16 107h1276q-3 -55 -16 -107t-30 -95t-46 -87t-53.5 -76t-64.5 -69.5t-66 -60t-70.5 -55t-66.5 -47.5t-65 -43q43 -28 65 -43t66.5 -47.5t70.5 -55t66 -60t64.5 -69.5t53.5 -76t46 -87t30 -95t16 -107h-1276zM1504 1536q14  [...]
+<glyph unicode="&#xf255;" d="M768 1152q-53 0 -90.5 -37.5t-37.5 -90.5v-128h-32v93q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-429l-32 30v172q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-224q0 -47 35 -82l310 -296q39 -39 39 -102q0 -26 19 -45t45 -19h640q26 0 45 19t19 45v25 q0 41 10 77l108 436q10 36 10 77v246q0 48 -32 81.5t-80 33.5q-46 0 -79 -33t-33 -79v-32h-32v125q0 40 -25 72.5t-64 40.5q-14 2 -23 2q-46 0 -79 -33t-33 -79v-128h-32v122q0 51 -32.5 89.5t-82.5 43.5q-5 1 -13 1zM768 1280q84 0 149 [...]
+<glyph unicode="&#xf256;" horiz-adv-x="1792" d="M880 1408q-46 0 -79 -33t-33 -79v-656h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528v-256l-154 205q-38 51 -102 51q-53 0 -90.5 -37.5t-37.5 -90.5q0 -43 26 -77l384 -512q38 -51 102 -51h688q34 0 61 22t34 56l76 405q5 32 5 59v498q0 46 -33 79t-79 33t-79 -33 t-33 -79v-272h-32v528q0 46 -33 79t-79 33t-79 -33t-33 -79v-528h-32v656q0 46 -33 79t-79 33zM880 1536q68 0 125.5 -35.5t88.5 -96.5q19 4 42 4q99 0 169.5 -70.5t70.5 -169.5v-17q105 6 180.5 -64t75.5 -17 [...]
+<glyph unicode="&#xf257;" horiz-adv-x="1792" d="M1073 -128h-177q-163 0 -226 141q-23 49 -23 102v5q-62 30 -98.5 88.5t-36.5 127.5q0 38 5 48h-261q-106 0 -181 75t-75 181t75 181t181 75h113l-44 17q-74 28 -119.5 93.5t-45.5 145.5q0 106 75 181t181 75q46 0 91 -17l628 -239h401q106 0 181 -75t75 -181v-668 q0 -88 -54 -157.5t-140 -90.5l-339 -85q-92 -23 -186 -23zM1024 583l-155 -71l-163 -74q-30 -14 -48 -41.5t-18 -60.5q0 -46 33 -79t79 -33q26 0 46 10l338 154q-49 10 -80.5 50t-31.5 90v55zM1344 272q0 46 -33 79 [...]
+<glyph unicode="&#xf258;" horiz-adv-x="2048" d="M1151 1536q61 0 116 -28t91 -77l572 -781q118 -159 118 -359v-355q0 -80 -56 -136t-136 -56h-384q-80 0 -136 56t-56 136v177l-286 143h-546q-80 0 -136 56t-56 136v32q0 119 84.5 203.5t203.5 84.5h420l42 128h-686q-100 0 -173.5 67.5t-81.5 166.5q-65 79 -65 182v32 q0 80 56 136t136 56h959zM1920 -64v355q0 157 -93 284l-573 781q-39 52 -103 52h-959q-26 0 -45 -19t-19 -45q0 -32 1.5 -49.5t9.5 -40.5t25 -43q10 31 35.5 50t56.5 19h832v-32h-832q-26 0 -45 -19t-19 -45q0 [...]
+<glyph unicode="&#xf259;" horiz-adv-x="2048" d="M816 1408q-48 0 -79.5 -34t-31.5 -82q0 -14 3 -28l150 -624h-26l-116 482q-9 38 -39.5 62t-69.5 24q-47 0 -79 -34t-32 -81q0 -11 4 -29q3 -13 39 -161t68 -282t32 -138v-227l-307 230q-34 26 -77 26q-52 0 -89.5 -36.5t-37.5 -88.5q0 -67 56 -110l507 -379 q34 -26 76 -26h694q33 0 59 20.5t34 52.5l100 401q8 30 10 88t9 86l116 478q3 12 3 26q0 46 -33 79t-80 33q-38 0 -69 -25.5t-40 -62.5l-99 -408h-26l132 547q3 14 3 28q0 47 -32 80t-80 33q-38 0 -68.5 -24t-39.5 -62l-1 [...]
+<glyph unicode="&#xf25a;" horiz-adv-x="1792" d="M640 1408q-53 0 -90.5 -37.5t-37.5 -90.5v-512v-384l-151 202q-41 54 -107 54q-52 0 -89 -38t-37 -90q0 -43 26 -77l384 -512q38 -51 102 -51h718q22 0 39.5 13.5t22.5 34.5l92 368q24 96 24 194v217q0 41 -28 71t-68 30t-68 -28t-28 -68h-32v61q0 48 -32 81.5t-80 33.5 q-46 0 -79 -33t-33 -79v-64h-32v90q0 55 -37 94.5t-91 39.5q-53 0 -90.5 -37.5t-37.5 -90.5v-96h-32v570q0 55 -37 94.5t-91 39.5zM640 1536q107 0 181.5 -77.5t74.5 -184.5v-220q22 2 32 2q99 0 173 -69q47  [...]
+<glyph unicode="&#xf25b;" d="M1288 889q60 0 107 -23q141 -63 141 -226v-177q0 -94 -23 -186l-85 -339q-21 -86 -90.5 -140t-157.5 -54h-668q-106 0 -181 75t-75 181v401l-239 628q-17 45 -17 91q0 106 75 181t181 75q80 0 145.5 -45.5t93.5 -119.5l17 -44v113q0 106 75 181t181 75t181 -75t75 -181 v-261q27 5 48 5q69 0 127.5 -36.5t88.5 -98.5zM1072 896q-33 0 -60.5 -18t-41.5 -48l-74 -163l-71 -155h55q50 0 90 -31.5t50 -80.5l154 338q10 20 10 46q0 46 -33 79t-79 33zM1293 761q-22 0 -40.5 -8t-29 -16t-23.5 -29.5t-17 - [...]
+<glyph unicode="&#xf25c;" horiz-adv-x="1973" d="M857 992v-117q0 -13 -9.5 -22t-22.5 -9h-298v-812q0 -13 -9 -22.5t-22 -9.5h-135q-13 0 -22.5 9t-9.5 23v812h-297q-13 0 -22.5 9t-9.5 22v117q0 14 9 23t23 9h793q13 0 22.5 -9.5t9.5 -22.5zM1895 995l77 -961q1 -13 -8 -24q-10 -10 -23 -10h-134q-12 0 -21 8.5 t-10 20.5l-46 588l-189 -425q-8 -19 -29 -19h-120q-20 0 -29 19l-188 427l-45 -590q-1 -12 -10 -20.5t-21 -8.5h-135q-13 0 -23 10q-9 10 -9 24l78 961q1 12 10 20.5t21 8.5h142q20 0 29 -19l220 -520q10 -24 20 -51 [...]
+<glyph unicode="&#xf25d;" horiz-adv-x="1792" d="M1042 833q0 88 -60 121q-33 18 -117 18h-123v-281h162q66 0 102 37t36 105zM1094 548l205 -373q8 -17 -1 -31q-8 -16 -27 -16h-152q-20 0 -28 17l-194 365h-155v-350q0 -14 -9 -23t-23 -9h-134q-14 0 -23 9t-9 23v960q0 14 9 23t23 9h294q128 0 190 -24q85 -31 134 -109 t49 -180q0 -92 -42.5 -165.5t-115.5 -109.5q6 -10 9 -16zM896 1376q-150 0 -286 -58.5t-234.5 -157t-157 -234.5t-58.5 -286t58.5 -286t157 -234.5t234.5 -157t286 -58.5t286 58.5t234.5 157t157 234.5t58.5  [...]
+<glyph unicode="&#xf25e;" horiz-adv-x="1792" d="M605 303q153 0 257 104q14 18 3 36l-45 82q-6 13 -24 17q-16 2 -27 -11l-4 -3q-4 -4 -11.5 -10t-17.5 -13t-23.5 -14.5t-28.5 -13.5t-33.5 -9.5t-37.5 -3.5q-76 0 -125 50t-49 127q0 76 48 125.5t122 49.5q37 0 71.5 -14t50.5 -28l16 -14q11 -11 26 -10q16 2 24 14l53 78 q13 20 -2 39q-3 4 -11 12t-30 23.5t-48.5 28t-67.5 22.5t-86 10q-148 0 -246 -96.5t-98 -240.5q0 -146 97 -241.5t247 -95.5zM1235 303q153 0 257 104q14 18 4 36l-45 82q-8 14 -25 17q-16 2 -27 -11l-4 -3q [...]
+<glyph unicode="&#xf260;" horiz-adv-x="2048" d="M736 736l384 -384l-384 -384l-672 672l672 672l168 -168l-96 -96l-72 72l-480 -480l480 -480l193 193l-289 287zM1312 1312l672 -672l-672 -672l-168 168l96 96l72 -72l480 480l-480 480l-193 -193l289 -287l-96 -96l-384 384z" />
+<glyph unicode="&#xf261;" horiz-adv-x="1792" d="M717 182l271 271l-279 279l-88 -88l192 -191l-96 -96l-279 279l279 279l40 -40l87 87l-127 128l-454 -454zM1075 190l454 454l-454 454l-271 -271l279 -279l88 88l-192 191l96 96l279 -279l-279 -279l-40 40l-87 -88zM1792 640q0 -182 -71 -348t-191 -286t-286 -191 t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf262;" horiz-adv-x="2304" d="M651 539q0 -39 -27.5 -66.5t-65.5 -27.5q-39 0 -66.5 27.5t-27.5 66.5q0 38 27.5 65.5t66.5 27.5q38 0 65.5 -27.5t27.5 -65.5zM1805 540q0 -39 -27.5 -66.5t-66.5 -27.5t-66.5 27.5t-27.5 66.5t27.5 66t66.5 27t66.5 -27t27.5 -66zM765 539q0 79 -56.5 136t-136.5 57 t-136.5 -56.5t-56.5 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM1918 540q0 80 -56.5 136.5t-136.5 56.5q-79 0 -136 -56.5t-57 -136.5t56.5 -136.5t136.5 -56.5t136.5 56.5t56.5 136.5zM850 539q [...]
+<glyph unicode="&#xf263;" horiz-adv-x="1280" d="M640 629q-188 0 -321 133t-133 320q0 188 133 321t321 133t321 -133t133 -321q0 -187 -133 -320t-321 -133zM640 1306q-92 0 -157.5 -65.5t-65.5 -158.5q0 -92 65.5 -157.5t157.5 -65.5t157.5 65.5t65.5 157.5q0 93 -65.5 158.5t-157.5 65.5zM1163 574q13 -27 15 -49.5 t-4.5 -40.5t-26.5 -38.5t-42.5 -37t-61.5 -41.5q-115 -73 -315 -94l73 -72l267 -267q30 -31 30 -74t-30 -73l-12 -13q-31 -30 -74 -30t-74 30q-67 68 -267 268l-267 -268q-31 -30 -74 -30t-73 30l-12 13q-31 3 [...]
+<glyph unicode="&#xf264;" d="M927 956q0 -66 -46.5 -112.5t-112.5 -46.5t-112.5 46.5t-46.5 112.5t46.5 112.5t112.5 46.5t112.5 -46.5t46.5 -112.5zM1141 593q-10 20 -28 32t-47.5 9.5t-60.5 -27.5q-10 -8 -29 -20t-81 -32t-127 -20t-124 18t-86 36l-27 18q-31 25 -60.5 27.5t-47.5 -9.5t-28 -32 q-22 -45 -2 -74.5t87 -73.5q83 -53 226 -67l-51 -52q-142 -142 -191 -190q-22 -22 -22 -52.5t22 -52.5l9 -9q22 -22 52.5 -22t52.5 22l191 191q114 -115 191 -191q22 -22 52.5 -22t52.5 22l9 9q22 22 22 52.5t-22 52.5l-191 190l-52 [...]
+<glyph unicode="&#xf265;" horiz-adv-x="1720" d="M1565 1408q65 0 110 -45.5t45 -110.5v-519q0 -176 -68 -336t-182.5 -275t-274 -182.5t-334.5 -67.5q-176 0 -335.5 67.5t-274.5 182.5t-183 275t-68 336v519q0 64 46 110t110 46h1409zM861 344q47 0 82 33l404 388q37 35 37 85q0 49 -34.5 83.5t-83.5 34.5q-47 0 -82 -33 l-323 -310l-323 310q-35 33 -81 33q-49 0 -83.5 -34.5t-34.5 -83.5q0 -51 36 -85l405 -388q33 -33 81 -33z" />
+<glyph unicode="&#xf266;" horiz-adv-x="2304" d="M1494 -103l-295 695q-25 -49 -158.5 -305.5t-198.5 -389.5q-1 -1 -27.5 -0.5t-26.5 1.5q-82 193 -255.5 587t-259.5 596q-21 50 -66.5 107.5t-103.5 100.5t-102 43q0 5 -0.5 24t-0.5 27h583v-50q-39 -2 -79.5 -16t-66.5 -43t-10 -64q26 -59 216.5 -499t235.5 -540 q31 61 140 266.5t131 247.5q-19 39 -126 281t-136 295q-38 69 -201 71v50l513 -1v-47q-60 -2 -93.5 -25t-12.5 -69q33 -70 87 -189.5t86 -187.5q110 214 173 363q24 55 -10 79.5t-129 26.5q1 7 1 25v24q64 0 170.5  [...]
+<glyph unicode="&#xf267;" horiz-adv-x="1792" d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640 q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 1 [...]
+<glyph unicode="&#xf268;" horiz-adv-x="1792" d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962 q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5  [...]
+<glyph unicode="&#xf269;" horiz-adv-x="1792" d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5 q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31. [...]
+<glyph unicode="&#xf26a;" horiz-adv-x="1792" d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339 q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83  [...]
+<glyph unicode="&#xf26b;" horiz-adv-x="1792" d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606 q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 [...]
+<glyph unicode="&#xf26c;" horiz-adv-x="2048" d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23 v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
+<glyph unicode="&#xf26d;" horiz-adv-x="1792" d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34 h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12  [...]
+<glyph unicode="&#xf26e;" d="M1401 -11l-6 -6q-113 -114 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6 q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q [...]
+<glyph unicode="&#xf270;" horiz-adv-x="1792" d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 - [...]
+<glyph unicode="&#xf271;" horiz-adv-x="1792" d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9 h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408 [...]
+<glyph unicode="&#xf272;" horiz-adv-x="1792" d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23 t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 1 [...]
+<glyph unicode="&#xf273;" horiz-adv-x="1792" d="M1111 151l-46 -46q-9 -9 -22 -9t-23 9l-188 189l-188 -189q-10 -9 -23 -9t-22 9l-46 46q-9 9 -9 22t9 23l189 188l-189 188q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l188 -188l188 188q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23l-188 -188l188 -188q9 -10 9 -23t-9 -22z M128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -1 [...]
+<glyph unicode="&#xf274;" horiz-adv-x="1792" d="M1303 572l-512 -512q-10 -9 -23 -9t-23 9l-288 288q-9 10 -9 23t9 22l46 46q9 9 22 9t23 -9l220 -220l444 444q10 9 23 9t22 -9l46 -46q9 -9 9 -22t-9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23 t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 5 [...]
+<glyph unicode="&#xf275;" horiz-adv-x="1792" d="M448 1536q26 0 45 -19t19 -45v-891l536 429q17 14 40 14q26 0 45 -19t19 -45v-379l536 429q17 14 40 14q26 0 45 -19t19 -45v-1152q0 -26 -19 -45t-45 -19h-1664q-26 0 -45 19t-19 45v1664q0 26 19 45t45 19h384z" />
+<glyph unicode="&#xf276;" horiz-adv-x="1024" d="M512 448q66 0 128 15v-655q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v655q61 -15 128 -15zM512 1536q212 0 362 -150t150 -362t-150 -362t-362 -150t-362 150t-150 362t150 362t362 150zM512 1312q14 0 23 9t9 23t-9 23t-23 9q-146 0 -249 -103t-103 -249 q0 -14 9 -23t23 -9t23 9t9 23q0 119 84.5 203.5t203.5 84.5z" />
+<glyph unicode="&#xf277;" horiz-adv-x="1792" d="M1745 1239q10 -10 10 -23t-10 -23l-141 -141q-28 -28 -68 -28h-1344q-26 0 -45 19t-19 45v256q0 26 19 45t45 19h576v64q0 26 19 45t45 19h128q26 0 45 -19t19 -45v-64h512q40 0 68 -28zM768 320h256v-512q0 -26 -19 -45t-45 -19h-128q-26 0 -45 19t-19 45v512zM1600 768 q26 0 45 -19t19 -45v-256q0 -26 -19 -45t-45 -19h-1344q-40 0 -68 28l-141 141q-10 10 -10 23t10 23l141 141q28 28 68 28h512v192h256v-192h576z" />
+<glyph unicode="&#xf278;" horiz-adv-x="2048" d="M2020 1525q28 -20 28 -53v-1408q0 -20 -11 -36t-29 -23l-640 -256q-24 -11 -48 0l-616 246l-616 -246q-10 -5 -24 -5q-19 0 -36 11q-28 20 -28 53v1408q0 20 11 36t29 23l640 256q24 11 48 0l616 -246l616 246q32 13 60 -6zM736 1390v-1270l576 -230v1270zM128 1173 v-1270l544 217v1270zM1920 107v1270l-544 -217v-1270z" />
+<glyph unicode="&#xf279;" horiz-adv-x="1792" d="M512 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472q0 20 17 28l480 256q7 4 15 4zM1760 1536q13 0 22.5 -9.5t9.5 -22.5v-1472q0 -20 -17 -28l-480 -256q-7 -4 -15 -4q-13 0 -22.5 9.5t-9.5 22.5v1472 q0 20 17 28l480 256q7 4 15 4zM640 1536q8 0 14 -3l512 -256q18 -10 18 -29v-1472q0 -13 -9.5 -22.5t-22.5 -9.5q-8 0 -14 3l-512 256q-18 10 -18 29v1472q0 13 9.5 22.5t22.5 9.5z" />
+<glyph unicode="&#xf27a;" horiz-adv-x="1792" d="M640 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1024 640q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1408 640q0 53 -37.5 90.5t-90.5 37.5 t-90.5 -37.5t-37.5 -90.5t37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5zM1792 640q0 -174 -120 -321.5t-326 -233t-450 -85.5q-110 0 -211 18q-173 -173 -435 -229q-52 -10 -86 -13q-12 -1 -22 6t-13 18q-4 15 20 37q5  [...]
+<glyph unicode="&#xf27b;" horiz-adv-x="1792" d="M640 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1024 640q0 -53 -37.5 -90.5t-90.5 -37.5t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM1408 640q0 -53 -37.5 -90.5t-90.5 -37.5 t-90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5t90.5 -37.5t37.5 -90.5zM896 1152q-204 0 -381.5 -69.5t-282 -187.5t-104.5 -255q0 -112 71.5 -213.5t201.5 -175.5l87 -50l-27 -96q-24 -91 -70 -172q152 63 275 171 [...]
+<glyph unicode="&#xf27c;" horiz-adv-x="1024" d="M512 345l512 295v-591l-512 -296v592zM0 640v-591l512 296zM512 1527v-591l-512 -296v591zM512 936l512 295v-591z" />
+<glyph unicode="&#xf27d;" horiz-adv-x="1792" d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246 q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
+<glyph unicode="&#xf27e;" d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
+<glyph unicode="&#xf280;" d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72 h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 [...]
+<glyph unicode="&#xf281;" horiz-adv-x="1792" d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5 l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105 [...]
+<glyph unicode="&#xf282;" horiz-adv-x="1792" d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53 q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -16 [...]
+<glyph unicode="&#xf283;" horiz-adv-x="2304" d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
+<glyph unicode="&#xf284;" horiz-adv-x="1792" d="M1549 857q55 0 85.5 -28.5t30.5 -83.5t-34 -82t-91 -27h-136v-177h-25v398h170zM1710 267l-4 -11l-5 -10q-113 -230 -330.5 -366t-474.5 -136q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q244 0 454.5 -124t329.5 -338l2 -4l8 -16 q-30 -15 -136.5 -68.5t-163.5 -84.5q-6 -3 -479 -268q384 -183 799 -366zM896 -234q250 0 462.5 132.5t322.5 357.5l-287 129q-72 -140 -206 -222t-292 -82q-151 0 -280 75t-204 204t-75 280t75 280t204 204t280 75t2 [...]
+<glyph unicode="&#xf285;" horiz-adv-x="1792" d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
+<glyph unicode="&#xf286;" horiz-adv-x="1792" d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96 q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h16v393q-32 19 -32 55q0 26 19 45t45 19t45 -19t19 -45q0 -36 -32 -55v-9h272q16 0 16 -16v-2 [...]
+<glyph unicode="&#xf287;" horiz-adv-x="2304" d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96 q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t [...]
+<glyph unicode="&#xf288;" horiz-adv-x="1792" d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348 t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
+<glyph unicode="&#xf289;" horiz-adv-x="2304" d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22 q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 22 [...]
+<glyph unicode="&#xf28a;" d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83 t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t- [...]
+<glyph unicode="&#xf28b;" d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103 t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
+<glyph unicode="&#xf28c;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
+<glyph unicode="&#xf28d;" d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
+<glyph unicode="&#xf28e;" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
+<glyph unicode="&#xf290;" horiz-adv-x="1792" d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 11 [...]
+<glyph unicode="&#xf291;" horiz-adv-x="2048" d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5 t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t- [...]
+<glyph unicode="&#xf292;" horiz-adv-x="1792" d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12 q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 3 [...]
+<glyph unicode="&#xf293;" d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5 t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
+<glyph unicode="&#xf294;" horiz-adv-x="1024" d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
+<glyph unicode="&#xf295;" d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5 t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5  [...]
+<glyph unicode="&#xf296;" horiz-adv-x="1792" d="M104 830l792 -1015l-868 630q-18 13 -25 34.5t0 42.5l101 308v0zM566 830h660l-330 -1015v0zM368 1442l198 -612h-462l198 612q8 23 33 23t33 -23zM1688 830l101 -308q7 -21 0 -42.5t-25 -34.5l-868 -630l792 1015v0zM1688 830h-462l198 612q8 23 33 23t33 -23z" />
+<glyph unicode="&#xf297;" horiz-adv-x="1792" d="M384 704h160v224h-160v-224zM1221 372v92q-104 -36 -243 -38q-135 -1 -259.5 46.5t-220.5 122.5l1 -96q88 -80 212 -128.5t272 -47.5q129 0 238 49zM640 704h640v224h-640v-224zM1792 736q0 -187 -99 -352q89 -102 89 -229q0 -157 -129.5 -268t-313.5 -111 q-122 0 -225 52.5t-161 140.5q-19 -1 -57 -1t-57 1q-58 -88 -161 -140.5t-225 -52.5q-184 0 -313.5 111t-129.5 268q0 127 89 229q-99 165 -99 352q0 209 120 385.5t326.5 279.5t449.5 103t449.5 -103t326.5 -279.5t120 -3 [...]
+<glyph unicode="&#xf298;" d="M515 625v-128h-252v128h252zM515 880v-127h-252v127h252zM1273 369v-128h-341v128h341zM1273 625v-128h-672v128h672zM1273 880v-127h-672v127h672zM1408 20v1240q0 8 -6 14t-14 6h-32l-378 -256l-210 171l-210 -171l-378 256h-32q-8 0 -14 -6t-6 -14v-1240q0 -8 6 -14 t14 -6h1240q8 0 14 6t6 14zM553 1130l185 150h-406zM983 1130l221 150h-406zM1536 1260v-1240q0 -62 -43 -105t-105 -43h-1240q-62 0 -105 43t-43 105v1240q0 62 43 105t105 43h1240q62 0 105 -43t43 -105z" />
+<glyph unicode="&#xf299;" horiz-adv-x="1792" d="M896 720q-104 196 -160 278q-139 202 -347 318q-34 19 -70 36q-89 40 -94 32t34 -38l39 -31q62 -43 112.5 -93.5t94.5 -116.5t70.5 -113t70.5 -131q9 -17 13 -25q44 -84 84 -153t98 -154t115.5 -150t131 -123.5t148.5 -90.5q153 -66 154 -60q1 3 -49 37q-53 36 -81 57 q-77 58 -179 211t-185 310zM549 177q-76 60 -132.5 125t-98 143.5t-71 154.5t-58.5 186t-52 209t-60.5 252t-76.5 289q273 0 497.5 -36t379 -92t271 -144.5t185.5 -172.5t110 -198.5t56 -199.5t12.5 -198.5t-9. [...]
+<glyph unicode="&#xf29a;" horiz-adv-x="1792" d="M1374 879q-6 26 -28.5 39.5t-48.5 7.5q-261 -62 -401 -62t-401 62q-26 6 -48.5 -7.5t-28.5 -39.5t7.5 -48.5t39.5 -28.5q194 -46 303 -58q-2 -158 -15.5 -269t-26.5 -155.5t-41 -115.5l-9 -21q-10 -25 1 -49t36 -34q9 -4 23 -4q44 0 60 41l8 20q54 139 71 259h42 q17 -120 71 -259l8 -20q16 -41 60 -41q14 0 23 4q25 10 36 34t1 49l-9 21q-28 71 -41 115.5t-26.5 155.5t-15.5 269q109 12 303 58q26 6 39.5 28.5t7.5 48.5zM1024 1024q0 53 -37.5 90.5t-90.5 37.5t-90.5 -37.5t-37 [...]
+<glyph unicode="&#xf29b;" d="M1438 723q34 -35 29 -82l-44 -551q-4 -42 -34.5 -70t-71.5 -28q-6 0 -9 1q-44 3 -72.5 36.5t-25.5 77.5l35 429l-143 -8q55 -113 55 -240q0 -216 -148 -372l-137 137q91 101 91 235q0 145 -102.5 248t-247.5 103q-134 0 -236 -92l-137 138q120 114 284 141l264 300 l-149 87l-181 -161q-33 -30 -77 -27.5t-73 35.5t-26.5 77t34.5 73l239 213q26 23 60 26.5t64 -14.5l488 -283q36 -21 48 -68q17 -67 -26 -117l-205 -232l371 20q49 3 83 -32zM1240 1180q-74 0 -126 52t-52 126t52 126t126 52t126.5 -5 [...]
+<glyph unicode="&#xf29c;" d="M880 336v-160q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v160q0 14 9 23t23 9h160q14 0 23 -9t9 -23zM1136 832q0 -50 -15 -90t-45.5 -69t-52 -44t-59.5 -36q-32 -18 -46.5 -28t-26 -24t-11.5 -29v-32q0 -14 -9 -23t-23 -9h-160q-14 0 -23 9t-9 23v68q0 35 10.5 64.5 t24 47.5t39 35.5t41 25.5t44.5 21q53 25 75 43t22 49q0 42 -43.5 71.5t-95.5 29.5q-56 0 -95 -27q-29 -20 -80 -83q-9 -12 -25 -12q-11 0 -19 6l-108 82q-10 7 -12 20t5 23q122 192 349 192q129 0 238.5 -89.5t109.5 -214.5zM768  [...]
+<glyph unicode="&#xf29d;" horiz-adv-x="1408" d="M366 1225q-64 0 -110 45.5t-46 110.5q0 64 46 109.5t110 45.5t109.5 -45.5t45.5 -109.5q0 -65 -45.5 -110.5t-109.5 -45.5zM917 583q0 -50 -30 -67.5t-63.5 -6.5t-47.5 34l-367 438q-7 12 -14 15.5t-11 1.5l-3 -3q-7 -8 4 -21l122 -139l1 -354l-161 -457 q-67 -192 -92 -234q-16 -26 -28 -32q-50 -26 -103 -1q-29 13 -41.5 43t-9.5 57q2 17 197 618l5 416l-85 -164l35 -222q4 -24 -1 -42t-14 -27.5t-19 -16t-17 -7.5l-7 -2q-19 -3 -34.5 3t-24 16t-14 22t-7.5 19.5t-2 9.5l-46 2 [...]
+<glyph unicode="&#xf29e;" horiz-adv-x="2304" d="M504 542h171l-1 265zM1530 641q0 87 -50.5 140t-146.5 53h-54v-388h52q91 0 145 57t54 138zM956 1018l1 -756q0 -14 -9.5 -24t-23.5 -10h-216q-14 0 -23.5 10t-9.5 24v62h-291l-55 -81q-10 -15 -28 -15h-267q-21 0 -30.5 18t3.5 35l556 757q9 14 27 14h332q14 0 24 -10 t10 -24zM1783 641q0 -193 -125.5 -303t-324.5 -110h-270q-14 0 -24 10t-10 24v756q0 14 10 24t24 10h268q200 0 326 -109t126 -302zM1939 640q0 -11 -0.5 -29t-8 -71.5t-21.5 -102t-44.5 -108t-73.5 -102.5h-5 [...]
+<glyph unicode="&#xf2a0;" horiz-adv-x="1408" d="M617 -153q0 11 -13 58t-31 107t-20 69q-1 4 -5 26.5t-8.5 36t-13.5 21.5q-15 14 -51 14q-23 0 -70 -5.5t-71 -5.5q-34 0 -47 11q-6 5 -11 15.5t-7.5 20t-6.5 24t-5 18.5q-37 128 -37 255t37 255q1 4 5 18.5t6.5 24t7.5 20t11 15.5q13 11 47 11q24 0 71 -5.5t70 -5.5 q36 0 51 14q9 8 13.5 21.5t8.5 36t5 26.5q2 9 20 69t31 107t13 58q0 22 -43.5 52.5t-75.5 42.5q-20 8 -45 8q-34 0 -98 -18q-57 -17 -96.5 -40.5t-71 -66t-46 -70t-45.5 -94.5q-6 -12 -9 -19q-49 -107 -68 -216t- [...]
+<glyph unicode="&#xf2a1;" horiz-adv-x="2176" d="M192 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM704 864q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 352 q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1984 352q-66 0 -113 -47t-47 -113t47 -113t113 -47t113 47t47 113t-47 113t-113 47zM1472 864q-66 0 -113 -47t-47 -113t47 -113t113  [...]
+<glyph unicode="&#xf2a2;" horiz-adv-x="1792" d="M128 -192q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM320 0q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45zM365 365l256 -256l-90 -90l-256 256zM704 384q0 -26 -19 -45t-45 -19t-45 19t-19 45t19 45t45 19t45 -19t19 -45z M1411 704q0 -59 -11.5 -108.5t-37.5 -93.5t-44 -67.5t-53 -64.5q-31 -35 -45.5 -54t-33.5 -50t-26.5 -64t-7.5 -74q0 -159 -112.5 -271.5t-271.5 -112.5q-26 0 -45 19t-19 45t19 45t45 19q106 0 181 75t75 181q0 [...]
+<glyph unicode="&#xf2a3;" horiz-adv-x="2304" d="M1032 576q-59 2 -84 55q-17 34 -48 53.5t-68 19.5q-53 0 -90.5 -37.5t-37.5 -90.5q0 -56 36 -89l10 -8q34 -31 82 -31q37 0 68 19.5t48 53.5q25 53 84 55zM1600 704q0 56 -36 89l-10 8q-34 31 -82 31q-37 0 -68 -19.5t-48 -53.5q-25 -53 -84 -55q59 -2 84 -55 q17 -34 48 -53.5t68 -19.5q53 0 90.5 37.5t37.5 90.5zM1174 925q-17 -35 -55 -48t-73 4q-62 31 -134 31q-51 0 -99 -17q3 0 9.5 0.5t9.5 0.5q92 0 170.5 -50t118.5 -133q17 -36 3.5 -73.5t-49.5 -54.5q-18 -9 -39 -9q21 [...]
+<glyph unicode="&#xf2a4;" horiz-adv-x="1792" d="M1056 704q0 -26 19 -45t45 -19t45 19t19 45q0 146 -103 249t-249 103t-249 -103t-103 -249q0 -26 19 -45t45 -19t45 19t19 45q0 93 66 158.5t158 65.5t158 -65.5t66 -158.5zM835 1280q-117 0 -223.5 -45.5t-184 -123t-123 -184t-45.5 -223.5q0 -26 19 -45t45 -19t45 19 t19 45q0 185 131.5 316.5t316.5 131.5t316.5 -131.5t131.5 -316.5q0 -55 -18 -103.5t-37.5 -74.5t-59.5 -72q-34 -39 -52 -63t-43.5 -66.5t-37 -91t-11.5 -105.5q0 -106 -75 -181t-181 -75q-26 0 -45 -19t-19  [...]
+<glyph unicode="&#xf2a5;" d="M866 1021q0 -27 -13 -94q-11 -50 -31.5 -150t-30.5 -150q-2 -11 -4.5 -12.5t-13.5 -2.5q-20 -2 -31 -2q-58 0 -84 49.5t-26 113.5q0 88 35 174t103 124q28 14 51 14q28 0 36.5 -16.5t8.5 -47.5zM1352 597q0 14 -39 75.5t-52 66.5q-21 8 -34 8q-91 0 -226 -77l-2 2 q3 22 27.5 135t24.5 178q0 233 -242 233q-24 0 -68 -6q-94 -17 -168.5 -89.5t-111.5 -166.5t-37 -189q0 -146 80.5 -225t227.5 -79q25 0 25 -3t-1 -5q-4 -34 -26 -117q-14 -52 -51.5 -101t-82.5 -49q-42 0 -42 47q0 24 10.5 47.5t25 39 [...]
+<glyph unicode="&#xf2a6;" horiz-adv-x="1535" d="M744 1231q0 24 -2 38.5t-8.5 30t-21 23t-37.5 7.5q-39 0 -78 -23q-105 -58 -159 -190.5t-54 -269.5q0 -44 8.5 -85.5t26.5 -80.5t52.5 -62.5t81.5 -23.5q4 0 18 -0.5t20 0t16 3t15 8.5t7 16q16 77 48 231.5t48 231.5q19 91 19 146zM1498 575q0 -7 -7.5 -13.5t-15.5 -6.5 l-6 1q-22 3 -62 11t-72 12.5t-63 4.5q-167 0 -351 -93q-15 -8 -21 -27q-10 -36 -24.5 -105.5t-22.5 -100.5q-23 -91 -70 -179.5t-112.5 -164.5t-154.5 -123t-185 -47q-135 0 -214.5 83.5t-79.5 219.5q0 53 19 [...]
+<glyph unicode="&#xf2a7;" horiz-adv-x="1664" d="M831 863q32 0 59 -18l222 -148q61 -40 110 -97l146 -170q40 -46 29 -106l-72 -413q-6 -32 -29.5 -53.5t-55.5 -25.5l-527 -56l-352 -32h-9q-39 0 -67.5 28t-28.5 68q0 37 27 64t65 32l260 32h-448q-41 0 -69.5 30t-26.5 71q2 39 32 65t69 26l442 1l-521 64q-41 5 -66 37 t-19 73q6 35 34.5 57.5t65.5 22.5h10l481 -60l-351 94q-38 10 -62 41.5t-18 68.5q6 36 33 58.5t62 22.5q6 0 20 -2l448 -96l217 -37q1 0 3 -0.5t3 -0.5q23 0 30.5 23t-12.5 36l-186 125q-35 23 -42 63.5t18 7 [...]
+<glyph unicode="&#xf2a8;" horiz-adv-x="1792" d="M335 180q-2 0 -6 2q-86 57 -168.5 145t-139.5 180q-21 30 -21 69q0 9 2 19t4 18t7 18t8.5 16t10.5 17t10 15t12 15.5t11 14.5q184 251 452 365q-110 198 -110 211q0 19 17 29q116 64 128 64q18 0 28 -16l124 -229q92 19 192 19q266 0 497.5 -137.5t378.5 -369.5 q20 -31 20 -69t-20 -69q-91 -142 -218.5 -253.5t-278.5 -175.5q110 -198 110 -211q0 -20 -17 -29q-116 -64 -127 -64q-19 0 -29 16l-124 229l-64 119l-444 820l7 7q-58 -24 -99 -47q3 -5 127 -234t243 -449t119 -223q [...]
+<glyph unicode="&#xf2a9;" horiz-adv-x="1280" d="M1050 430q0 -215 -147 -374q-148 -161 -378 -161q-232 0 -378 161q-147 159 -147 374q0 147 68 270.5t189 196.5t268 73q96 0 182 -31q-32 -62 -39 -126q-66 28 -143 28q-167 0 -280.5 -123t-113.5 -291q0 -170 112.5 -288.5t281.5 -118.5t281 118.5t112 288.5 q0 89 -32 166q66 13 123 49q41 -98 41 -212zM846 619q0 -192 -79.5 -345t-238.5 -253l-14 -1q-29 0 -62 5q83 32 146.5 102.5t99.5 154.5t58.5 189t30 192.5t7.5 178.5q0 69 -3 103q55 -160 55 -326zM791 947v-2q-73 2 [...]
+<glyph unicode="&#xf2aa;" d="M1050 495q0 78 -28 147q-41 -25 -85 -34q22 -50 22 -114q0 -117 -77 -198.5t-193 -81.5t-193.5 81.5t-77.5 198.5q0 115 78 199.5t193 84.5q53 0 98 -19q4 43 27 87q-60 21 -125 21q-154 0 -257.5 -108.5t-103.5 -263.5t103.5 -261t257.5 -106t257.5 106.5t103.5 260.5z M872 850q2 -24 2 -71q0 -63 -5 -123t-20.5 -132.5t-40.5 -130t-68.5 -106t-100.5 -70.5q21 -3 42 -3h10q219 139 219 411q0 116 -38 225zM872 850q-4 80 -44 171.5t-98 130.5q92 -156 142 -302zM1207 955q0 102 -51 174q-41 -86  [...]
+<glyph unicode="&#xf2ab;" d="M1279 388q0 22 -22 27q-67 15 -118 59t-80 108q-7 19 -7 25q0 15 19.5 26t43 17t43 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-12 0 -32 -8t-31 -8q-4 0 -12 2q5 95 5 114q0 79 -17 114q-36 78 -103 121.5t-152 43.5q-199 0 -275 -165q-17 -35 -17 -114q0 -19 5 -114 q-4 -2 -14 -2q-12 0 -32 7.5t-30 7.5q-21 0 -38.5 -12t-17.5 -32q0 -21 19.5 -35.5t43 -20.5t43 -17t19.5 -26q0 -6 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -46 137 -68q2 -5 6 -26t11.5 -30.5t23.5 -9.5q12 0 37.5 4.5t39 [...]
+<glyph unicode="&#xf2ac;" horiz-adv-x="1664" d="M848 1408q134 1 240.5 -68.5t163.5 -192.5q27 -58 27 -179q0 -47 -9 -191q14 -7 28 -7q18 0 51 13.5t51 13.5q29 0 56 -18t27 -46q0 -32 -31.5 -54t-69 -31.5t-69 -29t-31.5 -47.5q0 -15 12 -43q37 -82 102.5 -150t144.5 -101q28 -12 80 -23q28 -6 28 -35 q0 -70 -219 -103q-7 -11 -11 -39t-14 -46.5t-33 -18.5q-20 0 -62 6.5t-64 6.5q-37 0 -62 -5q-32 -5 -63 -22.5t-58 -38t-58 -40.5t-76 -33.5t-99 -13.5q-52 0 -96.5 13.5t-75 33.5t-57.5 40.5t-58 38t-62 22.5q-26 5 -63 5q [...]
+<glyph unicode="&#xf2ad;" d="M1280 388q0 22 -22 27q-67 14 -118 58t-80 109q-7 14 -7 25q0 15 19.5 26t42.5 17t42.5 20.5t19.5 36.5q0 19 -18.5 31.5t-38.5 12.5q-11 0 -31 -8t-32 -8q-4 0 -12 2q5 63 5 115q0 78 -17 114q-36 78 -102.5 121.5t-152.5 43.5q-198 0 -275 -165q-18 -38 -18 -115 q0 -38 6 -114q-10 -2 -15 -2q-11 0 -31.5 8t-30.5 8q-20 0 -37.5 -12.5t-17.5 -32.5q0 -21 19.5 -35.5t42.5 -20.5t42.5 -17t19.5 -26q0 -11 -7 -25q-64 -138 -198 -167q-22 -5 -22 -27q0 -47 138 -69q2 -5 6 -26t11 -30.5t23 -9.5q13 [...]
+<glyph unicode="&#xf2ae;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b0;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b1;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b2;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b3;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b4;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b5;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b6;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b7;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b8;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2b9;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2ba;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2bb;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2bc;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2bd;" horiz-adv-x="1792" />
+<glyph unicode="&#xf2be;" horiz-adv-x="1792" />
+<glyph unicode="&#xf500;" horiz-adv-x="1792" />
+</font>
+</defs></svg> 
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.ttf b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.ttf
new file mode 100644
index 0000000..86784df
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.ttf differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.woff b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.woff
new file mode 100644
index 0000000..c7faa19
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.woff differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.woff2 b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.woff2
new file mode 100644
index 0000000..cab8571
Binary files /dev/null and b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/font-awesome/4.6.1/fonts/fontawesome-webfont.woff2 differ
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.js
new file mode 100644
index 0000000..69fa11b
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.js
@@ -0,0 +1,748 @@
+/*! jQuery UI - v1.12.1 - 2016-11-18
+* http://jqueryui.com
+* Includes: widget.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+(function( factory ) {
+	if ( typeof define === "function" && define.amd ) {
+
+		// AMD. Register as an anonymous module.
+		define([ "jquery" ], factory );
+	} else {
+
+		// Browser globals
+		factory( jQuery );
+	}
+}(function( $ ) {
+
+$.ui = $.ui || {};
+
+var version = $.ui.version = "1.12.1";
+
+
+/*!
+ * jQuery UI Widget 1.12.1
+ * http://jqueryui.com
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+
+//>>label: Widget
+//>>group: Core
+//>>description: Provides a factory for creating stateful widgets with a common API.
+//>>docs: http://api.jqueryui.com/jQuery.widget/
+//>>demos: http://jqueryui.com/widget/
+
+
+
+var widgetUuid = 0;
+var widgetSlice = Array.prototype.slice;
+
+$.cleanData = ( function( orig ) {
+	return function( elems ) {
+		var events, elem, i;
+		for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
+			try {
+
+				// Only trigger remove when necessary to save time
+				events = $._data( elem, "events" );
+				if ( events && events.remove ) {
+					$( elem ).triggerHandler( "remove" );
+				}
+
+			// Http://bugs.jquery.com/ticket/8235
+			} catch ( e ) {}
+		}
+		orig( elems );
+	};
+} )( $.cleanData );
+
+$.widget = function( name, base, prototype ) {
+	var existingConstructor, constructor, basePrototype;
+
+	// ProxiedPrototype allows the provided prototype to remain unmodified
+	// so that it can be used as a mixin for multiple widgets (#8876)
+	var proxiedPrototype = {};
+
+	var namespace = name.split( "." )[ 0 ];
+	name = name.split( "." )[ 1 ];
+	var fullName = namespace + "-" + name;
+
+	if ( !prototype ) {
+		prototype = base;
+		base = $.Widget;
+	}
+
+	if ( $.isArray( prototype ) ) {
+		prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
+	}
+
+	// Create selector for plugin
+	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
+		return !!$.data( elem, fullName );
+	};
+
+	$[ namespace ] = $[ namespace ] || {};
+	existingConstructor = $[ namespace ][ name ];
+	constructor = $[ namespace ][ name ] = function( options, element ) {
+
+		// Allow instantiation without "new" keyword
+		if ( !this._createWidget ) {
+			return new constructor( options, element );
+		}
+
+		// Allow instantiation without initializing for simple inheritance
+		// must use "new" keyword (the code above always passes args)
+		if ( arguments.length ) {
+			this._createWidget( options, element );
+		}
+	};
+
+	// Extend with the existing constructor to carry over any static properties
+	$.extend( constructor, existingConstructor, {
+		version: prototype.version,
+
+		// Copy the object used to create the prototype in case we need to
+		// redefine the widget later
+		_proto: $.extend( {}, prototype ),
+
+		// Track widgets that inherit from this widget in case this widget is
+		// redefined after a widget inherits from it
+		_childConstructors: []
+	} );
+
+	basePrototype = new base();
+
+	// We need to make the options hash a property directly on the new instance
+	// otherwise we'll modify the options hash on the prototype that we're
+	// inheriting from
+	basePrototype.options = $.widget.extend( {}, basePrototype.options );
+	$.each( prototype, function( prop, value ) {
+		if ( !$.isFunction( value ) ) {
+			proxiedPrototype[ prop ] = value;
+			return;
+		}
+		proxiedPrototype[ prop ] = ( function() {
+			function _super() {
+				return base.prototype[ prop ].apply( this, arguments );
+			}
+
+			function _superApply( args ) {
+				return base.prototype[ prop ].apply( this, args );
+			}
+
+			return function() {
+				var __super = this._super;
+				var __superApply = this._superApply;
+				var returnValue;
+
+				this._super = _super;
+				this._superApply = _superApply;
+
+				returnValue = value.apply( this, arguments );
+
+				this._super = __super;
+				this._superApply = __superApply;
+
+				return returnValue;
+			};
+		} )();
+	} );
+	constructor.prototype = $.widget.extend( basePrototype, {
+
+		// TODO: remove support for widgetEventPrefix
+		// always use the name + a colon as the prefix, e.g., draggable:start
+		// don't prefix for widgets that aren't DOM-based
+		widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
+	}, proxiedPrototype, {
+		constructor: constructor,
+		namespace: namespace,
+		widgetName: name,
+		widgetFullName: fullName
+	} );
+
+	// If this widget is being redefined then we need to find all widgets that
+	// are inheriting from it and redefine all of them so that they inherit from
+	// the new version of this widget. We're essentially trying to replace one
+	// level in the prototype chain.
+	if ( existingConstructor ) {
+		$.each( existingConstructor._childConstructors, function( i, child ) {
+			var childPrototype = child.prototype;
+
+			// Redefine the child widget using the same prototype that was
+			// originally used, but inherit from the new version of the base
+			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
+				child._proto );
+		} );
+
+		// Remove the list of existing child constructors from the old constructor
+		// so the old child constructors can be garbage collected
+		delete existingConstructor._childConstructors;
+	} else {
+		base._childConstructors.push( constructor );
+	}
+
+	$.widget.bridge( name, constructor );
+
+	return constructor;
+};
+
+$.widget.extend = function( target ) {
+	var input = widgetSlice.call( arguments, 1 );
+	var inputIndex = 0;
+	var inputLength = input.length;
+	var key;
+	var value;
+
+	for ( ; inputIndex < inputLength; inputIndex++ ) {
+		for ( key in input[ inputIndex ] ) {
+			value = input[ inputIndex ][ key ];
+			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
+
+				// Clone objects
+				if ( $.isPlainObject( value ) ) {
+					target[ key ] = $.isPlainObject( target[ key ] ) ?
+						$.widget.extend( {}, target[ key ], value ) :
+
+						// Don't extend strings, arrays, etc. with objects
+						$.widget.extend( {}, value );
+
+				// Copy everything else by reference
+				} else {
+					target[ key ] = value;
+				}
+			}
+		}
+	}
+	return target;
+};
+
+$.widget.bridge = function( name, object ) {
+	var fullName = object.prototype.widgetFullName || name;
+	$.fn[ name ] = function( options ) {
+		var isMethodCall = typeof options === "string";
+		var args = widgetSlice.call( arguments, 1 );
+		var returnValue = this;
+
+		if ( isMethodCall ) {
+
+			// If this is an empty collection, we need to have the instance method
+			// return undefined instead of the jQuery instance
+			if ( !this.length && options === "instance" ) {
+				returnValue = undefined;
+			} else {
+				this.each( function() {
+					var methodValue;
+					var instance = $.data( this, fullName );
+
+					if ( options === "instance" ) {
+						returnValue = instance;
+						return false;
+					}
+
+					if ( !instance ) {
+						return $.error( "cannot call methods on " + name +
+							" prior to initialization; " +
+							"attempted to call method '" + options + "'" );
+					}
+
+					if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
+						return $.error( "no such method '" + options + "' for " + name +
+							" widget instance" );
+					}
+
+					methodValue = instance[ options ].apply( instance, args );
+
+					if ( methodValue !== instance && methodValue !== undefined ) {
+						returnValue = methodValue && methodValue.jquery ?
+							returnValue.pushStack( methodValue.get() ) :
+							methodValue;
+						return false;
+					}
+				} );
+			}
+		} else {
+
+			// Allow multiple hashes to be passed on init
+			if ( args.length ) {
+				options = $.widget.extend.apply( null, [ options ].concat( args ) );
+			}
+
+			this.each( function() {
+				var instance = $.data( this, fullName );
+				if ( instance ) {
+					instance.option( options || {} );
+					if ( instance._init ) {
+						instance._init();
+					}
+				} else {
+					$.data( this, fullName, new object( options, this ) );
+				}
+			} );
+		}
+
+		return returnValue;
+	};
+};
+
+$.Widget = function( /* options, element */ ) {};
+$.Widget._childConstructors = [];
+
+$.Widget.prototype = {
+	widgetName: "widget",
+	widgetEventPrefix: "",
+	defaultElement: "<div>",
+
+	options: {
+		classes: {},
+		disabled: false,
+
+		// Callbacks
+		create: null
+	},
+
+	_createWidget: function( options, element ) {
+		element = $( element || this.defaultElement || this )[ 0 ];
+		this.element = $( element );
+		this.uuid = widgetUuid++;
+		this.eventNamespace = "." + this.widgetName + this.uuid;
+
+		this.bindings = $();
+		this.hoverable = $();
+		this.focusable = $();
+		this.classesElementLookup = {};
+
+		if ( element !== this ) {
+			$.data( element, this.widgetFullName, this );
+			this._on( true, this.element, {
+				remove: function( event ) {
+					if ( event.target === element ) {
+						this.destroy();
+					}
+				}
+			} );
+			this.document = $( element.style ?
+
+				// Element within the document
+				element.ownerDocument :
+
+				// Element is window or document
+				element.document || element );
+			this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
+		}
+
+		this.options = $.widget.extend( {},
+			this.options,
+			this._getCreateOptions(),
+			options );
+
+		this._create();
+
+		if ( this.options.disabled ) {
+			this._setOptionDisabled( this.options.disabled );
+		}
+
+		this._trigger( "create", null, this._getCreateEventData() );
+		this._init();
+	},
+
+	_getCreateOptions: function() {
+		return {};
+	},
+
+	_getCreateEventData: $.noop,
+
+	_create: $.noop,
+
+	_init: $.noop,
+
+	destroy: function() {
+		var that = this;
+
+		this._destroy();
+		$.each( this.classesElementLookup, function( key, value ) {
+			that._removeClass( value, key );
+		} );
+
+		// We can probably remove the unbind calls in 2.0
+		// all event bindings should go through this._on()
+		this.element
+			.off( this.eventNamespace )
+			.removeData( this.widgetFullName );
+		this.widget()
+			.off( this.eventNamespace )
+			.removeAttr( "aria-disabled" );
+
+		// Clean up events and states
+		this.bindings.off( this.eventNamespace );
+	},
+
+	_destroy: $.noop,
+
+	widget: function() {
+		return this.element;
+	},
+
+	option: function( key, value ) {
+		var options = key;
+		var parts;
+		var curOption;
+		var i;
+
+		if ( arguments.length === 0 ) {
+
+			// Don't return a reference to the internal hash
+			return $.widget.extend( {}, this.options );
+		}
+
+		if ( typeof key === "string" ) {
+
+			// Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+			options = {};
+			parts = key.split( "." );
+			key = parts.shift();
+			if ( parts.length ) {
+				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
+				for ( i = 0; i < parts.length - 1; i++ ) {
+					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
+					curOption = curOption[ parts[ i ] ];
+				}
+				key = parts.pop();
+				if ( arguments.length === 1 ) {
+					return curOption[ key ] === undefined ? null : curOption[ key ];
+				}
+				curOption[ key ] = value;
+			} else {
+				if ( arguments.length === 1 ) {
+					return this.options[ key ] === undefined ? null : this.options[ key ];
+				}
+				options[ key ] = value;
+			}
+		}
+
+		this._setOptions( options );
+
+		return this;
+	},
+
+	_setOptions: function( options ) {
+		var key;
+
+		for ( key in options ) {
+			this._setOption( key, options[ key ] );
+		}
+
+		return this;
+	},
+
+	_setOption: function( key, value ) {
+		if ( key === "classes" ) {
+			this._setOptionClasses( value );
+		}
+
+		this.options[ key ] = value;
+
+		if ( key === "disabled" ) {
+			this._setOptionDisabled( value );
+		}
+
+		return this;
+	},
+
+	_setOptionClasses: function( value ) {
+		var classKey, elements, currentElements;
+
+		for ( classKey in value ) {
+			currentElements = this.classesElementLookup[ classKey ];
+			if ( value[ classKey ] === this.options.classes[ classKey ] ||
+					!currentElements ||
+					!currentElements.length ) {
+				continue;
+			}
+
+			// We are doing this to create a new jQuery object because the _removeClass() call
+			// on the next line is going to destroy the reference to the current elements being
+			// tracked. We need to save a copy of this collection so that we can add the new classes
+			// below.
+			elements = $( currentElements.get() );
+			this._removeClass( currentElements, classKey );
+
+			// We don't use _addClass() here, because that uses this.options.classes
+			// for generating the string of classes. We want to use the value passed in from
+			// _setOption(), this is the new value of the classes option which was passed to
+			// _setOption(). We pass this value directly to _classes().
+			elements.addClass( this._classes( {
+				element: elements,
+				keys: classKey,
+				classes: value,
+				add: true
+			} ) );
+		}
+	},
+
+	_setOptionDisabled: function( value ) {
+		this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
+
+		// If the widget is becoming disabled, then nothing is interactive
+		if ( value ) {
+			this._removeClass( this.hoverable, null, "ui-state-hover" );
+			this._removeClass( this.focusable, null, "ui-state-focus" );
+		}
+	},
+
+	enable: function() {
+		return this._setOptions( { disabled: false } );
+	},
+
+	disable: function() {
+		return this._setOptions( { disabled: true } );
+	},
+
+	_classes: function( options ) {
+		var full = [];
+		var that = this;
+
+		options = $.extend( {
+			element: this.element,
+			classes: this.options.classes || {}
+		}, options );
+
+		function processClassString( classes, checkOption ) {
+			var current, i;
+			for ( i = 0; i < classes.length; i++ ) {
+				current = that.classesElementLookup[ classes[ i ] ] || $();
+				if ( options.add ) {
+					current = $( $.unique( current.get().concat( options.element.get() ) ) );
+				} else {
+					current = $( current.not( options.element ).get() );
+				}
+				that.classesElementLookup[ classes[ i ] ] = current;
+				full.push( classes[ i ] );
+				if ( checkOption && options.classes[ classes[ i ] ] ) {
+					full.push( options.classes[ classes[ i ] ] );
+				}
+			}
+		}
+
+		this._on( options.element, {
+			"remove": "_untrackClassesElement"
+		} );
+
+		if ( options.keys ) {
+			processClassString( options.keys.match( /\S+/g ) || [], true );
+		}
+		if ( options.extra ) {
+			processClassString( options.extra.match( /\S+/g ) || [] );
+		}
+
+		return full.join( " " );
+	},
+
+	_untrackClassesElement: function( event ) {
+		var that = this;
+		$.each( that.classesElementLookup, function( key, value ) {
+			if ( $.inArray( event.target, value ) !== -1 ) {
+				that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
+			}
+		} );
+	},
+
+	_removeClass: function( element, keys, extra ) {
+		return this._toggleClass( element, keys, extra, false );
+	},
+
+	_addClass: function( element, keys, extra ) {
+		return this._toggleClass( element, keys, extra, true );
+	},
+
+	_toggleClass: function( element, keys, extra, add ) {
+		add = ( typeof add === "boolean" ) ? add : extra;
+		var shift = ( typeof element === "string" || element === null ),
+			options = {
+				extra: shift ? keys : extra,
+				keys: shift ? element : keys,
+				element: shift ? this.element : element,
+				add: add
+			};
+		options.element.toggleClass( this._classes( options ), add );
+		return this;
+	},
+
+	_on: function( suppressDisabledCheck, element, handlers ) {
+		var delegateElement;
+		var instance = this;
+
+		// No suppressDisabledCheck flag, shuffle arguments
+		if ( typeof suppressDisabledCheck !== "boolean" ) {
+			handlers = element;
+			element = suppressDisabledCheck;
+			suppressDisabledCheck = false;
+		}
+
+		// No element argument, shuffle and use this.element
+		if ( !handlers ) {
+			handlers = element;
+			element = this.element;
+			delegateElement = this.widget();
+		} else {
+			element = delegateElement = $( element );
+			this.bindings = this.bindings.add( element );
+		}
+
+		$.each( handlers, function( event, handler ) {
+			function handlerProxy() {
+
+				// Allow widgets to customize the disabled handling
+				// - disabled as an array instead of boolean
+				// - disabled class as method for disabling individual parts
+				if ( !suppressDisabledCheck &&
+						( instance.options.disabled === true ||
+						$( this ).hasClass( "ui-state-disabled" ) ) ) {
+					return;
+				}
+				return ( typeof handler === "string" ? instance[ handler ] : handler )
+					.apply( instance, arguments );
+			}
+
+			// Copy the guid so direct unbinding works
+			if ( typeof handler !== "string" ) {
+				handlerProxy.guid = handler.guid =
+					handler.guid || handlerProxy.guid || $.guid++;
+			}
+
+			var match = event.match( /^([\w:-]*)\s*(.*)$/ );
+			var eventName = match[ 1 ] + instance.eventNamespace;
+			var selector = match[ 2 ];
+
+			if ( selector ) {
+				delegateElement.on( eventName, selector, handlerProxy );
+			} else {
+				element.on( eventName, handlerProxy );
+			}
+		} );
+	},
+
+	_off: function( element, eventName ) {
+		eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
+			this.eventNamespace;
+		element.off( eventName ).off( eventName );
+
+		// Clear the stack to avoid memory leaks (#10056)
+		this.bindings = $( this.bindings.not( element ).get() );
+		this.focusable = $( this.focusable.not( element ).get() );
+		this.hoverable = $( this.hoverable.not( element ).get() );
+	},
+
+	_delay: function( handler, delay ) {
+		function handlerProxy() {
+			return ( typeof handler === "string" ? instance[ handler ] : handler )
+				.apply( instance, arguments );
+		}
+		var instance = this;
+		return setTimeout( handlerProxy, delay || 0 );
+	},
+
+	_hoverable: function( element ) {
+		this.hoverable = this.hoverable.add( element );
+		this._on( element, {
+			mouseenter: function( event ) {
+				this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
+			},
+			mouseleave: function( event ) {
+				this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
+			}
+		} );
+	},
+
+	_focusable: function( element ) {
+		this.focusable = this.focusable.add( element );
+		this._on( element, {
+			focusin: function( event ) {
+				this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
+			},
+			focusout: function( event ) {
+				this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
+			}
+		} );
+	},
+
+	_trigger: function( type, event, data ) {
+		var prop, orig;
+		var callback = this.options[ type ];
+
+		data = data || {};
+		event = $.Event( event );
+		event.type = ( type === this.widgetEventPrefix ?
+			type :
+			this.widgetEventPrefix + type ).toLowerCase();
+
+		// The original event may come from any element
+		// so we need to reset the target on the new event
+		event.target = this.element[ 0 ];
+
+		// Copy original event properties over to the new event
+		orig = event.originalEvent;
+		if ( orig ) {
+			for ( prop in orig ) {
+				if ( !( prop in event ) ) {
+					event[ prop ] = orig[ prop ];
+				}
+			}
+		}
+
+		this.element.trigger( event, data );
+		return !( $.isFunction( callback ) &&
+			callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
+			event.isDefaultPrevented() );
+	}
+};
+
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
+	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
+		if ( typeof options === "string" ) {
+			options = { effect: options };
+		}
+
+		var hasOptions;
+		var effectName = !options ?
+			method :
+			options === true || typeof options === "number" ?
+				defaultEffect :
+				options.effect || defaultEffect;
+
+		options = options || {};
+		if ( typeof options === "number" ) {
+			options = { duration: options };
+		}
+
+		hasOptions = !$.isEmptyObject( options );
+		options.complete = callback;
+
+		if ( options.delay ) {
+			element.delay( options.delay );
+		}
+
+		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
+			element[ method ]( options );
+		} else if ( effectName !== method && element[ effectName ] ) {
+			element[ effectName ]( options.duration, options.easing, callback );
+		} else {
+			element.queue( function( next ) {
+				$( this )[ method ]();
+				if ( callback ) {
+					callback.call( element[ 0 ] );
+				}
+				next();
+			} );
+		}
+	};
+} );
+
+var widget = $.widget;
+
+
+
+
+}));
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.min.js
new file mode 100644
index 0000000..f2a61a2
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.min.js
@@ -0,0 +1,6 @@
+/*! jQuery UI - v1.12.1 - 2016-11-18
+* http://jqueryui.com
+* Includes: widget.js
+* Copyright jQuery Foundation and other contributors; Licensed MIT */
+
+(function(t){"function"==typeof define&&define.amd?define(["jquery"],t):t(jQuery)})(function(t){t.ui=t.ui||{},t.ui.version="1.12.1";var e=0,i=Array.prototype.slice;t.cleanData=function(e){return function(i){var s,n,o;for(o=0;null!=(n=i[o]);o++)try{s=t._data(n,"events"),s&&s.remove&&t(n).triggerHandler("remove")}catch(a){}e(i)}}(t.cleanData),t.widget=function(e,i,s){var n,o,a,r={},l=e.split(".")[0];e=e.split(".")[1];var h=l+"-"+e;return s||(s=i,i=t.Widget),t.isArray(s)&&(s=t.extend.apply( [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.js
new file mode 100644
index 0000000..5c3c456
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.js
@@ -0,0 +1,9814 @@
+/*!
+ * jQuery JavaScript Library v2.2.4
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2016-05-20T17:23Z
+ */
+
+(function( global, factory ) {
+
+	if ( typeof module === "object" && typeof module.exports === "object" ) {
+		// For CommonJS and CommonJS-like environments where a proper `window`
+		// is present, execute the factory and get jQuery.
+		// For environments that do not have a `window` with a `document`
+		// (such as Node.js), expose a factory as module.exports.
+		// This accentuates the need for the creation of a real `window`.
+		// e.g. var jQuery = require("jquery")(window);
+		// See ticket #14549 for more info.
+		module.exports = global.document ?
+			factory( global, true ) :
+			function( w ) {
+				if ( !w.document ) {
+					throw new Error( "jQuery requires a window with a document" );
+				}
+				return factory( w );
+			};
+	} else {
+		factory( global );
+	}
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Support: Firefox 18+
+// Can't be in strict mode, several libs including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+//"use strict";
+var arr = [];
+
+var document = window.document;
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+	version = "2.2.4",
+
+	// Define a local copy of jQuery
+	jQuery = function( selector, context ) {
+
+		// The jQuery object is actually just the init constructor 'enhanced'
+		// Need init if jQuery is called (just allow error to be thrown if not included)
+		return new jQuery.fn.init( selector, context );
+	},
+
+	// Support: Android<4.1
+	// Make sure we trim BOM and NBSP
+	rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+	// Matches dashed string for camelizing
+	rmsPrefix = /^-ms-/,
+	rdashAlpha = /-([\da-z])/gi,
+
+	// Used by jQuery.camelCase as callback to replace()
+	fcamelCase = function( all, letter ) {
+		return letter.toUpperCase();
+	};
+
+jQuery.fn = jQuery.prototype = {
+
+	// The current version of jQuery being used
+	jquery: version,
+
+	constructor: jQuery,
+
+	// Start with an empty selector
+	selector: "",
+
+	// The default length of a jQuery object is 0
+	length: 0,
+
+	toArray: function() {
+		return slice.call( this );
+	},
+
+	// Get the Nth element in the matched element set OR
+	// Get the whole matched element set as a clean array
+	get: function( num ) {
+		return num != null ?
+
+			// Return just the one element from the set
+			( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+			// Return all the elements in a clean array
+			slice.call( this );
+	},
+
+	// Take an array of elements and push it onto the stack
+	// (returning the new matched element set)
+	pushStack: function( elems ) {
+
+		// Build a new jQuery matched element set
+		var ret = jQuery.merge( this.constructor(), elems );
+
+		// Add the old object onto the stack (as a reference)
+		ret.prevObject = this;
+		ret.context = this.context;
+
+		// Return the newly-formed element set
+		return ret;
+	},
+
+	// Execute a callback for every element in the matched set.
+	each: function( callback ) {
+		return jQuery.each( this, callback );
+	},
+
+	map: function( callback ) {
+		return this.pushStack( jQuery.map( this, function( elem, i ) {
+			return callback.call( elem, i, elem );
+		} ) );
+	},
+
+	slice: function() {
+		return this.pushStack( slice.apply( this, arguments ) );
+	},
+
+	first: function() {
+		return this.eq( 0 );
+	},
+
+	last: function() {
+		return this.eq( -1 );
+	},
+
+	eq: function( i ) {
+		var len = this.length,
+			j = +i + ( i < 0 ? len : 0 );
+		return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
+	},
+
+	end: function() {
+		return this.prevObject || this.constructor();
+	},
+
+	// For internal use only.
+	// Behaves like an Array's method, not like a jQuery method.
+	push: push,
+	sort: arr.sort,
+	splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+	var options, name, src, copy, copyIsArray, clone,
+		target = arguments[ 0 ] || {},
+		i = 1,
+		length = arguments.length,
+		deep = false;
+
+	// Handle a deep copy situation
+	if ( typeof target === "boolean" ) {
+		deep = target;
+
+		// Skip the boolean and the target
+		target = arguments[ i ] || {};
+		i++;
+	}
+
+	// Handle case when target is a string or something (possible in deep copy)
+	if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+		target = {};
+	}
+
+	// Extend jQuery itself if only one argument is passed
+	if ( i === length ) {
+		target = this;
+		i--;
+	}
+
+	for ( ; i < length; i++ ) {
+
+		// Only deal with non-null/undefined values
+		if ( ( options = arguments[ i ] ) != null ) {
+
+			// Extend the base object
+			for ( name in options ) {
+				src = target[ name ];
+				copy = options[ name ];
+
+				// Prevent never-ending loop
+				if ( target === copy ) {
+					continue;
+				}
+
+				// Recurse if we're merging plain objects or arrays
+				if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+					( copyIsArray = jQuery.isArray( copy ) ) ) ) {
+
+					if ( copyIsArray ) {
+						copyIsArray = false;
+						clone = src && jQuery.isArray( src ) ? src : [];
+
+					} else {
+						clone = src && jQuery.isPlainObject( src ) ? src : {};
+					}
+
+					// Never move original objects, clone them
+					target[ name ] = jQuery.extend( deep, clone, copy );
+
+				// Don't bring in undefined values
+				} else if ( copy !== undefined ) {
+					target[ name ] = copy;
+				}
+			}
+		}
+	}
+
+	// Return the modified object
+	return target;
+};
+
+jQuery.extend( {
+
+	// Unique for each copy of jQuery on the page
+	expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+	// Assume jQuery is ready without the ready module
+	isReady: true,
+
+	error: function( msg ) {
+		throw new Error( msg );
+	},
+
+	noop: function() {},
+
+	isFunction: function( obj ) {
+		return jQuery.type( obj ) === "function";
+	},
+
+	isArray: Array.isArray,
+
+	isWindow: function( obj ) {
+		return obj != null && obj === obj.window;
+	},
+
+	isNumeric: function( obj ) {
+
+		// parseFloat NaNs numeric-cast false positives (null|true|false|"")
+		// ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+		// subtraction forces infinities to NaN
+		// adding 1 corrects loss of precision from parseFloat (#15100)
+		var realStringObj = obj && obj.toString();
+		return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
+	},
+
+	isPlainObject: function( obj ) {
+		var key;
+
+		// Not plain objects:
+		// - Any object or value whose internal [[Class]] property is not "[object Object]"
+		// - DOM nodes
+		// - window
+		if ( jQuery.type( obj ) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+			return false;
+		}
+
+		// Not own constructor property must be Object
+		if ( obj.constructor &&
+				!hasOwn.call( obj, "constructor" ) &&
+				!hasOwn.call( obj.constructor.prototype || {}, "isPrototypeOf" ) ) {
+			return false;
+		}
+
+		// Own properties are enumerated firstly, so to speed up,
+		// if last one is own, then all properties are own
+		for ( key in obj ) {}
+
+		return key === undefined || hasOwn.call( obj, key );
+	},
+
+	isEmptyObject: function( obj ) {
+		var name;
+		for ( name in obj ) {
+			return false;
+		}
+		return true;
+	},
+
+	type: function( obj ) {
+		if ( obj == null ) {
+			return obj + "";
+		}
+
+		// Support: Android<4.0, iOS<6 (functionish RegExp)
+		return typeof obj === "object" || typeof obj === "function" ?
+			class2type[ toString.call( obj ) ] || "object" :
+			typeof obj;
+	},
+
+	// Evaluates a script in a global context
+	globalEval: function( code ) {
+		var script,
+			indirect = eval;
+
+		code = jQuery.trim( code );
+
+		if ( code ) {
+
+			// If the code includes a valid, prologue position
+			// strict mode pragma, execute code by injecting a
+			// script tag into the document.
+			if ( code.indexOf( "use strict" ) === 1 ) {
+				script = document.createElement( "script" );
+				script.text = code;
+				document.head.appendChild( script ).parentNode.removeChild( script );
+			} else {
+
+				// Otherwise, avoid the DOM node creation, insertion
+				// and removal by using an indirect global eval
+
+				indirect( code );
+			}
+		}
+	},
+
+	// Convert dashed to camelCase; used by the css and data modules
+	// Support: IE9-11+
+	// Microsoft forgot to hump their vendor prefix (#9572)
+	camelCase: function( string ) {
+		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+	},
+
+	nodeName: function( elem, name ) {
+		return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+	},
+
+	each: function( obj, callback ) {
+		var length, i = 0;
+
+		if ( isArrayLike( obj ) ) {
+			length = obj.length;
+			for ( ; i < length; i++ ) {
+				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+					break;
+				}
+			}
+		} else {
+			for ( i in obj ) {
+				if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+					break;
+				}
+			}
+		}
+
+		return obj;
+	},
+
+	// Support: Android<4.1
+	trim: function( text ) {
+		return text == null ?
+			"" :
+			( text + "" ).replace( rtrim, "" );
+	},
+
+	// results is for internal usage only
+	makeArray: function( arr, results ) {
+		var ret = results || [];
+
+		if ( arr != null ) {
+			if ( isArrayLike( Object( arr ) ) ) {
+				jQuery.merge( ret,
+					typeof arr === "string" ?
+					[ arr ] : arr
+				);
+			} else {
+				push.call( ret, arr );
+			}
+		}
+
+		return ret;
+	},
+
+	inArray: function( elem, arr, i ) {
+		return arr == null ? -1 : indexOf.call( arr, elem, i );
+	},
+
+	merge: function( first, second ) {
+		var len = +second.length,
+			j = 0,
+			i = first.length;
+
+		for ( ; j < len; j++ ) {
+			first[ i++ ] = second[ j ];
+		}
+
+		first.length = i;
+
+		return first;
+	},
+
+	grep: function( elems, callback, invert ) {
+		var callbackInverse,
+			matches = [],
+			i = 0,
+			length = elems.length,
+			callbackExpect = !invert;
+
+		// Go through the array, only saving the items
+		// that pass the validator function
+		for ( ; i < length; i++ ) {
+			callbackInverse = !callback( elems[ i ], i );
+			if ( callbackInverse !== callbackExpect ) {
+				matches.push( elems[ i ] );
+			}
+		}
+
+		return matches;
+	},
+
+	// arg is for internal usage only
+	map: function( elems, callback, arg ) {
+		var length, value,
+			i = 0,
+			ret = [];
+
+		// Go through the array, translating each of the items to their new values
+		if ( isArrayLike( elems ) ) {
+			length = elems.length;
+			for ( ; i < length; i++ ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+
+		// Go through every key on the object,
+		} else {
+			for ( i in elems ) {
+				value = callback( elems[ i ], i, arg );
+
+				if ( value != null ) {
+					ret.push( value );
+				}
+			}
+		}
+
+		// Flatten any nested arrays
+		return concat.apply( [], ret );
+	},
+
+	// A global GUID counter for objects
+	guid: 1,
+
+	// Bind a function to a context, optionally partially applying any
+	// arguments.
+	proxy: function( fn, context ) {
+		var tmp, args, proxy;
+
+		if ( typeof context === "string" ) {
+			tmp = fn[ context ];
+			context = fn;
+			fn = tmp;
+		}
+
+		// Quick check to determine if target is callable, in the spec
+		// this throws a TypeError, but we will just return undefined.
+		if ( !jQuery.isFunction( fn ) ) {
+			return undefined;
+		}
+
+		// Simulated bind
+		args = slice.call( arguments, 2 );
+		proxy = function() {
+			return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+		};
+
+		// Set the guid of unique handler to the same of original handler, so it can be removed
+		proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+		return proxy;
+	},
+
+	now: Date.now,
+
+	// jQuery.support is not used in Core but other projects attach their
+	// properties to it so it needs to exist.
+	support: support
+} );
+
+// JSHint would error on this code due to the Symbol not being defined in ES5.
+// Defining this global in .jshintrc would create a danger of using the global
+// unguarded in another place, it seems safer to just disable JSHint for these
+// three lines.
+/* jshint ignore: start */
+if ( typeof Symbol === "function" ) {
+	jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+}
+/* jshint ignore: end */
+
+// Populate the class2type map
+jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+function( i, name ) {
+	class2type[ "[object " + name + "]" ] = name.toLowerCase();
+} );
+
+function isArrayLike( obj ) {
+
+	// Support: iOS 8.2 (not reproducible in simulator)
+	// `in` check used to prevent JIT error (gh-2145)
+	// hasOwn isn't used here due to false negatives
+	// regarding Nodelist length in IE
+	var length = !!obj && "length" in obj && obj.length,
+		type = jQuery.type( obj );
+
+	if ( type === "function" || jQuery.isWindow( obj ) ) {
+		return false;
+	}
+
+	return type === "array" || length === 0 ||
+		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.1
+ * http://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-10-17
+ */
+(function( window ) {
+
+var i,
+	support,
+	Expr,
+	getText,
+	isXML,
+	tokenize,
+	compile,
+	select,
+	outermostContext,
+	sortInput,
+	hasDuplicate,
+
+	// Local document vars
+	setDocument,
+	document,
+	docElem,
+	documentIsHTML,
+	rbuggyQSA,
+	rbuggyMatches,
+	matches,
+	contains,
+
+	// Instance-specific data
+	expando = "sizzle" + 1 * new Date(),
+	preferredDoc = window.document,
+	dirruns = 0,
+	done = 0,
+	classCache = createCache(),
+	tokenCache = createCache(),
+	compilerCache = createCache(),
+	sortOrder = function( a, b ) {
+		if ( a === b ) {
+			hasDuplicate = true;
+		}
+		return 0;
+	},
+
+	// General-purpose constants
+	MAX_NEGATIVE = 1 << 31,
+
+	// Instance methods
+	hasOwn = ({}).hasOwnProperty,
+	arr = [],
+	pop = arr.pop,
+	push_native = arr.push,
+	push = arr.push,
+	slice = arr.slice,
+	// Use a stripped-down indexOf as it's faster than native
+	// http://jsperf.com/thor-indexof-vs-for/5
+	indexOf = function( list, elem ) {
+		var i = 0,
+			len = list.length;
+		for ( ; i < len; i++ ) {
+			if ( list[i] === elem ) {
+				return i;
+			}
+		}
+		return -1;
+	},
+
+	booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+	// Regular expressions
+
+	// http://www.w3.org/TR/css3-selectors/#whitespace
+	whitespace = "[\\x20\\t\\r\\n\\f]",
+
+	// http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+	identifier = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+	// Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+	attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+		// Operator (capture 2)
+		"*([*^$|!~]?=)" + whitespace +
+		// "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+		"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+		"*\\]",
+
+	pseudos = ":(" + identifier + ")(?:\\((" +
+		// To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+		// 1. quoted (capture 3; capture 4 or capture 5)
+		"('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+		// 2. simple (capture 6)
+		"((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+		// 3. anything else (capture 2)
+		".*" +
+		")\\)|)",
+
+	// Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+	rwhitespace = new RegExp( whitespace + "+", "g" ),
+	rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+	rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+	rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+	rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+	rpseudo = new RegExp( pseudos ),
+	ridentifier = new RegExp( "^" + identifier + "$" ),
+
+	matchExpr = {
+		"ID": new RegExp( "^#(" + identifier + ")" ),
+		"CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+		"TAG": new RegExp( "^(" + identifier + "|[*])" ),
+		"ATTR": new RegExp( "^" + attributes ),
+		"PSEUDO": new RegExp( "^" + pseudos ),
+		"CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+			"*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+			"*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+		"bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+		// For use in libraries implementing .is()
+		// We use this for POS matching in `select`
+		"needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+			whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+	},
+
+	rinputs = /^(?:input|select|textarea|button)$/i,
+	rheader = /^h\d$/i,
+
+	rnative = /^[^{]+\{\s*\[native \w/,
+
+	// Easily-parseable/retrievable ID or TAG or CLASS selectors
+	rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+	rsibling = /[+~]/,
+	rescape = /'|\\/g,
+
+	// CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+	runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+	funescape = function( _, escaped, escapedWhitespace ) {
+		var high = "0x" + escaped - 0x10000;
+		// NaN means non-codepoint
+		// Support: Firefox<24
+		// Workaround erroneous numeric interpretation of +"0x"
+		return high !== high || escapedWhitespace ?
+			escaped :
+			high < 0 ?
+				// BMP codepoint
+				String.fromCharCode( high + 0x10000 ) :
+				// Supplemental Plane codepoint (surrogate pair)
+				String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+	},
+
+	// Used for iframes
+	// See setDocument()
+	// Removing the function wrapper causes a "Permission Denied"
+	// error in IE
+	unloadHandler = function() {
+		setDocument();
+	};
+
+// Optimize for push.apply( _, NodeList )
+try {
+	push.apply(
+		(arr = slice.call( preferredDoc.childNodes )),
+		preferredDoc.childNodes
+	);
+	// Support: Android<4.0
+	// Detect silently failing push.apply
+	arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+	push = { apply: arr.length ?
+
+		// Leverage slice if possible
+		function( target, els ) {
+			push_native.apply( target, slice.call(els) );
+		} :
+
+		// Support: IE<9
+		// Otherwise append directly
+		function( target, els ) {
+			var j = target.length,
+				i = 0;
+			// Can't trust NodeList.length
+			while ( (target[j++] = els[i++]) ) {}
+			target.length = j - 1;
+		}
+	};
+}
+
+function Sizzle( selector, context, results, seed ) {
+	var m, i, elem, nid, nidselect, match, groups, newSelector,
+		newContext = context && context.ownerDocument,
+
+		// nodeType defaults to 9, since context defaults to document
+		nodeType = context ? context.nodeType : 9;
+
+	results = results || [];
+
+	// Return early from calls with invalid selector or context
+	if ( typeof selector !== "string" || !selector ||
+		nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+		return results;
+	}
+
+	// Try to shortcut find operations (as opposed to filters) in HTML documents
+	if ( !seed ) {
+
+		if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+			setDocument( context );
+		}
+		context = context || document;
+
+		if ( documentIsHTML ) {
+
+			// If the selector is sufficiently simple, try using a "get*By*" DOM method
+			// (excepting DocumentFragment context, where the methods don't exist)
+			if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+				// ID selector
+				if ( (m = match[1]) ) {
+
+					// Document context
+					if ( nodeType === 9 ) {
+						if ( (elem = context.getElementById( m )) ) {
+
+							// Support: IE, Opera, Webkit
+							// TODO: identify versions
+							// getElementById can match elements by name instead of ID
+							if ( elem.id === m ) {
+								results.push( elem );
+								return results;
+							}
+						} else {
+							return results;
+						}
+
+					// Element context
+					} else {
+
+						// Support: IE, Opera, Webkit
+						// TODO: identify versions
+						// getElementById can match elements by name instead of ID
+						if ( newContext && (elem = newContext.getElementById( m )) &&
+							contains( context, elem ) &&
+							elem.id === m ) {
+
+							results.push( elem );
+							return results;
+						}
+					}
+
+				// Type selector
+				} else if ( match[2] ) {
+					push.apply( results, context.getElementsByTagName( selector ) );
+					return results;
+
+				// Class selector
+				} else if ( (m = match[3]) && support.getElementsByClassName &&
+					context.getElementsByClassName ) {
+
+					push.apply( results, context.getElementsByClassName( m ) );
+					return results;
+				}
+			}
+
+			// Take advantage of querySelectorAll
+			if ( support.qsa &&
+				!compilerCache[ selector + " " ] &&
+				(!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+
+				if ( nodeType !== 1 ) {
+					newContext = context;
+					newSelector = selector;
+
+				// qSA looks outside Element context, which is not what we want
+				// Thanks to Andrew Dupont for this workaround technique
+				// Support: IE <=8
+				// Exclude object elements
+				} else if ( context.nodeName.toLowerCase() !== "object" ) {
+
+					// Capture the context ID, setting it first if necessary
+					if ( (nid = context.getAttribute( "id" )) ) {
+						nid = nid.replace( rescape, "\\$&" );
+					} else {
+						context.setAttribute( "id", (nid = expando) );
+					}
+
+					// Prefix every selector in the list
+					groups = tokenize( selector );
+					i = groups.length;
+					nidselect = ridentifier.test( nid ) ? "#" + nid : "[id='" + nid + "']";
+					while ( i-- ) {
+						groups[i] = nidselect + " " + toSelector( groups[i] );
+					}
+					newSelector = groups.join( "," );
+
+					// Expand context for sibling selectors
+					newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+						context;
+				}
+
+				if ( newSelector ) {
+					try {
+						push.apply( results,
+							newContext.querySelectorAll( newSelector )
+						);
+						return results;
+					} catch ( qsaError ) {
+					} finally {
+						if ( nid === expando ) {
+							context.removeAttribute( "id" );
+						}
+					}
+				}
+			}
+		}
+	}
+
+	// All others
+	return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {function(string, object)} Returns the Object data after storing it on itself with
+ *	property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ *	deleting the oldest entry
+ */
+function createCache() {
+	var keys = [];
+
+	function cache( key, value ) {
+		// Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+		if ( keys.push( key + " " ) > Expr.cacheLength ) {
+			// Only keep the most recent entries
+			delete cache[ keys.shift() ];
+		}
+		return (cache[ key + " " ] = value);
+	}
+	return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+	fn[ expando ] = true;
+	return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+	var div = document.createElement("div");
+
+	try {
+		return !!fn( div );
+	} catch (e) {
+		return false;
+	} finally {
+		// Remove from its parent by default
+		if ( div.parentNode ) {
+			div.parentNode.removeChild( div );
+		}
+		// release memory in IE
+		div = null;
+	}
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+	var arr = attrs.split("|"),
+		i = arr.length;
+
+	while ( i-- ) {
+		Expr.attrHandle[ arr[i] ] = handler;
+	}
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+	var cur = b && a,
+		diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+			( ~b.sourceIndex || MAX_NEGATIVE ) -
+			( ~a.sourceIndex || MAX_NEGATIVE );
+
+	// Use IE sourceIndex if available on both nodes
+	if ( diff ) {
+		return diff;
+	}
+
+	// Check if b follows a
+	if ( cur ) {
+		while ( (cur = cur.nextSibling) ) {
+			if ( cur === b ) {
+				return -1;
+			}
+		}
+	}
+
+	return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return name === "input" && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+	return function( elem ) {
+		var name = elem.nodeName.toLowerCase();
+		return (name === "input" || name === "button") && elem.type === type;
+	};
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+	return markFunction(function( argument ) {
+		argument = +argument;
+		return markFunction(function( seed, matches ) {
+			var j,
+				matchIndexes = fn( [], seed.length, argument ),
+				i = matchIndexes.length;
+
+			// Match elements found at the specified indexes
+			while ( i-- ) {
+				if ( seed[ (j = matchIndexes[i]) ] ) {
+					seed[j] = !(matches[j] = seed[j]);
+				}
+			}
+		});
+	});
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+	return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+	// documentElement is verified for cases where it doesn't yet exist
+	// (such as loading iframes in IE - #4833)
+	var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+	return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+	var hasCompare, parent,
+		doc = node ? node.ownerDocument || node : preferredDoc;
+
+	// Return early if doc is invalid or already selected
+	if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+		return document;
+	}
+
+	// Update global variables
+	document = doc;
+	docElem = document.documentElement;
+	documentIsHTML = !isXML( document );
+
+	// Support: IE 9-11, Edge
+	// Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+	if ( (parent = document.defaultView) && parent.top !== parent ) {
+		// Support: IE 11
+		if ( parent.addEventListener ) {
+			parent.addEventListener( "unload", unloadHandler, false );
+
+		// Support: IE 9 - 10 only
+		} else if ( parent.attachEvent ) {
+			parent.attachEvent( "onunload", unloadHandler );
+		}
+	}
+
+	/* Attributes
+	---------------------------------------------------------------------- */
+
+	// Support: IE<8
+	// Verify that getAttribute really returns attributes and not properties
+	// (excepting IE8 booleans)
+	support.attributes = assert(function( div ) {
+		div.className = "i";
+		return !div.getAttribute("className");
+	});
+
+	/* getElement(s)By*
+	---------------------------------------------------------------------- */
+
+	// Check if getElementsByTagName("*") returns only elements
+	support.getElementsByTagName = assert(function( div ) {
+		div.appendChild( document.createComment("") );
+		return !div.getElementsByTagName("*").length;
+	});
+
+	// Support: IE<9
+	support.getElementsByClassName = rnative.test( document.getElementsByClassName );
+
+	// Support: IE<10
+	// Check if getElementById returns elements by name
+	// The broken getElementById methods don't pick up programatically-set names,
+	// so use a roundabout getElementsByName test
+	support.getById = assert(function( div ) {
+		docElem.appendChild( div ).id = expando;
+		return !document.getElementsByName || !document.getElementsByName( expando ).length;
+	});
+
+	// ID find and filter
+	if ( support.getById ) {
+		Expr.find["ID"] = function( id, context ) {
+			if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+				var m = context.getElementById( id );
+				return m ? [ m ] : [];
+			}
+		};
+		Expr.filter["ID"] = function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				return elem.getAttribute("id") === attrId;
+			};
+		};
+	} else {
+		// Support: IE6/7
+		// getElementById is not reliable as a find shortcut
+		delete Expr.find["ID"];
+
+		Expr.filter["ID"] =  function( id ) {
+			var attrId = id.replace( runescape, funescape );
+			return function( elem ) {
+				var node = typeof elem.getAttributeNode !== "undefined" &&
+					elem.getAttributeNode("id");
+				return node && node.value === attrId;
+			};
+		};
+	}
+
+	// Tag
+	Expr.find["TAG"] = support.getElementsByTagName ?
+		function( tag, context ) {
+			if ( typeof context.getElementsByTagName !== "undefined" ) {
+				return context.getElementsByTagName( tag );
+
+			// DocumentFragment nodes don't have gEBTN
+			} else if ( support.qsa ) {
+				return context.querySelectorAll( tag );
+			}
+		} :
+
+		function( tag, context ) {
+			var elem,
+				tmp = [],
+				i = 0,
+				// By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+				results = context.getElementsByTagName( tag );
+
+			// Filter out possible comments
+			if ( tag === "*" ) {
+				while ( (elem = results[i++]) ) {
+					if ( elem.nodeType === 1 ) {
+						tmp.push( elem );
+					}
+				}
+
+				return tmp;
+			}
+			return results;
+		};
+
+	// Class
+	Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+		if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
+			return context.getElementsByClassName( className );
+		}
+	};
+
+	/* QSA/matchesSelector
+	---------------------------------------------------------------------- */
+
+	// QSA and matchesSelector support
+
+	// matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+	rbuggyMatches = [];
+
+	// qSa(:focus) reports false when true (Chrome 21)
+	// We allow this because of a bug in IE8/9 that throws an error
+	// whenever `document.activeElement` is accessed on an iframe
+	// So, we allow :focus to pass through QSA all the time to avoid the IE error
+	// See http://bugs.jquery.com/ticket/13378
+	rbuggyQSA = [];
+
+	if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
+		// Build QSA regex
+		// Regex strategy adopted from Diego Perini
+		assert(function( div ) {
+			// Select is set to empty string on purpose
+			// This is to test IE's treatment of not explicitly
+			// setting a boolean content attribute,
+			// since its presence should be enough
+			// http://bugs.jquery.com/ticket/12359
+			docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+				"<select id='" + expando + "-\r\\' msallowcapture=''>" +
+				"<option selected=''></option></select>";
+
+			// Support: IE8, Opera 11-12.16
+			// Nothing should be selected when empty strings follow ^= or $= or *=
+			// The test attribute must be unknown in Opera but "safe" for WinRT
+			// http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+			if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+				rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+			}
+
+			// Support: IE8
+			// Boolean attributes and "value" are not treated correctly
+			if ( !div.querySelectorAll("[selected]").length ) {
+				rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+			}
+
+			// Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+			if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+				rbuggyQSA.push("~=");
+			}
+
+			// Webkit/Opera - :checked should return selected option elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":checked").length ) {
+				rbuggyQSA.push(":checked");
+			}
+
+			// Support: Safari 8+, iOS 8+
+			// https://bugs.webkit.org/show_bug.cgi?id=136851
+			// In-page `selector#id sibing-combinator selector` fails
+			if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+				rbuggyQSA.push(".#.+[+~]");
+			}
+		});
+
+		assert(function( div ) {
+			// Support: Windows 8 Native Apps
+			// The type and name attributes are restricted during .innerHTML assignment
+			var input = document.createElement("input");
+			input.setAttribute( "type", "hidden" );
+			div.appendChild( input ).setAttribute( "name", "D" );
+
+			// Support: IE8
+			// Enforce case-sensitivity of name attribute
+			if ( div.querySelectorAll("[name=d]").length ) {
+				rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+			}
+
+			// FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+			// IE8 throws error here and will not see later tests
+			if ( !div.querySelectorAll(":enabled").length ) {
+				rbuggyQSA.push( ":enabled", ":disabled" );
+			}
+
+			// Opera 10-11 does not throw on post-comma invalid pseudos
+			div.querySelectorAll("*,:x");
+			rbuggyQSA.push(",.*:");
+		});
+	}
+
+	if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+		docElem.webkitMatchesSelector ||
+		docElem.mozMatchesSelector ||
+		docElem.oMatchesSelector ||
+		docElem.msMatchesSelector) )) ) {
+
+		assert(function( div ) {
+			// Check to see if it's possible to do matchesSelector
+			// on a disconnected node (IE 9)
+			support.disconnectedMatch = matches.call( div, "div" );
+
+			// This should fail with an exception
+			// Gecko does not error, returns false instead
+			matches.call( div, "[s!='']:x" );
+			rbuggyMatches.push( "!=", pseudos );
+		});
+	}
+
+	rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+	rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+	/* Contains
+	---------------------------------------------------------------------- */
+	hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+	// Element contains another
+	// Purposefully self-exclusive
+	// As in, an element does not contain itself
+	contains = hasCompare || rnative.test( docElem.contains ) ?
+		function( a, b ) {
+			var adown = a.nodeType === 9 ? a.documentElement : a,
+				bup = b && b.parentNode;
+			return a === bup || !!( bup && bup.nodeType === 1 && (
+				adown.contains ?
+					adown.contains( bup ) :
+					a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+			));
+		} :
+		function( a, b ) {
+			if ( b ) {
+				while ( (b = b.parentNode) ) {
+					if ( b === a ) {
+						return true;
+					}
+				}
+			}
+			return false;
+		};
+
+	/* Sorting
+	---------------------------------------------------------------------- */
+
+	// Document order sorting
+	sortOrder = hasCompare ?
+	function( a, b ) {
+
+		// Flag for duplicate removal
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		// Sort on method existence if only one input has compareDocumentPosition
+		var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+		if ( compare ) {
+			return compare;
+		}
+
+		// Calculate position if both inputs belong to the same document
+		compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+			a.compareDocumentPosition( b ) :
+
+			// Otherwise we know they are disconnected
+			1;
+
+		// Disconnected nodes
+		if ( compare & 1 ||
+			(!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+			// Choose the first element that is related to our preferred document
+			if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+				return -1;
+			}
+			if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+				return 1;
+			}
+
+			// Maintain original order
+			return sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+		}
+
+		return compare & 4 ? -1 : 1;
+	} :
+	function( a, b ) {
+		// Exit early if the nodes are identical
+		if ( a === b ) {
+			hasDuplicate = true;
+			return 0;
+		}
+
+		var cur,
+			i = 0,
+			aup = a.parentNode,
+			bup = b.parentNode,
+			ap = [ a ],
+			bp = [ b ];
+
+		// Parentless nodes are either documents or disconnected
+		if ( !aup || !bup ) {
+			return a === document ? -1 :
+				b === document ? 1 :
+				aup ? -1 :
+				bup ? 1 :
+				sortInput ?
+				( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+				0;
+
+		// If the nodes are siblings, we can do a quick check
+		} else if ( aup === bup ) {
+			return siblingCheck( a, b );
+		}
+
+		// Otherwise we need full lists of their ancestors for comparison
+		cur = a;
+		while ( (cur = cur.parentNode) ) {
+			ap.unshift( cur );
+		}
+		cur = b;
+		while ( (cur = cur.parentNode) ) {
+			bp.unshift( cur );
+		}
+
+		// Walk down the tree looking for a discrepancy
+		while ( ap[i] === bp[i] ) {
+			i++;
+		}
+
+		return i ?
+			// Do a sibling check if the nodes have a common ancestor
+			siblingCheck( ap[i], bp[i] ) :
+
+			// Otherwise nodes in our document sort first
+			ap[i] === preferredDoc ? -1 :
+			bp[i] === preferredDoc ? 1 :
+			0;
+	};
+
+	return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+	return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	// Make sure that attribute selectors are quoted
+	expr = expr.replace( rattributeQuotes, "='$1']" );
+
+	if ( support.matchesSelector && documentIsHTML &&
+		!compilerCache[ expr + " " ] &&
+		( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+		( !rbuggyQSA     || !rbuggyQSA.test( expr ) ) ) {
+
+		try {
+			var ret = matches.call( elem, expr );
+
+			// IE 9's matchesSelector returns false on disconnected nodes
+			if ( ret || support.disconnectedMatch ||
+					// As well, disconnected nodes are said to be in a document
+					// fragment in IE 9
+					elem.document && elem.document.nodeType !== 11 ) {
+				return ret;
+			}
+		} catch (e) {}
+	}
+
+	return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+	// Set document vars if needed
+	if ( ( context.ownerDocument || context ) !== document ) {
+		setDocument( context );
+	}
+	return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+	// Set document vars if needed
+	if ( ( elem.ownerDocument || elem ) !== document ) {
+		setDocument( elem );
+	}
+
+	var fn = Expr.attrHandle[ name.toLowerCase() ],
+		// Don't get fooled by Object.prototype properties (jQuery #13807)
+		val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+			fn( elem, name, !documentIsHTML ) :
+			undefined;
+
+	return val !== undefined ?
+		val :
+		support.attributes || !documentIsHTML ?
+			elem.getAttribute( name ) :
+			(val = elem.getAttributeNode(name)) && val.specified ?
+				val.value :
+				null;
+};
+
+Sizzle.error = function( msg ) {
+	throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+	var elem,
+		duplicates = [],
+		j = 0,
+		i = 0;
+
+	// Unless we *know* we can detect duplicates, assume their presence
+	hasDuplicate = !support.detectDuplicates;
+	sortInput = !support.sortStable && results.slice( 0 );
+	results.sort( sortOrder );
+
+	if ( hasDuplicate ) {
+		while ( (elem = results[i++]) ) {
+			if ( elem === results[ i ] ) {
+				j = duplicates.push( i );
+			}
+		}
+		while ( j-- ) {
+			results.splice( duplicates[ j ], 1 );
+		}
+	}
+
+	// Clear input after sorting to release objects
+	// See https://github.com/jquery/sizzle/pull/225
+	sortInput = null;
+
+	return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+	var node,
+		ret = "",
+		i = 0,
+		nodeType = elem.nodeType;
+
+	if ( !nodeType ) {
+		// If no nodeType, this is expected to be an array
+		while ( (node = elem[i++]) ) {
+			// Do not traverse comment nodes
+			ret += getText( node );
+		}
+	} else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+		// Use textContent for elements
+		// innerText usage removed for consistency of new lines (jQuery #11153)
+		if ( typeof elem.textContent === "string" ) {
+			return elem.textContent;
+		} else {
+			// Traverse its children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				ret += getText( elem );
+			}
+		}
+	} else if ( nodeType === 3 || nodeType === 4 ) {
+		return elem.nodeValue;
+	}
+	// Do not include comment or processing instruction nodes
+
+	return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+	// Can be adjusted by the user
+	cacheLength: 50,
+
+	createPseudo: markFunction,
+
+	match: matchExpr,
+
+	attrHandle: {},
+
+	find: {},
+
+	relative: {
+		">": { dir: "parentNode", first: true },
+		" ": { dir: "parentNode" },
+		"+": { dir: "previousSibling", first: true },
+		"~": { dir: "previousSibling" }
+	},
+
+	preFilter: {
+		"ATTR": function( match ) {
+			match[1] = match[1].replace( runescape, funescape );
+
+			// Move the given value to match[3] whether quoted or unquoted
+			match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+			if ( match[2] === "~=" ) {
+				match[3] = " " + match[3] + " ";
+			}
+
+			return match.slice( 0, 4 );
+		},
+
+		"CHILD": function( match ) {
+			/* matches from matchExpr["CHILD"]
+				1 type (only|nth|...)
+				2 what (child|of-type)
+				3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+				4 xn-component of xn+y argument ([+-]?\d*n|)
+				5 sign of xn-component
+				6 x of xn-component
+				7 sign of y-component
+				8 y of y-component
+			*/
+			match[1] = match[1].toLowerCase();
+
+			if ( match[1].slice( 0, 3 ) === "nth" ) {
+				// nth-* requires argument
+				if ( !match[3] ) {
+					Sizzle.error( match[0] );
+				}
+
+				// numeric x and y parameters for Expr.filter.CHILD
+				// remember that false/true cast respectively to 0/1
+				match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+				match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+			// other types prohibit arguments
+			} else if ( match[3] ) {
+				Sizzle.error( match[0] );
+			}
+
+			return match;
+		},
+
+		"PSEUDO": function( match ) {
+			var excess,
+				unquoted = !match[6] && match[2];
+
+			if ( matchExpr["CHILD"].test( match[0] ) ) {
+				return null;
+			}
+
+			// Accept quoted arguments as-is
+			if ( match[3] ) {
+				match[2] = match[4] || match[5] || "";
+
+			// Strip excess characters from unquoted arguments
+			} else if ( unquoted && rpseudo.test( unquoted ) &&
+				// Get excess from tokenize (recursively)
+				(excess = tokenize( unquoted, true )) &&
+				// advance to the next closing parenthesis
+				(excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+				// excess is a negative index
+				match[0] = match[0].slice( 0, excess );
+				match[2] = unquoted.slice( 0, excess );
+			}
+
+			// Return only captures needed by the pseudo filter method (type and argument)
+			return match.slice( 0, 3 );
+		}
+	},
+
+	filter: {
+
+		"TAG": function( nodeNameSelector ) {
+			var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+			return nodeNameSelector === "*" ?
+				function() { return true; } :
+				function( elem ) {
+					return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+				};
+		},
+
+		"CLASS": function( className ) {
+			var pattern = classCache[ className + " " ];
+
+			return pattern ||
+				(pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+				classCache( className, function( elem ) {
+					return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+				});
+		},
+
+		"ATTR": function( name, operator, check ) {
+			return function( elem ) {
+				var result = Sizzle.attr( elem, name );
+
+				if ( result == null ) {
+					return operator === "!=";
+				}
+				if ( !operator ) {
+					return true;
+				}
+
+				result += "";
+
+				return operator === "=" ? result === check :
+					operator === "!=" ? result !== check :
+					operator === "^=" ? check && result.indexOf( check ) === 0 :
+					operator === "*=" ? check && result.indexOf( check ) > -1 :
+					operator === "$=" ? check && result.slice( -check.length ) === check :
+					operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+					operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+					false;
+			};
+		},
+
+		"CHILD": function( type, what, argument, first, last ) {
+			var simple = type.slice( 0, 3 ) !== "nth",
+				forward = type.slice( -4 ) !== "last",
+				ofType = what === "of-type";
+
+			return first === 1 && last === 0 ?
+
+				// Shortcut for :nth-*(n)
+				function( elem ) {
+					return !!elem.parentNode;
+				} :
+
+				function( elem, context, xml ) {
+					var cache, uniqueCache, outerCache, node, nodeIndex, start,
+						dir = simple !== forward ? "nextSibling" : "previousSibling",
+						parent = elem.parentNode,
+						name = ofType && elem.nodeName.toLowerCase(),
+						useCache = !xml && !ofType,
+						diff = false;
+
+					if ( parent ) {
+
+						// :(first|last|only)-(child|of-type)
+						if ( simple ) {
+							while ( dir ) {
+								node = elem;
+								while ( (node = node[ dir ]) ) {
+									if ( ofType ?
+										node.nodeName.toLowerCase() === name :
+										node.nodeType === 1 ) {
+
+										return false;
+									}
+								}
+								// Reverse direction for :only-* (if we haven't yet done so)
+								start = dir = type === "only" && !start && "nextSibling";
+							}
+							return true;
+						}
+
+						start = [ forward ? parent.firstChild : parent.lastChild ];
+
+						// non-xml :nth-child(...) stores cache data on `parent`
+						if ( forward && useCache ) {
+
+							// Seek `elem` from a previously-cached index
+
+							// ...in a gzip-friendly way
+							node = parent;
+							outerCache = node[ expando ] || (node[ expando ] = {});
+
+							// Support: IE <9 only
+							// Defend against cloned attroperties (jQuery gh-1709)
+							uniqueCache = outerCache[ node.uniqueID ] ||
+								(outerCache[ node.uniqueID ] = {});
+
+							cache = uniqueCache[ type ] || [];
+							nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+							diff = nodeIndex && cache[ 2 ];
+							node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+							while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+								// Fallback to seeking `elem` from the start
+								(diff = nodeIndex = 0) || start.pop()) ) {
+
+								// When found, cache indexes on `parent` and break
+								if ( node.nodeType === 1 && ++diff && node === elem ) {
+									uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
+									break;
+								}
+							}
+
+						} else {
+							// Use previously-cached element index if available
+							if ( useCache ) {
+								// ...in a gzip-friendly way
+								node = elem;
+								outerCache = node[ expando ] || (node[ expando ] = {});
+
+								// Support: IE <9 only
+								// Defend against cloned attroperties (jQuery gh-1709)
+								uniqueCache = outerCache[ node.uniqueID ] ||
+									(outerCache[ node.uniqueID ] = {});
+
+								cache = uniqueCache[ type ] || [];
+								nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+								diff = nodeIndex;
+							}
+
+							// xml :nth-child(...)
+							// or :nth-last-child(...) or :nth(-last)?-of-type(...)
+							if ( diff === false ) {
+								// Use the same loop as above to seek `elem` from the start
+								while ( (node = ++nodeIndex && node && node[ dir ] ||
+									(diff = nodeIndex = 0) || start.pop()) ) {
+
+									if ( ( ofType ?
+										node.nodeName.toLowerCase() === name :
+										node.nodeType === 1 ) &&
+										++diff ) {
+
+										// Cache the index of each encountered element
+										if ( useCache ) {
+											outerCache = node[ expando ] || (node[ expando ] = {});
+
+											// Support: IE <9 only
+											// Defend against cloned attroperties (jQuery gh-1709)
+											uniqueCache = outerCache[ node.uniqueID ] ||
+												(outerCache[ node.uniqueID ] = {});
+
+											uniqueCache[ type ] = [ dirruns, diff ];
+										}
+
+										if ( node === elem ) {
+											break;
+										}
+									}
+								}
+							}
+						}
+
+						// Incorporate the offset, then check against cycle size
+						diff -= last;
+						return diff === first || ( diff % first === 0 && diff / first >= 0 );
+					}
+				};
+		},
+
+		"PSEUDO": function( pseudo, argument ) {
+			// pseudo-class names are case-insensitive
+			// http://www.w3.org/TR/selectors/#pseudo-classes
+			// Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+			// Remember that setFilters inherits from pseudos
+			var args,
+				fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+					Sizzle.error( "unsupported pseudo: " + pseudo );
+
+			// The user may use createPseudo to indicate that
+			// arguments are needed to create the filter function
+			// just as Sizzle does
+			if ( fn[ expando ] ) {
+				return fn( argument );
+			}
+
+			// But maintain support for old signatures
+			if ( fn.length > 1 ) {
+				args = [ pseudo, pseudo, "", argument ];
+				return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+					markFunction(function( seed, matches ) {
+						var idx,
+							matched = fn( seed, argument ),
+							i = matched.length;
+						while ( i-- ) {
+							idx = indexOf( seed, matched[i] );
+							seed[ idx ] = !( matches[ idx ] = matched[i] );
+						}
+					}) :
+					function( elem ) {
+						return fn( elem, 0, args );
+					};
+			}
+
+			return fn;
+		}
+	},
+
+	pseudos: {
+		// Potentially complex pseudos
+		"not": markFunction(function( selector ) {
+			// Trim the selector passed to compile
+			// to avoid treating leading and trailing
+			// spaces as combinators
+			var input = [],
+				results = [],
+				matcher = compile( selector.replace( rtrim, "$1" ) );
+
+			return matcher[ expando ] ?
+				markFunction(function( seed, matches, context, xml ) {
+					var elem,
+						unmatched = matcher( seed, null, xml, [] ),
+						i = seed.length;
+
+					// Match elements unmatched by `matcher`
+					while ( i-- ) {
+						if ( (elem = unmatched[i]) ) {
+							seed[i] = !(matches[i] = elem);
+						}
+					}
+				}) :
+				function( elem, context, xml ) {
+					input[0] = elem;
+					matcher( input, null, xml, results );
+					// Don't keep the element (issue #299)
+					input[0] = null;
+					return !results.pop();
+				};
+		}),
+
+		"has": markFunction(function( selector ) {
+			return function( elem ) {
+				return Sizzle( selector, elem ).length > 0;
+			};
+		}),
+
+		"contains": markFunction(function( text ) {
+			text = text.replace( runescape, funescape );
+			return function( elem ) {
+				return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+			};
+		}),
+
+		// "Whether an element is represented by a :lang() selector
+		// is based solely on the element's language value
+		// being equal to the identifier C,
+		// or beginning with the identifier C immediately followed by "-".
+		// The matching of C against the element's language value is performed case-insensitively.
+		// The identifier C does not have to be a valid language name."
+		// http://www.w3.org/TR/selectors/#lang-pseudo
+		"lang": markFunction( function( lang ) {
+			// lang value must be a valid identifier
+			if ( !ridentifier.test(lang || "") ) {
+				Sizzle.error( "unsupported lang: " + lang );
+			}
+			lang = lang.replace( runescape, funescape ).toLowerCase();
+			return function( elem ) {
+				var elemLang;
+				do {
+					if ( (elemLang = documentIsHTML ?
+						elem.lang :
+						elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+						elemLang = elemLang.toLowerCase();
+						return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+					}
+				} while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+				return false;
+			};
+		}),
+
+		// Miscellaneous
+		"target": function( elem ) {
+			var hash = window.location && window.location.hash;
+			return hash && hash.slice( 1 ) === elem.id;
+		},
+
+		"root": function( elem ) {
+			return elem === docElem;
+		},
+
+		"focus": function( elem ) {
+			return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+		},
+
+		// Boolean properties
+		"enabled": function( elem ) {
+			return elem.disabled === false;
+		},
+
+		"disabled": function( elem ) {
+			return elem.disabled === true;
+		},
+
+		"checked": function( elem ) {
+			// In CSS3, :checked should return both checked and selected elements
+			// http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+			var nodeName = elem.nodeName.toLowerCase();
+			return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+		},
+
+		"selected": function( elem ) {
+			// Accessing this property makes selected-by-default
+			// options in Safari work properly
+			if ( elem.parentNode ) {
+				elem.parentNode.selectedIndex;
+			}
+
+			return elem.selected === true;
+		},
+
+		// Contents
+		"empty": function( elem ) {
+			// http://www.w3.org/TR/selectors/#empty-pseudo
+			// :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+			//   but not by others (comment: 8; processing instruction: 7; etc.)
+			// nodeType < 6 works because attributes (2) do not appear as children
+			for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+				if ( elem.nodeType < 6 ) {
+					return false;
+				}
+			}
+			return true;
+		},
+
+		"parent": function( elem ) {
+			return !Expr.pseudos["empty"]( elem );
+		},
+
+		// Element/input types
+		"header": function( elem ) {
+			return rheader.test( elem.nodeName );
+		},
+
+		"input": function( elem ) {
+			return rinputs.test( elem.nodeName );
+		},
+
+		"button": function( elem ) {
+			var name = elem.nodeName.toLowerCase();
+			return name === "input" && elem.type === "button" || name === "button";
+		},
+
+		"text": function( elem ) {
+			var attr;
+			return elem.nodeName.toLowerCase() === "input" &&
+				elem.type === "text" &&
+
+				// Support: IE<8
+				// New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+				( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+		},
+
+		// Position-in-collection
+		"first": createPositionalPseudo(function() {
+			return [ 0 ];
+		}),
+
+		"last": createPositionalPseudo(function( matchIndexes, length ) {
+			return [ length - 1 ];
+		}),
+
+		"eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			return [ argument < 0 ? argument + length : argument ];
+		}),
+
+		"even": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 0;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"odd": createPositionalPseudo(function( matchIndexes, length ) {
+			var i = 1;
+			for ( ; i < length; i += 2 ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; --i >= 0; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		}),
+
+		"gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+			var i = argument < 0 ? argument + length : argument;
+			for ( ; ++i < length; ) {
+				matchIndexes.push( i );
+			}
+			return matchIndexes;
+		})
+	}
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+	Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+	Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+	var matched, match, tokens, type,
+		soFar, groups, preFilters,
+		cached = tokenCache[ selector + " " ];
+
+	if ( cached ) {
+		return parseOnly ? 0 : cached.slice( 0 );
+	}
+
+	soFar = selector;
+	groups = [];
+	preFilters = Expr.preFilter;
+
+	while ( soFar ) {
+
+		// Comma and first run
+		if ( !matched || (match = rcomma.exec( soFar )) ) {
+			if ( match ) {
+				// Don't consume trailing commas as valid
+				soFar = soFar.slice( match[0].length ) || soFar;
+			}
+			groups.push( (tokens = []) );
+		}
+
+		matched = false;
+
+		// Combinators
+		if ( (match = rcombinators.exec( soFar )) ) {
+			matched = match.shift();
+			tokens.push({
+				value: matched,
+				// Cast descendant combinators to space
+				type: match[0].replace( rtrim, " " )
+			});
+			soFar = soFar.slice( matched.length );
+		}
+
+		// Filters
+		for ( type in Expr.filter ) {
+			if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+				(match = preFilters[ type ]( match ))) ) {
+				matched = match.shift();
+				tokens.push({
+					value: matched,
+					type: type,
+					matches: match
+				});
+				soFar = soFar.slice( matched.length );
+			}
+		}
+
+		if ( !matched ) {
+			break;
+		}
+	}
+
+	// Return the length of the invalid excess
+	// if we're just parsing
+	// Otherwise, throw an error or return tokens
+	return parseOnly ?
+		soFar.length :
+		soFar ?
+			Sizzle.error( selector ) :
+			// Cache the tokens
+			tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+	var i = 0,
+		len = tokens.length,
+		selector = "";
+	for ( ; i < len; i++ ) {
+		selector += tokens[i].value;
+	}
+	return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+	var dir = combinator.dir,
+		checkNonElements = base && dir === "parentNode",
+		doneName = done++;
+
+	return combinator.first ?
+		// Check against closest ancestor/preceding element
+		function( elem, context, xml ) {
+			while ( (elem = elem[ dir ]) ) {
+				if ( elem.nodeType === 1 || checkNonElements ) {
+					return matcher( elem, context, xml );
+				}
+			}
+		} :
+
+		// Check against all ancestor/preceding elements
+		function( elem, context, xml ) {
+			var oldCache, uniqueCache, outerCache,
+				newCache = [ dirruns, doneName ];
+
+			// We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
+			if ( xml ) {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						if ( matcher( elem, context, xml ) ) {
+							return true;
+						}
+					}
+				}
+			} else {
+				while ( (elem = elem[ dir ]) ) {
+					if ( elem.nodeType === 1 || checkNonElements ) {
+						outerCache = elem[ expando ] || (elem[ expando ] = {});
+
+						// Support: IE <9 only
+						// Defend against cloned attroperties (jQuery gh-1709)
+						uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
+
+						if ( (oldCache = uniqueCache[ dir ]) &&
+							oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+							// Assign to newCache so results back-propagate to previous elements
+							return (newCache[ 2 ] = oldCache[ 2 ]);
+						} else {
+							// Reuse newcache so results back-propagate to previous elements
+							uniqueCache[ dir ] = newCache;
+
+							// A match means we're done; a fail means we have to keep checking
+							if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+								return true;
+							}
+						}
+					}
+				}
+			}
+		};
+}
+
+function elementMatcher( matchers ) {
+	return matchers.length > 1 ?
+		function( elem, context, xml ) {
+			var i = matchers.length;
+			while ( i-- ) {
+				if ( !matchers[i]( elem, context, xml ) ) {
+					return false;
+				}
+			}
+			return true;
+		} :
+		matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+	var i = 0,
+		len = contexts.length;
+	for ( ; i < len; i++ ) {
+		Sizzle( selector, contexts[i], results );
+	}
+	return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+	var elem,
+		newUnmatched = [],
+		i = 0,
+		len = unmatched.length,
+		mapped = map != null;
+
+	for ( ; i < len; i++ ) {
+		if ( (elem = unmatched[i]) ) {
+			if ( !filter || filter( elem, context, xml ) ) {
+				newUnmatched.push( elem );
+				if ( mapped ) {
+					map.push( i );
+				}
+			}
+		}
+	}
+
+	return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+	if ( postFilter && !postFilter[ expando ] ) {
+		postFilter = setMatcher( postFilter );
+	}
+	if ( postFinder && !postFinder[ expando ] ) {
+		postFinder = setMatcher( postFinder, postSelector );
+	}
+	return markFunction(function( seed, results, context, xml ) {
+		var temp, i, elem,
+			preMap = [],
+			postMap = [],
+			preexisting = results.length,
+
+			// Get initial elements from seed or context
+			elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+			// Prefilter to get matcher input, preserving a map for seed-results synchronization
+			matcherIn = preFilter && ( seed || !selector ) ?
+				condense( elems, preMap, preFilter, context, xml ) :
+				elems,
+
+			matcherOut = matcher ?
+				// If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+				postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+					// ...intermediate processing is necessary
+					[] :
+
+					// ...otherwise use results directly
+					results :
+				matcherIn;
+
+		// Find primary matches
+		if ( matcher ) {
+			matcher( matcherIn, matcherOut, context, xml );
+		}
+
+		// Apply postFilter
+		if ( postFilter ) {
+			temp = condense( matcherOut, postMap );
+			postFilter( temp, [], context, xml );
+
+			// Un-match failing elements by moving them back to matcherIn
+			i = temp.length;
+			while ( i-- ) {
+				if ( (elem = temp[i]) ) {
+					matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+				}
+			}
+		}
+
+		if ( seed ) {
+			if ( postFinder || preFilter ) {
+				if ( postFinder ) {
+					// Get the final matcherOut by condensing this intermediate into postFinder contexts
+					temp = [];
+					i = matcherOut.length;
+					while ( i-- ) {
+						if ( (elem = matcherOut[i]) ) {
+							// Restore matcherIn since elem is not yet a final match
+							temp.push( (matcherIn[i] = elem) );
+						}
+					}
+					postFinder( null, (matcherOut = []), temp, xml );
+				}
+
+				// Move matched elements from seed to results to keep them synchronized
+				i = matcherOut.length;
+				while ( i-- ) {
+					if ( (elem = matcherOut[i]) &&
+						(temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+						seed[temp] = !(results[temp] = elem);
+					}
+				}
+			}
+
+		// Add elements to results, through postFinder if defined
+		} else {
+			matcherOut = condense(
+				matcherOut === results ?
+					matcherOut.splice( preexisting, matcherOut.length ) :
+					matcherOut
+			);
+			if ( postFinder ) {
+				postFinder( null, results, matcherOut, xml );
+			} else {
+				push.apply( results, matcherOut );
+			}
+		}
+	});
+}
+
+function matcherFromTokens( tokens ) {
+	var checkContext, matcher, j,
+		len = tokens.length,
+		leadingRelative = Expr.relative[ tokens[0].type ],
+		implicitRelative = leadingRelative || Expr.relative[" "],
+		i = leadingRelative ? 1 : 0,
+
+		// The foundational matcher ensures that elements are reachable from top-level context(s)
+		matchContext = addCombinator( function( elem ) {
+			return elem === checkContext;
+		}, implicitRelative, true ),
+		matchAnyContext = addCombinator( function( elem ) {
+			return indexOf( checkContext, elem ) > -1;
+		}, implicitRelative, true ),
+		matchers = [ function( elem, context, xml ) {
+			var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+				(checkContext = context).nodeType ?
+					matchContext( elem, context, xml ) :
+					matchAnyContext( elem, context, xml ) );
+			// Avoid hanging onto element (issue #299)
+			checkContext = null;
+			return ret;
+		} ];
+
+	for ( ; i < len; i++ ) {
+		if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+			matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+		} else {
+			matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+			// Return special upon seeing a positional matcher
+			if ( matcher[ expando ] ) {
+				// Find the next relative operator (if any) for proper handling
+				j = ++i;
+				for ( ; j < len; j++ ) {
+					if ( Expr.relative[ tokens[j].type ] ) {
+						break;
+					}
+				}
+				return setMatcher(
+					i > 1 && elementMatcher( matchers ),
+					i > 1 && toSelector(
+						// If the preceding token was a descendant combinator, insert an implicit any-element `*`
+						tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+					).replace( rtrim, "$1" ),
+					matcher,
+					i < j && matcherFromTokens( tokens.slice( i, j ) ),
+					j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+					j < len && toSelector( tokens )
+				);
+			}
+			matchers.push( matcher );
+		}
+	}
+
+	return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+	var bySet = setMatchers.length > 0,
+		byElement = elementMatchers.length > 0,
+		superMatcher = function( seed, context, xml, results, outermost ) {
+			var elem, j, matcher,
+				matchedCount = 0,
+				i = "0",
+				unmatched = seed && [],
+				setMatched = [],
+				contextBackup = outermostContext,
+				// We must always have either seed elements or outermost context
+				elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+				// Use integer dirruns iff this is the outermost matcher
+				dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+				len = elems.length;
+
+			if ( outermost ) {
+				outermostContext = context === document || context || outermost;
+			}
+
+			// Add elements passing elementMatchers directly to results
+			// Support: IE<9, Safari
+			// Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+			for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+				if ( byElement && elem ) {
+					j = 0;
+					if ( !context && elem.ownerDocument !== document ) {
+						setDocument( elem );
+						xml = !documentIsHTML;
+					}
+					while ( (matcher = elementMatchers[j++]) ) {
+						if ( matcher( elem, context || document, xml) ) {
+							results.push( elem );
+							break;
+						}
+					}
+					if ( outermost ) {
+						dirruns = dirrunsUnique;
+					}
+				}
+
+				// Track unmatched elements for set filters
+				if ( bySet ) {
+					// They will have gone through all possible matchers
+					if ( (elem = !matcher && elem) ) {
+						matchedCount--;
+					}
+
+					// Lengthen the array for every element, matched or not
+					if ( seed ) {
+						unmatched.push( elem );
+					}
+				}
+			}
+
+			// `i` is now the count of elements visited above, and adding it to `matchedCount`
+			// makes the latter nonnegative.
+			matchedCount += i;
+
+			// Apply set filters to unmatched elements
+			// NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
+			// equals `i`), unless we didn't visit _any_ elements in the above loop because we have
+			// no element matchers and no seed.
+			// Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
+			// case, which will result in a "00" `matchedCount` that differs from `i` but is also
+			// numerically zero.
+			if ( bySet && i !== matchedCount ) {
+				j = 0;
+				while ( (matcher = setMatchers[j++]) ) {
+					matcher( unmatched, setMatched, context, xml );
+				}
+
+				if ( seed ) {
+					// Reintegrate element matches to eliminate the need for sorting
+					if ( matchedCount > 0 ) {
+						while ( i-- ) {
+							if ( !(unmatched[i] || setMatched[i]) ) {
+								setMatched[i] = pop.call( results );
+							}
+						}
+					}
+
+					// Discard index placeholder values to get only actual matches
+					setMatched = condense( setMatched );
+				}
+
+				// Add matches to results
+				push.apply( results, setMatched );
+
+				// Seedless set matches succeeding multiple successful matchers stipulate sorting
+				if ( outermost && !seed && setMatched.length > 0 &&
+					( matchedCount + setMatchers.length ) > 1 ) {
+
+					Sizzle.uniqueSort( results );
+				}
+			}
+
+			// Override manipulation of globals by nested matchers
+			if ( outermost ) {
+				dirruns = dirrunsUnique;
+				outermostContext = contextBackup;
+			}
+
+			return unmatched;
+		};
+
+	return bySet ?
+		markFunction( superMatcher ) :
+		superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+	var i,
+		setMatchers = [],
+		elementMatchers = [],
+		cached = compilerCache[ selector + " " ];
+
+	if ( !cached ) {
+		// Generate a function of recursive functions that can be used to check each element
+		if ( !match ) {
+			match = tokenize( selector );
+		}
+		i = match.length;
+		while ( i-- ) {
+			cached = matcherFromTokens( match[i] );
+			if ( cached[ expando ] ) {
+				setMatchers.push( cached );
+			} else {
+				elementMatchers.push( cached );
+			}
+		}
+
+		// Cache the compiled function
+		cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+		// Save selector and tokenization
+		cached.selector = selector;
+	}
+	return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ *  selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ *  selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+	var i, tokens, token, type, find,
+		compiled = typeof selector === "function" && selector,
+		match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+	results = results || [];
+
+	// Try to minimize operations if there is only one selector in the list and no seed
+	// (the latter of which guarantees us context)
+	if ( match.length === 1 ) {
+
+		// Reduce context if the leading compound selector is an ID
+		tokens = match[0] = match[0].slice( 0 );
+		if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+				support.getById && context.nodeType === 9 && documentIsHTML &&
+				Expr.relative[ tokens[1].type ] ) {
+
+			context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+			if ( !context ) {
+				return results;
+
+			// Precompiled matchers will still verify ancestry, so step up a level
+			} else if ( compiled ) {
+				context = context.parentNode;
+			}
+
+			selector = selector.slice( tokens.shift().value.length );
+		}
+
+		// Fetch a seed set for right-to-left matching
+		i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+		while ( i-- ) {
+			token = tokens[i];
+
+			// Abort if we hit a combinator
+			if ( Expr.relative[ (type = token.type) ] ) {
+				break;
+			}
+			if ( (find = Expr.find[ type ]) ) {
+				// Search, expanding context for leading sibling combinators
+				if ( (seed = find(
+					token.matches[0].replace( runescape, funescape ),
+					rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+				)) ) {
+
+					// If seed is empty or no tokens remain, we can return early
+					tokens.splice( i, 1 );
+					selector = seed.length && toSelector( tokens );
+					if ( !selector ) {
+						push.apply( results, seed );
+						return results;
+					}
+
+					break;
+				}
+			}
+		}
+	}
+
+	// Compile and execute a filtering function if one is not provided
+	// Provide `match` to avoid retokenization if we modified the selector above
+	( compiled || compile( selector, match ) )(
+		seed,
+		context,
+		!documentIsHTML,
+		results,
+		!context || rsibling.test( selector ) && testContext( context.parentNode ) || context
+	);
+	return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+	// Should return 1, but returns 4 (following)
+	return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+	div.innerHTML = "<a href='#'></a>";
+	return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+	addHandle( "type|href|height|width", function( elem, name, isXML ) {
+		if ( !isXML ) {
+			return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+		}
+	});
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+	div.innerHTML = "<input/>";
+	div.firstChild.setAttribute( "value", "" );
+	return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+	addHandle( "value", function( elem, name, isXML ) {
+		if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+			return elem.defaultValue;
+		}
+	});
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+	return div.getAttribute("disabled") == null;
+}) ) {
+	addHandle( booleans, function( elem, name, isXML ) {
+		var val;
+		if ( !isXML ) {
+			return elem[ name ] === true ? name.toLowerCase() :
+					(val = elem.getAttributeNode( name )) && val.specified ?
+					val.value :
+				null;
+		}
+	});
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[ ":" ] = jQuery.expr.pseudos;
+jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var dir = function( elem, dir, until ) {
+	var matched = [],
+		truncate = until !== undefined;
+
+	while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
+		if ( elem.nodeType === 1 ) {
+			if ( truncate && jQuery( elem ).is( until ) ) {
+				break;
+			}
+			matched.push( elem );
+		}
+	}
+	return matched;
+};
+
+
+var siblings = function( n, elem ) {
+	var matched = [];
+
+	for ( ; n; n = n.nextSibling ) {
+		if ( n.nodeType === 1 && n !== elem ) {
+			matched.push( n );
+		}
+	}
+
+	return matched;
+};
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = ( /^<([\w-]+)\s*\/?>(?:<\/\1>|)$/ );
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+	if ( jQuery.isFunction( qualifier ) ) {
+		return jQuery.grep( elements, function( elem, i ) {
+			/* jshint -W018 */
+			return !!qualifier.call( elem, i, elem ) !== not;
+		} );
+
+	}
+
+	if ( qualifier.nodeType ) {
+		return jQuery.grep( elements, function( elem ) {
+			return ( elem === qualifier ) !== not;
+		} );
+
+	}
+
+	if ( typeof qualifier === "string" ) {
+		if ( risSimple.test( qualifier ) ) {
+			return jQuery.filter( qualifier, elements, not );
+		}
+
+		qualifier = jQuery.filter( qualifier, elements );
+	}
+
+	return jQuery.grep( elements, function( elem ) {
+		return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
+	} );
+}
+
+jQuery.filter = function( expr, elems, not ) {
+	var elem = elems[ 0 ];
+
+	if ( not ) {
+		expr = ":not(" + expr + ")";
+	}
+
+	return elems.length === 1 && elem.nodeType === 1 ?
+		jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+		jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+			return elem.nodeType === 1;
+		} ) );
+};
+
+jQuery.fn.extend( {
+	find: function( selector ) {
+		var i,
+			len = this.length,
+			ret = [],
+			self = this;
+
+		if ( typeof selector !== "string" ) {
+			return this.pushStack( jQuery( selector ).filter( function() {
+				for ( i = 0; i < len; i++ ) {
+					if ( jQuery.contains( self[ i ], this ) ) {
+						return true;
+					}
+				}
+			} ) );
+		}
+
+		for ( i = 0; i < len; i++ ) {
+			jQuery.find( selector, self[ i ], ret );
+		}
+
+		// Needed because $( selector, context ) becomes $( context ).find( selector )
+		ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+		ret.selector = this.selector ? this.selector + " " + selector : selector;
+		return ret;
+	},
+	filter: function( selector ) {
+		return this.pushStack( winnow( this, selector || [], false ) );
+	},
+	not: function( selector ) {
+		return this.pushStack( winnow( this, selector || [], true ) );
+	},
+	is: function( selector ) {
+		return !!winnow(
+			this,
+
+			// If this is a positional/relative selector, check membership in the returned set
+			// so $("p:first").is("p:last") won't return true for a doc with two "p".
+			typeof selector === "string" && rneedsContext.test( selector ) ?
+				jQuery( selector ) :
+				selector || [],
+			false
+		).length;
+	}
+} );
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+	// A simple way to check for HTML strings
+	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+	// Strict HTML recognition (#11290: must start with <)
+	rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+	init = jQuery.fn.init = function( selector, context, root ) {
+		var match, elem;
+
+		// HANDLE: $(""), $(null), $(undefined), $(false)
+		if ( !selector ) {
+			return this;
+		}
+
+		// Method init() accepts an alternate rootjQuery
+		// so migrate can support jQuery.sub (gh-2101)
+		root = root || rootjQuery;
+
+		// Handle HTML strings
+		if ( typeof selector === "string" ) {
+			if ( selector[ 0 ] === "<" &&
+				selector[ selector.length - 1 ] === ">" &&
+				selector.length >= 3 ) {
+
+				// Assume that strings that start and end with <> are HTML and skip the regex check
+				match = [ null, selector, null ];
+
+			} else {
+				match = rquickExpr.exec( selector );
+			}
+
+			// Match html or make sure no context is specified for #id
+			if ( match && ( match[ 1 ] || !context ) ) {
+
+				// HANDLE: $(html) -> $(array)
+				if ( match[ 1 ] ) {
+					context = context instanceof jQuery ? context[ 0 ] : context;
+
+					// Option to run scripts is true for back-compat
+					// Intentionally let the error be thrown if parseHTML is not present
+					jQuery.merge( this, jQuery.parseHTML(
+						match[ 1 ],
+						context && context.nodeType ? context.ownerDocument || context : document,
+						true
+					) );
+
+					// HANDLE: $(html, props)
+					if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
+						for ( match in context ) {
+
+							// Properties of context are called as methods if possible
+							if ( jQuery.isFunction( this[ match ] ) ) {
+								this[ match ]( context[ match ] );
+
+							// ...and otherwise set as attributes
+							} else {
+								this.attr( match, context[ match ] );
+							}
+						}
+					}
+
+					return this;
+
+				// HANDLE: $(#id)
+				} else {
+					elem = document.getElementById( match[ 2 ] );
+
+					// Support: Blackberry 4.6
+					// gEBID returns nodes no longer in the document (#6963)
+					if ( elem && elem.parentNode ) {
+
+						// Inject the element directly into the jQuery object
+						this.length = 1;
+						this[ 0 ] = elem;
+					}
+
+					this.context = document;
+					this.selector = selector;
+					return this;
+				}
+
+			// HANDLE: $(expr, $(...))
+			} else if ( !context || context.jquery ) {
+				return ( context || root ).find( selector );
+
+			// HANDLE: $(expr, context)
+			// (which is just equivalent to: $(context).find(expr)
+			} else {
+				return this.constructor( context ).find( selector );
+			}
+
+		// HANDLE: $(DOMElement)
+		} else if ( selector.nodeType ) {
+			this.context = this[ 0 ] = selector;
+			this.length = 1;
+			return this;
+
+		// HANDLE: $(function)
+		// Shortcut for document ready
+		} else if ( jQuery.isFunction( selector ) ) {
+			return root.ready !== undefined ?
+				root.ready( selector ) :
+
+				// Execute immediately if ready is not present
+				selector( jQuery );
+		}
+
+		if ( selector.selector !== undefined ) {
+			this.selector = selector.selector;
+			this.context = selector.context;
+		}
+
+		return jQuery.makeArray( selector, this );
+	};
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+
+	// Methods guaranteed to produce a unique set when starting from a unique set
+	guaranteedUnique = {
+		children: true,
+		contents: true,
+		next: true,
+		prev: true
+	};
+
+jQuery.fn.extend( {
+	has: function( target ) {
+		var targets = jQuery( target, this ),
+			l = targets.length;
+
+		return this.filter( function() {
+			var i = 0;
+			for ( ; i < l; i++ ) {
+				if ( jQuery.contains( this, targets[ i ] ) ) {
+					return true;
+				}
+			}
+		} );
+	},
+
+	closest: function( selectors, context ) {
+		var cur,
+			i = 0,
+			l = this.length,
+			matched = [],
+			pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+				jQuery( selectors, context || this.context ) :
+				0;
+
+		for ( ; i < l; i++ ) {
+			for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
+
+				// Always skip document fragments
+				if ( cur.nodeType < 11 && ( pos ?
+					pos.index( cur ) > -1 :
+
+					// Don't pass non-elements to Sizzle
+					cur.nodeType === 1 &&
+						jQuery.find.matchesSelector( cur, selectors ) ) ) {
+
+					matched.push( cur );
+					break;
+				}
+			}
+		}
+
+		return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
+	},
+
+	// Determine the position of an element within the set
+	index: function( elem ) {
+
+		// No argument, return index in parent
+		if ( !elem ) {
+			return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+		}
+
+		// Index in selector
+		if ( typeof elem === "string" ) {
+			return indexOf.call( jQuery( elem ), this[ 0 ] );
+		}
+
+		// Locate the position of the desired element
+		return indexOf.call( this,
+
+			// If it receives a jQuery object, the first element is used
+			elem.jquery ? elem[ 0 ] : elem
+		);
+	},
+
+	add: function( selector, context ) {
+		return this.pushStack(
+			jQuery.uniqueSort(
+				jQuery.merge( this.get(), jQuery( selector, context ) )
+			)
+		);
+	},
+
+	addBack: function( selector ) {
+		return this.add( selector == null ?
+			this.prevObject : this.prevObject.filter( selector )
+		);
+	}
+} );
+
+function sibling( cur, dir ) {
+	while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
+	return cur;
+}
+
+jQuery.each( {
+	parent: function( elem ) {
+		var parent = elem.parentNode;
+		return parent && parent.nodeType !== 11 ? parent : null;
+	},
+	parents: function( elem ) {
+		return dir( elem, "parentNode" );
+	},
+	parentsUntil: function( elem, i, until ) {
+		return dir( elem, "parentNode", until );
+	},
+	next: function( elem ) {
+		return sibling( elem, "nextSibling" );
+	},
+	prev: function( elem ) {
+		return sibling( elem, "previousSibling" );
+	},
+	nextAll: function( elem ) {
+		return dir( elem, "nextSibling" );
+	},
+	prevAll: function( elem ) {
+		return dir( elem, "previousSibling" );
+	},
+	nextUntil: function( elem, i, until ) {
+		return dir( elem, "nextSibling", until );
+	},
+	prevUntil: function( elem, i, until ) {
+		return dir( elem, "previousSibling", until );
+	},
+	siblings: function( elem ) {
+		return siblings( ( elem.parentNode || {} ).firstChild, elem );
+	},
+	children: function( elem ) {
+		return siblings( elem.firstChild );
+	},
+	contents: function( elem ) {
+		return elem.contentDocument || jQuery.merge( [], elem.childNodes );
+	}
+}, function( name, fn ) {
+	jQuery.fn[ name ] = function( until, selector ) {
+		var matched = jQuery.map( this, fn, until );
+
+		if ( name.slice( -5 ) !== "Until" ) {
+			selector = until;
+		}
+
+		if ( selector && typeof selector === "string" ) {
+			matched = jQuery.filter( selector, matched );
+		}
+
+		if ( this.length > 1 ) {
+
+			// Remove duplicates
+			if ( !guaranteedUnique[ name ] ) {
+				jQuery.uniqueSort( matched );
+			}
+
+			// Reverse order for parents* and prev-derivatives
+			if ( rparentsprev.test( name ) ) {
+				matched.reverse();
+			}
+		}
+
+		return this.pushStack( matched );
+	};
+} );
+var rnotwhite = ( /\S+/g );
+
+
+
+// Convert String-formatted options into Object-formatted ones
+function createOptions( options ) {
+	var object = {};
+	jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+		object[ flag ] = true;
+	} );
+	return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ *	options: an optional list of space-separated options that will change how
+ *			the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ *	once:			will ensure the callback list can only be fired once (like a Deferred)
+ *
+ *	memory:			will keep track of previous values and will call any callback added
+ *					after the list has been fired right away with the latest "memorized"
+ *					values (like a Deferred)
+ *
+ *	unique:			will ensure a callback can only be added once (no duplicate in the list)
+ *
+ *	stopOnFalse:	interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+	// Convert options from String-formatted to Object-formatted if needed
+	// (we check in cache first)
+	options = typeof options === "string" ?
+		createOptions( options ) :
+		jQuery.extend( {}, options );
+
+	var // Flag to know if list is currently firing
+		firing,
+
+		// Last fire value for non-forgettable lists
+		memory,
+
+		// Flag to know if list was already fired
+		fired,
+
+		// Flag to prevent firing
+		locked,
+
+		// Actual callback list
+		list = [],
+
+		// Queue of execution data for repeatable lists
+		queue = [],
+
+		// Index of currently firing callback (modified by add/remove as needed)
+		firingIndex = -1,
+
+		// Fire callbacks
+		fire = function() {
+
+			// Enforce single-firing
+			locked = options.once;
+
+			// Execute callbacks for all pending executions,
+			// respecting firingIndex overrides and runtime changes
+			fired = firing = true;
+			for ( ; queue.length; firingIndex = -1 ) {
+				memory = queue.shift();
+				while ( ++firingIndex < list.length ) {
+
+					// Run callback and check for early termination
+					if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
+						options.stopOnFalse ) {
+
+						// Jump to end and forget the data so .add doesn't re-fire
+						firingIndex = list.length;
+						memory = false;
+					}
+				}
+			}
+
+			// Forget the data if we're done with it
+			if ( !options.memory ) {
+				memory = false;
+			}
+
+			firing = false;
+
+			// Clean up if we're done firing for good
+			if ( locked ) {
+
+				// Keep an empty list if we have data for future add calls
+				if ( memory ) {
+					list = [];
+
+				// Otherwise, this object is spent
+				} else {
+					list = "";
+				}
+			}
+		},
+
+		// Actual Callbacks object
+		self = {
+
+			// Add a callback or a collection of callbacks to the list
+			add: function() {
+				if ( list ) {
+
+					// If we have memory from a past run, we should fire after adding
+					if ( memory && !firing ) {
+						firingIndex = list.length - 1;
+						queue.push( memory );
+					}
+
+					( function add( args ) {
+						jQuery.each( args, function( _, arg ) {
+							if ( jQuery.isFunction( arg ) ) {
+								if ( !options.unique || !self.has( arg ) ) {
+									list.push( arg );
+								}
+							} else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+
+								// Inspect recursively
+								add( arg );
+							}
+						} );
+					} )( arguments );
+
+					if ( memory && !firing ) {
+						fire();
+					}
+				}
+				return this;
+			},
+
+			// Remove a callback from the list
+			remove: function() {
+				jQuery.each( arguments, function( _, arg ) {
+					var index;
+					while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+						list.splice( index, 1 );
+
+						// Handle firing indexes
+						if ( index <= firingIndex ) {
+							firingIndex--;
+						}
+					}
+				} );
+				return this;
+			},
+
+			// Check if a given callback is in the list.
+			// If no argument is given, return whether or not list has callbacks attached.
+			has: function( fn ) {
+				return fn ?
+					jQuery.inArray( fn, list ) > -1 :
+					list.length > 0;
+			},
+
+			// Remove all callbacks from the list
+			empty: function() {
+				if ( list ) {
+					list = [];
+				}
+				return this;
+			},
+
+			// Disable .fire and .add
+			// Abort any current/pending executions
+			// Clear all callbacks and values
+			disable: function() {
+				locked = queue = [];
+				list = memory = "";
+				return this;
+			},
+			disabled: function() {
+				return !list;
+			},
+
+			// Disable .fire
+			// Also disable .add unless we have memory (since it would have no effect)
+			// Abort any pending executions
+			lock: function() {
+				locked = queue = [];
+				if ( !memory ) {
+					list = memory = "";
+				}
+				return this;
+			},
+			locked: function() {
+				return !!locked;
+			},
+
+			// Call all callbacks with the given context and arguments
+			fireWith: function( context, args ) {
+				if ( !locked ) {
+					args = args || [];
+					args = [ context, args.slice ? args.slice() : args ];
+					queue.push( args );
+					if ( !firing ) {
+						fire();
+					}
+				}
+				return this;
+			},
+
+			// Call all the callbacks with the given arguments
+			fire: function() {
+				self.fireWith( this, arguments );
+				return this;
+			},
+
+			// To know if the callbacks have already been called at least once
+			fired: function() {
+				return !!fired;
+			}
+		};
+
+	return self;
+};
+
+
+jQuery.extend( {
+
+	Deferred: function( func ) {
+		var tuples = [
+
+				// action, add listener, listener list, final state
+				[ "resolve", "done", jQuery.Callbacks( "once memory" ), "resolved" ],
+				[ "reject", "fail", jQuery.Callbacks( "once memory" ), "rejected" ],
+				[ "notify", "progress", jQuery.Callbacks( "memory" ) ]
+			],
+			state = "pending",
+			promise = {
+				state: function() {
+					return state;
+				},
+				always: function() {
+					deferred.done( arguments ).fail( arguments );
+					return this;
+				},
+				then: function( /* fnDone, fnFail, fnProgress */ ) {
+					var fns = arguments;
+					return jQuery.Deferred( function( newDefer ) {
+						jQuery.each( tuples, function( i, tuple ) {
+							var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+
+							// deferred[ done | fail | progress ] for forwarding actions to newDefer
+							deferred[ tuple[ 1 ] ]( function() {
+								var returned = fn && fn.apply( this, arguments );
+								if ( returned && jQuery.isFunction( returned.promise ) ) {
+									returned.promise()
+										.progress( newDefer.notify )
+										.done( newDefer.resolve )
+										.fail( newDefer.reject );
+								} else {
+									newDefer[ tuple[ 0 ] + "With" ](
+										this === promise ? newDefer.promise() : this,
+										fn ? [ returned ] : arguments
+									);
+								}
+							} );
+						} );
+						fns = null;
+					} ).promise();
+				},
+
+				// Get a promise for this deferred
+				// If obj is provided, the promise aspect is added to the object
+				promise: function( obj ) {
+					return obj != null ? jQuery.extend( obj, promise ) : promise;
+				}
+			},
+			deferred = {};
+
+		// Keep pipe for back-compat
+		promise.pipe = promise.then;
+
+		// Add list-specific methods
+		jQuery.each( tuples, function( i, tuple ) {
+			var list = tuple[ 2 ],
+				stateString = tuple[ 3 ];
+
+			// promise[ done | fail | progress ] = list.add
+			promise[ tuple[ 1 ] ] = list.add;
+
+			// Handle state
+			if ( stateString ) {
+				list.add( function() {
+
+					// state = [ resolved | rejected ]
+					state = stateString;
+
+				// [ reject_list | resolve_list ].disable; progress_list.lock
+				}, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+			}
+
+			// deferred[ resolve | reject | notify ]
+			deferred[ tuple[ 0 ] ] = function() {
+				deferred[ tuple[ 0 ] + "With" ]( this === deferred ? promise : this, arguments );
+				return this;
+			};
+			deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
+		} );
+
+		// Make the deferred a promise
+		promise.promise( deferred );
+
+		// Call given func if any
+		if ( func ) {
+			func.call( deferred, deferred );
+		}
+
+		// All done!
+		return deferred;
+	},
+
+	// Deferred helper
+	when: function( subordinate /* , ..., subordinateN */ ) {
+		var i = 0,
+			resolveValues = slice.call( arguments ),
+			length = resolveValues.length,
+
+			// the count of uncompleted subordinates
+			remaining = length !== 1 ||
+				( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+			// the master Deferred.
+			// If resolveValues consist of only a single Deferred, just use that.
+			deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+			// Update function for both resolve and progress values
+			updateFunc = function( i, contexts, values ) {
+				return function( value ) {
+					contexts[ i ] = this;
+					values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+					if ( values === progressValues ) {
+						deferred.notifyWith( contexts, values );
+					} else if ( !( --remaining ) ) {
+						deferred.resolveWith( contexts, values );
+					}
+				};
+			},
+
+			progressValues, progressContexts, resolveContexts;
+
+		// Add listeners to Deferred subordinates; treat others as resolved
+		if ( length > 1 ) {
+			progressValues = new Array( length );
+			progressContexts = new Array( length );
+			resolveContexts = new Array( length );
+			for ( ; i < length; i++ ) {
+				if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+					resolveValues[ i ].promise()
+						.progress( updateFunc( i, progressContexts, progressValues ) )
+						.done( updateFunc( i, resolveContexts, resolveValues ) )
+						.fail( deferred.reject );
+				} else {
+					--remaining;
+				}
+			}
+		}
+
+		// If we're not waiting on anything, resolve the master
+		if ( !remaining ) {
+			deferred.resolveWith( resolveContexts, resolveValues );
+		}
+
+		return deferred.promise();
+	}
+} );
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+
+	// Add the callback
+	jQuery.ready.promise().done( fn );
+
+	return this;
+};
+
+jQuery.extend( {
+
+	// Is the DOM ready to be used? Set to true once it occurs.
+	isReady: false,
+
+	// A counter to track how many items to wait for before
+	// the ready event fires. See #6781
+	readyWait: 1,
+
+	// Hold (or release) the ready event
+	holdReady: function( hold ) {
+		if ( hold ) {
+			jQuery.readyWait++;
+		} else {
+			jQuery.ready( true );
+		}
+	},
+
+	// Handle when the DOM is ready
+	ready: function( wait ) {
+
+		// Abort if there are pending holds or we're already ready
+		if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+			return;
+		}
+
+		// Remember that the DOM is ready
+		jQuery.isReady = true;
+
+		// If a normal DOM Ready event fired, decrement, and wait if need be
+		if ( wait !== true && --jQuery.readyWait > 0 ) {
+			return;
+		}
+
+		// If there are functions bound, to execute
+		readyList.resolveWith( document, [ jQuery ] );
+
+		// Trigger any bound ready events
+		if ( jQuery.fn.triggerHandler ) {
+			jQuery( document ).triggerHandler( "ready" );
+			jQuery( document ).off( "ready" );
+		}
+	}
+} );
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+	document.removeEventListener( "DOMContentLoaded", completed );
+	window.removeEventListener( "load", completed );
+	jQuery.ready();
+}
+
+jQuery.ready.promise = function( obj ) {
+	if ( !readyList ) {
+
+		readyList = jQuery.Deferred();
+
+		// Catch cases where $(document).ready() is called
+		// after the browser event has already occurred.
+		// Support: IE9-10 only
+		// Older IE sometimes signals "interactive" too soon
+		if ( document.readyState === "complete" ||
+			( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+
+			// Handle it asynchronously to allow scripts the opportunity to delay ready
+			window.setTimeout( jQuery.ready );
+
+		} else {
+
+			// Use the handy event callback
+			document.addEventListener( "DOMContentLoaded", completed );
+
+			// A fallback to window.onload, that will always work
+			window.addEventListener( "load", completed );
+		}
+	}
+	return readyList.promise( obj );
+};
+
+// Kick off the DOM ready check even if the user does not
+jQuery.ready.promise();
+
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+	var i = 0,
+		len = elems.length,
+		bulk = key == null;
+
+	// Sets many values
+	if ( jQuery.type( key ) === "object" ) {
+		chainable = true;
+		for ( i in key ) {
+			access( elems, fn, i, key[ i ], true, emptyGet, raw );
+		}
+
+	// Sets one value
+	} else if ( value !== undefined ) {
+		chainable = true;
+
+		if ( !jQuery.isFunction( value ) ) {
+			raw = true;
+		}
+
+		if ( bulk ) {
+
+			// Bulk operations run against the entire set
+			if ( raw ) {
+				fn.call( elems, value );
+				fn = null;
+
+			// ...except when executing function values
+			} else {
+				bulk = fn;
+				fn = function( elem, key, value ) {
+					return bulk.call( jQuery( elem ), value );
+				};
+			}
+		}
+
+		if ( fn ) {
+			for ( ; i < len; i++ ) {
+				fn(
+					elems[ i ], key, raw ?
+					value :
+					value.call( elems[ i ], i, fn( elems[ i ], key ) )
+				);
+			}
+		}
+	}
+
+	return chainable ?
+		elems :
+
+		// Gets
+		bulk ?
+			fn.call( elems ) :
+			len ? fn( elems[ 0 ], key ) : emptyGet;
+};
+var acceptData = function( owner ) {
+
+	// Accepts only:
+	//  - Node
+	//    - Node.ELEMENT_NODE
+	//    - Node.DOCUMENT_NODE
+	//  - Object
+	//    - Any
+	/* jshint -W018 */
+	return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
+
+
+
+
+function Data() {
+	this.expando = jQuery.expando + Data.uid++;
+}
+
+Data.uid = 1;
+
+Data.prototype = {
+
+	register: function( owner, initial ) {
+		var value = initial || {};
+
+		// If it is a node unlikely to be stringify-ed or looped over
+		// use plain assignment
+		if ( owner.nodeType ) {
+			owner[ this.expando ] = value;
+
+		// Otherwise secure it in a non-enumerable, non-writable property
+		// configurability must be true to allow the property to be
+		// deleted with the delete operator
+		} else {
+			Object.defineProperty( owner, this.expando, {
+				value: value,
+				writable: true,
+				configurable: true
+			} );
+		}
+		return owner[ this.expando ];
+	},
+	cache: function( owner ) {
+
+		// We can accept data for non-element nodes in modern browsers,
+		// but we should not, see #8335.
+		// Always return an empty object.
+		if ( !acceptData( owner ) ) {
+			return {};
+		}
+
+		// Check if the owner object already has a cache
+		var value = owner[ this.expando ];
+
+		// If not, create one
+		if ( !value ) {
+			value = {};
+
+			// We can accept data for non-element nodes in modern browsers,
+			// but we should not, see #8335.
+			// Always return an empty object.
+			if ( acceptData( owner ) ) {
+
+				// If it is a node unlikely to be stringify-ed or looped over
+				// use plain assignment
+				if ( owner.nodeType ) {
+					owner[ this.expando ] = value;
+
+				// Otherwise secure it in a non-enumerable property
+				// configurable must be true to allow the property to be
+				// deleted when data is removed
+				} else {
+					Object.defineProperty( owner, this.expando, {
+						value: value,
+						configurable: true
+					} );
+				}
+			}
+		}
+
+		return value;
+	},
+	set: function( owner, data, value ) {
+		var prop,
+			cache = this.cache( owner );
+
+		// Handle: [ owner, key, value ] args
+		if ( typeof data === "string" ) {
+			cache[ data ] = value;
+
+		// Handle: [ owner, { properties } ] args
+		} else {
+
+			// Copy the properties one-by-one to the cache object
+			for ( prop in data ) {
+				cache[ prop ] = data[ prop ];
+			}
+		}
+		return cache;
+	},
+	get: function( owner, key ) {
+		return key === undefined ?
+			this.cache( owner ) :
+			owner[ this.expando ] && owner[ this.expando ][ key ];
+	},
+	access: function( owner, key, value ) {
+		var stored;
+
+		// In cases where either:
+		//
+		//   1. No key was specified
+		//   2. A string key was specified, but no value provided
+		//
+		// Take the "read" path and allow the get method to determine
+		// which value to return, respectively either:
+		//
+		//   1. The entire cache object
+		//   2. The data stored at the key
+		//
+		if ( key === undefined ||
+				( ( key && typeof key === "string" ) && value === undefined ) ) {
+
+			stored = this.get( owner, key );
+
+			return stored !== undefined ?
+				stored : this.get( owner, jQuery.camelCase( key ) );
+		}
+
+		// When the key is not a string, or both a key and value
+		// are specified, set or extend (existing objects) with either:
+		//
+		//   1. An object of properties
+		//   2. A key and value
+		//
+		this.set( owner, key, value );
+
+		// Since the "set" path can have two possible entry points
+		// return the expected data based on which path was taken[*]
+		return value !== undefined ? value : key;
+	},
+	remove: function( owner, key ) {
+		var i, name, camel,
+			cache = owner[ this.expando ];
+
+		if ( cache === undefined ) {
+			return;
+		}
+
+		if ( key === undefined ) {
+			this.register( owner );
+
+		} else {
+
+			// Support array or space separated string of keys
+			if ( jQuery.isArray( key ) ) {
+
+				// If "name" is an array of keys...
+				// When data is initially created, via ("key", "val") signature,
+				// keys will be converted to camelCase.
+				// Since there is no way to tell _how_ a key was added, remove
+				// both plain key and camelCase key. #12786
+				// This will only penalize the array argument path.
+				name = key.concat( key.map( jQuery.camelCase ) );
+			} else {
+				camel = jQuery.camelCase( key );
+
+				// Try the string as a key before any manipulation
+				if ( key in cache ) {
+					name = [ key, camel ];
+				} else {
+
+					// If a key with the spaces exists, use it.
+					// Otherwise, create an array by matching non-whitespace
+					name = camel;
+					name = name in cache ?
+						[ name ] : ( name.match( rnotwhite ) || [] );
+				}
+			}
+
+			i = name.length;
+
+			while ( i-- ) {
+				delete cache[ name[ i ] ];
+			}
+		}
+
+		// Remove the expando if there's no more data
+		if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
+
+			// Support: Chrome <= 35-45+
+			// Webkit & Blink performance suffers when deleting properties
+			// from DOM nodes, so set to undefined instead
+			// https://code.google.com/p/chromium/issues/detail?id=378607
+			if ( owner.nodeType ) {
+				owner[ this.expando ] = undefined;
+			} else {
+				delete owner[ this.expando ];
+			}
+		}
+	},
+	hasData: function( owner ) {
+		var cache = owner[ this.expando ];
+		return cache !== undefined && !jQuery.isEmptyObject( cache );
+	}
+};
+var dataPriv = new Data();
+
+var dataUser = new Data();
+
+
+
+//	Implementation Summary
+//
+//	1. Enforce API surface and semantic compatibility with 1.9.x branch
+//	2. Improve the module's maintainability by reducing the storage
+//		paths to a single mechanism.
+//	3. Use the same single mechanism to support "private" and "user" data.
+//	4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+//	5. Avoid exposing implementation details on user objects (eg. expando properties)
+//	6. Provide a clear path for implementation upgrade to WeakMap in 2014
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+	rmultiDash = /[A-Z]/g;
+
+function dataAttr( elem, key, data ) {
+	var name;
+
+	// If nothing was found internally, try to fetch any
+	// data from the HTML5 data-* attribute
+	if ( data === undefined && elem.nodeType === 1 ) {
+		name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
+		data = elem.getAttribute( name );
+
+		if ( typeof data === "string" ) {
+			try {
+				data = data === "true" ? true :
+					data === "false" ? false :
+					data === "null" ? null :
+
+					// Only convert to a number if it doesn't change the string
+					+data + "" === data ? +data :
+					rbrace.test( data ) ? jQuery.parseJSON( data ) :
+					data;
+			} catch ( e ) {}
+
+			// Make sure we set the data so it isn't changed later
+			dataUser.set( elem, key, data );
+		} else {
+			data = undefined;
+		}
+	}
+	return data;
+}
+
+jQuery.extend( {
+	hasData: function( elem ) {
+		return dataUser.hasData( elem ) || dataPriv.hasData( elem );
+	},
+
+	data: function( elem, name, data ) {
+		return dataUser.access( elem, name, data );
+	},
+
+	removeData: function( elem, name ) {
+		dataUser.remove( elem, name );
+	},
+
+	// TODO: Now that all calls to _data and _removeData have been replaced
+	// with direct calls to dataPriv methods, these can be deprecated.
+	_data: function( elem, name, data ) {
+		return dataPriv.access( elem, name, data );
+	},
+
+	_removeData: function( elem, name ) {
+		dataPriv.remove( elem, name );
+	}
+} );
+
+jQuery.fn.extend( {
+	data: function( key, value ) {
+		var i, name, data,
+			elem = this[ 0 ],
+			attrs = elem && elem.attributes;
+
+		// Gets all values
+		if ( key === undefined ) {
+			if ( this.length ) {
+				data = dataUser.get( elem );
+
+				if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
+					i = attrs.length;
+					while ( i-- ) {
+
+						// Support: IE11+
+						// The attrs elements can be null (#14894)
+						if ( attrs[ i ] ) {
+							name = attrs[ i ].name;
+							if ( name.indexOf( "data-" ) === 0 ) {
+								name = jQuery.camelCase( name.slice( 5 ) );
+								dataAttr( elem, name, data[ name ] );
+							}
+						}
+					}
+					dataPriv.set( elem, "hasDataAttrs", true );
+				}
+			}
+
+			return data;
+		}
+
+		// Sets multiple values
+		if ( typeof key === "object" ) {
+			return this.each( function() {
+				dataUser.set( this, key );
+			} );
+		}
+
+		return access( this, function( value ) {
+			var data, camelKey;
+
+			// The calling jQuery object (element matches) is not empty
+			// (and therefore has an element appears at this[ 0 ]) and the
+			// `value` parameter was not undefined. An empty jQuery object
+			// will result in `undefined` for elem = this[ 0 ] which will
+			// throw an exception if an attempt to read a data cache is made.
+			if ( elem && value === undefined ) {
+
+				// Attempt to get data from the cache
+				// with the key as-is
+				data = dataUser.get( elem, key ) ||
+
+					// Try to find dashed key if it exists (gh-2779)
+					// This is for 2.2.x only
+					dataUser.get( elem, key.replace( rmultiDash, "-$&" ).toLowerCase() );
+
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				camelKey = jQuery.camelCase( key );
+
+				// Attempt to get data from the cache
+				// with the key camelized
+				data = dataUser.get( elem, camelKey );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// Attempt to "discover" the data in
+				// HTML5 custom data-* attrs
+				data = dataAttr( elem, camelKey, undefined );
+				if ( data !== undefined ) {
+					return data;
+				}
+
+				// We tried really hard, but the data doesn't exist.
+				return;
+			}
+
+			// Set the data...
+			camelKey = jQuery.camelCase( key );
+			this.each( function() {
+
+				// First, attempt to store a copy or reference of any
+				// data that might've been store with a camelCased key.
+				var data = dataUser.get( this, camelKey );
+
+				// For HTML5 data-* attribute interop, we have to
+				// store property names with dashes in a camelCase form.
+				// This might not apply to all properties...*
+				dataUser.set( this, camelKey, value );
+
+				// *... In the case of properties that might _actually_
+				// have dashes, we need to also store a copy of that
+				// unchanged property.
+				if ( key.indexOf( "-" ) > -1 && data !== undefined ) {
+					dataUser.set( this, key, value );
+				}
+			} );
+		}, null, value, arguments.length > 1, null, true );
+	},
+
+	removeData: function( key ) {
+		return this.each( function() {
+			dataUser.remove( this, key );
+		} );
+	}
+} );
+
+
+jQuery.extend( {
+	queue: function( elem, type, data ) {
+		var queue;
+
+		if ( elem ) {
+			type = ( type || "fx" ) + "queue";
+			queue = dataPriv.get( elem, type );
+
+			// Speed up dequeue by getting out quickly if this is just a lookup
+			if ( data ) {
+				if ( !queue || jQuery.isArray( data ) ) {
+					queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
+				} else {
+					queue.push( data );
+				}
+			}
+			return queue || [];
+		}
+	},
+
+	dequeue: function( elem, type ) {
+		type = type || "fx";
+
+		var queue = jQuery.queue( elem, type ),
+			startLength = queue.length,
+			fn = queue.shift(),
+			hooks = jQuery._queueHooks( elem, type ),
+			next = function() {
+				jQuery.dequeue( elem, type );
+			};
+
+		// If the fx queue is dequeued, always remove the progress sentinel
+		if ( fn === "inprogress" ) {
+			fn = queue.shift();
+			startLength--;
+		}
+
+		if ( fn ) {
+
+			// Add a progress sentinel to prevent the fx queue from being
+			// automatically dequeued
+			if ( type === "fx" ) {
+				queue.unshift( "inprogress" );
+			}
+
+			// Clear up the last queue stop function
+			delete hooks.stop;
+			fn.call( elem, next, hooks );
+		}
+
+		if ( !startLength && hooks ) {
+			hooks.empty.fire();
+		}
+	},
+
+	// Not public - generate a queueHooks object, or return the current one
+	_queueHooks: function( elem, type ) {
+		var key = type + "queueHooks";
+		return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
+			empty: jQuery.Callbacks( "once memory" ).add( function() {
+				dataPriv.remove( elem, [ type + "queue", key ] );
+			} )
+		} );
+	}
+} );
+
+jQuery.fn.extend( {
+	queue: function( type, data ) {
+		var setter = 2;
+
+		if ( typeof type !== "string" ) {
+			data = type;
+			type = "fx";
+			setter--;
+		}
+
+		if ( arguments.length < setter ) {
+			return jQuery.queue( this[ 0 ], type );
+		}
+
+		return data === undefined ?
+			this :
+			this.each( function() {
+				var queue = jQuery.queue( this, type, data );
+
+				// Ensure a hooks for this queue
+				jQuery._queueHooks( this, type );
+
+				if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
+					jQuery.dequeue( this, type );
+				}
+			} );
+	},
+	dequeue: function( type ) {
+		return this.each( function() {
+			jQuery.dequeue( this, type );
+		} );
+	},
+	clearQueue: function( type ) {
+		return this.queue( type || "fx", [] );
+	},
+
+	// Get a promise resolved when queues of a certain type
+	// are emptied (fx is the type by default)
+	promise: function( type, obj ) {
+		var tmp,
+			count = 1,
+			defer = jQuery.Deferred(),
+			elements = this,
+			i = this.length,
+			resolve = function() {
+				if ( !( --count ) ) {
+					defer.resolveWith( elements, [ elements ] );
+				}
+			};
+
+		if ( typeof type !== "string" ) {
+			obj = type;
+			type = undefined;
+		}
+		type = type || "fx";
+
+		while ( i-- ) {
+			tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
+			if ( tmp && tmp.empty ) {
+				count++;
+				tmp.empty.add( resolve );
+			}
+		}
+		resolve();
+		return defer.promise( obj );
+	}
+} );
+var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
+
+var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
+
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+
+		// isHidden might be called from jQuery#filter function;
+		// in that case, element will be second argument
+		elem = el || elem;
+		return jQuery.css( elem, "display" ) === "none" ||
+			!jQuery.contains( elem.ownerDocument, elem );
+	};
+
+
+
+function adjustCSS( elem, prop, valueParts, tween ) {
+	var adjusted,
+		scale = 1,
+		maxIterations = 20,
+		currentValue = tween ?
+			function() { return tween.cur(); } :
+			function() { return jQuery.css( elem, prop, "" ); },
+		initial = currentValue(),
+		unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+		// Starting value computation is required for potential unit mismatches
+		initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+			rcssNum.exec( jQuery.css( elem, prop ) );
+
+	if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+
+		// Trust units reported by jQuery.css
+		unit = unit || initialInUnit[ 3 ];
+
+		// Make sure we update the tween properties later on
+		valueParts = valueParts || [];
+
+		// Iteratively approximate from a nonzero starting point
+		initialInUnit = +initial || 1;
+
+		do {
+
+			// If previous iteration zeroed out, double until we get *something*.
+			// Use string for doubling so we don't accidentally see scale as unchanged below
+			scale = scale || ".5";
+
+			// Adjust and apply
+			initialInUnit = initialInUnit / scale;
+			jQuery.style( elem, prop, initialInUnit + unit );
+
+		// Update scale, tolerating zero or NaN from tween.cur()
+		// Break the loop if scale is unchanged or perfect, or if we've just had enough.
+		} while (
+			scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
+		);
+	}
+
+	if ( valueParts ) {
+		initialInUnit = +initialInUnit || +initial || 0;
+
+		// Apply relative offset (+=/-=) if specified
+		adjusted = valueParts[ 1 ] ?
+			initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+			+valueParts[ 2 ];
+		if ( tween ) {
+			tween.unit = unit;
+			tween.start = initialInUnit;
+			tween.end = adjusted;
+		}
+	}
+	return adjusted;
+}
+var rcheckableType = ( /^(?:checkbox|radio)$/i );
+
+var rtagName = ( /<([\w:-]+)/ );
+
+var rscriptType = ( /^$|\/(?:java|ecma)script/i );
+
+
+
+// We have to close these tags to support XHTML (#13200)
+var wrapMap = {
+
+	// Support: IE9
+	option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+	// XHTML parsers do not magically insert elements in the
+	// same way that tag soup parsers do. So we cannot shorten
+	// this by omitting <tbody> or other required elements.
+	thead: [ 1, "<table>", "</table>" ],
+	col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+	tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+	td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+	_default: [ 0, "", "" ]
+};
+
+// Support: IE9
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function getAll( context, tag ) {
+
+	// Support: IE9-11+
+	// Use typeof to avoid zero-argument method invocation on host objects (#15151)
+	var ret = typeof context.getElementsByTagName !== "undefined" ?
+			context.getElementsByTagName( tag || "*" ) :
+			typeof context.querySelectorAll !== "undefined" ?
+				context.querySelectorAll( tag || "*" ) :
+			[];
+
+	return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+		jQuery.merge( [ context ], ret ) :
+		ret;
+}
+
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+	var i = 0,
+		l = elems.length;
+
+	for ( ; i < l; i++ ) {
+		dataPriv.set(
+			elems[ i ],
+			"globalEval",
+			!refElements || dataPriv.get( refElements[ i ], "globalEval" )
+		);
+	}
+}
+
+
+var rhtml = /<|&#?\w+;/;
+
+function buildFragment( elems, context, scripts, selection, ignored ) {
+	var elem, tmp, tag, wrap, contains, j,
+		fragment = context.createDocumentFragment(),
+		nodes = [],
+		i = 0,
+		l = elems.length;
+
+	for ( ; i < l; i++ ) {
+		elem = elems[ i ];
+
+		if ( elem || elem === 0 ) {
+
+			// Add nodes directly
+			if ( jQuery.type( elem ) === "object" ) {
+
+				// Support: Android<4.1, PhantomJS<2
+				// push.apply(_, arraylike) throws on ancient WebKit
+				jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+			// Convert non-html into a text node
+			} else if ( !rhtml.test( elem ) ) {
+				nodes.push( context.createTextNode( elem ) );
+
+			// Convert html into DOM nodes
+			} else {
+				tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
+
+				// Deserialize a standard representation
+				tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+				wrap = wrapMap[ tag ] || wrapMap._default;
+				tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
+
+				// Descend through wrappers to the right content
+				j = wrap[ 0 ];
+				while ( j-- ) {
+					tmp = tmp.lastChild;
+				}
+
+				// Support: Android<4.1, PhantomJS<2
+				// push.apply(_, arraylike) throws on ancient WebKit
+				jQuery.merge( nodes, tmp.childNodes );
+
+				// Remember the top-level container
+				tmp = fragment.firstChild;
+
+				// Ensure the created nodes are orphaned (#12392)
+				tmp.textContent = "";
+			}
+		}
+	}
+
+	// Remove wrapper from fragment
+	fragment.textContent = "";
+
+	i = 0;
+	while ( ( elem = nodes[ i++ ] ) ) {
+
+		// Skip elements already in the context collection (trac-4087)
+		if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
+			if ( ignored ) {
+				ignored.push( elem );
+			}
+			continue;
+		}
+
+		contains = jQuery.contains( elem.ownerDocument, elem );
+
+		// Append to fragment
+		tmp = getAll( fragment.appendChild( elem ), "script" );
+
+		// Preserve script evaluation history
+		if ( contains ) {
+			setGlobalEval( tmp );
+		}
+
+		// Capture executables
+		if ( scripts ) {
+			j = 0;
+			while ( ( elem = tmp[ j++ ] ) ) {
+				if ( rscriptType.test( elem.type || "" ) ) {
+					scripts.push( elem );
+				}
+			}
+		}
+	}
+
+	return fragment;
+}
+
+
+( function() {
+	var fragment = document.createDocumentFragment(),
+		div = fragment.appendChild( document.createElement( "div" ) ),
+		input = document.createElement( "input" );
+
+	// Support: Android 4.0-4.3, Safari<=5.1
+	// Check state lost if the name is set (#11217)
+	// Support: Windows Web Apps (WWA)
+	// `name` and `type` must use .setAttribute for WWA (#14901)
+	input.setAttribute( "type", "radio" );
+	input.setAttribute( "checked", "checked" );
+	input.setAttribute( "name", "t" );
+
+	div.appendChild( input );
+
+	// Support: Safari<=5.1, Android<4.2
+	// Older WebKit doesn't clone checked state correctly in fragments
+	support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+	// Support: IE<=11+
+	// Make sure textarea (and checkbox) defaultValue is properly cloned
+	div.innerHTML = "<textarea>x</textarea>";
+	support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+} )();
+
+
+var
+	rkeyEvent = /^key/,
+	rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
+	rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+
+function returnTrue() {
+	return true;
+}
+
+function returnFalse() {
+	return false;
+}
+
+// Support: IE9
+// See #13393 for more info
+function safeActiveElement() {
+	try {
+		return document.activeElement;
+	} catch ( err ) { }
+}
+
+function on( elem, types, selector, data, fn, one ) {
+	var origFn, type;
+
+	// Types can be a map of types/handlers
+	if ( typeof types === "object" ) {
+
+		// ( types-Object, selector, data )
+		if ( typeof selector !== "string" ) {
+
+			// ( types-Object, data )
+			data = data || selector;
+			selector = undefined;
+		}
+		for ( type in types ) {
+			on( elem, type, selector, data, types[ type ], one );
+		}
+		return elem;
+	}
+
+	if ( data == null && fn == null ) {
+
+		// ( types, fn )
+		fn = selector;
+		data = selector = undefined;
+	} else if ( fn == null ) {
+		if ( typeof selector === "string" ) {
+
+			// ( types, selector, fn )
+			fn = data;
+			data = undefined;
+		} else {
+
+			// ( types, data, fn )
+			fn = data;
+			data = selector;
+			selector = undefined;
+		}
+	}
+	if ( fn === false ) {
+		fn = returnFalse;
+	} else if ( !fn ) {
+		return elem;
+	}
+
+	if ( one === 1 ) {
+		origFn = fn;
+		fn = function( event ) {
+
+			// Can use an empty set, since event contains the info
+			jQuery().off( event );
+			return origFn.apply( this, arguments );
+		};
+
+		// Use same guid so caller can remove using origFn
+		fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+	}
+	return elem.each( function() {
+		jQuery.event.add( this, types, fn, data, selector );
+	} );
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+	global: {},
+
+	add: function( elem, types, handler, data, selector ) {
+
+		var handleObjIn, eventHandle, tmp,
+			events, t, handleObj,
+			special, handlers, type, namespaces, origType,
+			elemData = dataPriv.get( elem );
+
+		// Don't attach events to noData or text/comment nodes (but allow plain objects)
+		if ( !elemData ) {
+			return;
+		}
+
+		// Caller can pass in an object of custom data in lieu of the handler
+		if ( handler.handler ) {
+			handleObjIn = handler;
+			handler = handleObjIn.handler;
+			selector = handleObjIn.selector;
+		}
+
+		// Make sure that the handler has a unique ID, used to find/remove it later
+		if ( !handler.guid ) {
+			handler.guid = jQuery.guid++;
+		}
+
+		// Init the element's event structure and main handler, if this is the first
+		if ( !( events = elemData.events ) ) {
+			events = elemData.events = {};
+		}
+		if ( !( eventHandle = elemData.handle ) ) {
+			eventHandle = elemData.handle = function( e ) {
+
+				// Discard the second event of a jQuery.event.trigger() and
+				// when an event is called after a page has unloaded
+				return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
+					jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+			};
+		}
+
+		// Handle multiple events separated by a space
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[ t ] ) || [];
+			type = origType = tmp[ 1 ];
+			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+			// There *must* be a type, no attaching namespace-only handlers
+			if ( !type ) {
+				continue;
+			}
+
+			// If event changes its type, use the special event handlers for the changed type
+			special = jQuery.event.special[ type ] || {};
+
+			// If selector defined, determine special event api type, otherwise given type
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+
+			// Update special based on newly reset type
+			special = jQuery.event.special[ type ] || {};
+
+			// handleObj is passed to all event handlers
+			handleObj = jQuery.extend( {
+				type: type,
+				origType: origType,
+				data: data,
+				handler: handler,
+				guid: handler.guid,
+				selector: selector,
+				needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+				namespace: namespaces.join( "." )
+			}, handleObjIn );
+
+			// Init the event handler queue if we're the first
+			if ( !( handlers = events[ type ] ) ) {
+				handlers = events[ type ] = [];
+				handlers.delegateCount = 0;
+
+				// Only use addEventListener if the special events handler returns false
+				if ( !special.setup ||
+					special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+
+					if ( elem.addEventListener ) {
+						elem.addEventListener( type, eventHandle );
+					}
+				}
+			}
+
+			if ( special.add ) {
+				special.add.call( elem, handleObj );
+
+				if ( !handleObj.handler.guid ) {
+					handleObj.handler.guid = handler.guid;
+				}
+			}
+
+			// Add to the element's handler list, delegates in front
+			if ( selector ) {
+				handlers.splice( handlers.delegateCount++, 0, handleObj );
+			} else {
+				handlers.push( handleObj );
+			}
+
+			// Keep track of which events have ever been used, for event optimization
+			jQuery.event.global[ type ] = true;
+		}
+
+	},
+
+	// Detach an event or set of events from an element
+	remove: function( elem, types, handler, selector, mappedTypes ) {
+
+		var j, origCount, tmp,
+			events, t, handleObj,
+			special, handlers, type, namespaces, origType,
+			elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
+
+		if ( !elemData || !( events = elemData.events ) ) {
+			return;
+		}
+
+		// Once for each type.namespace in types; type may be omitted
+		types = ( types || "" ).match( rnotwhite ) || [ "" ];
+		t = types.length;
+		while ( t-- ) {
+			tmp = rtypenamespace.exec( types[ t ] ) || [];
+			type = origType = tmp[ 1 ];
+			namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+			// Unbind all events (on this namespace, if provided) for the element
+			if ( !type ) {
+				for ( type in events ) {
+					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+				}
+				continue;
+			}
+
+			special = jQuery.event.special[ type ] || {};
+			type = ( selector ? special.delegateType : special.bindType ) || type;
+			handlers = events[ type ] || [];
+			tmp = tmp[ 2 ] &&
+				new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
+
+			// Remove matching events
+			origCount = j = handlers.length;
+			while ( j-- ) {
+				handleObj = handlers[ j ];
+
+				if ( ( mappedTypes || origType === handleObj.origType ) &&
+					( !handler || handler.guid === handleObj.guid ) &&
+					( !tmp || tmp.test( handleObj.namespace ) ) &&
+					( !selector || selector === handleObj.selector ||
+						selector === "**" && handleObj.selector ) ) {
+					handlers.splice( j, 1 );
+
+					if ( handleObj.selector ) {
+						handlers.delegateCount--;
+					}
+					if ( special.remove ) {
+						special.remove.call( elem, handleObj );
+					}
+				}
+			}
+
+			// Remove generic event handler if we removed something and no more handlers exist
+			// (avoids potential for endless recursion during removal of special event handlers)
+			if ( origCount && !handlers.length ) {
+				if ( !special.teardown ||
+					special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+
+					jQuery.removeEvent( elem, type, elemData.handle );
+				}
+
+				delete events[ type ];
+			}
+		}
+
+		// Remove data and the expando if it's no longer used
+		if ( jQuery.isEmptyObject( events ) ) {
+			dataPriv.remove( elem, "handle events" );
+		}
+	},
+
+	dispatch: function( event ) {
+
+		// Make a writable jQuery.Event from the native event object
+		event = jQuery.event.fix( event );
+
+		var i, j, ret, matched, handleObj,
+			handlerQueue = [],
+			args = slice.call( arguments ),
+			handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
+			special = jQuery.event.special[ event.type ] || {};
+
+		// Use the fix-ed jQuery.Event rather than the (read-only) native event
+		args[ 0 ] = event;
+		event.delegateTarget = this;
+
+		// Call the preDispatch hook for the mapped type, and let it bail if desired
+		if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+			return;
+		}
+
+		// Determine handlers
+		handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+		// Run delegates first; they may want to stop propagation beneath us
+		i = 0;
+		while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
+			event.currentTarget = matched.elem;
+
+			j = 0;
+			while ( ( handleObj = matched.handlers[ j++ ] ) &&
+				!event.isImmediatePropagationStopped() ) {
+
+				// Triggered event must either 1) have no namespace, or 2) have namespace(s)
+				// a subset or equal to those in the bound event (both can have no namespace).
+				if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
+
+					event.handleObj = handleObj;
+					event.data = handleObj.data;
+
+					ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
+						handleObj.handler ).apply( matched.elem, args );
+
+					if ( ret !== undefined ) {
+						if ( ( event.result = ret ) === false ) {
+							event.preventDefault();
+							event.stopPropagation();
+						}
+					}
+				}
+			}
+		}
+
+		// Call the postDispatch hook for the mapped type
+		if ( special.postDispatch ) {
+			special.postDispatch.call( this, event );
+		}
+
+		return event.result;
+	},
+
+	handlers: function( event, handlers ) {
+		var i, matches, sel, handleObj,
+			handlerQueue = [],
+			delegateCount = handlers.delegateCount,
+			cur = event.target;
+
+		// Support (at least): Chrome, IE9
+		// Find delegate handlers
+		// Black-hole SVG <use> instance trees (#13180)
+		//
+		// Support: Firefox<=42+
+		// Avoid non-left-click in FF but don't block IE radio events (#3861, gh-2343)
+		if ( delegateCount && cur.nodeType &&
+			( event.type !== "click" || isNaN( event.button ) || event.button < 1 ) ) {
+
+			for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+				// Don't check non-elements (#13208)
+				// Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+				if ( cur.nodeType === 1 && ( cur.disabled !== true || event.type !== "click" ) ) {
+					matches = [];
+					for ( i = 0; i < delegateCount; i++ ) {
+						handleObj = handlers[ i ];
+
+						// Don't conflict with Object.prototype properties (#13203)
+						sel = handleObj.selector + " ";
+
+						if ( matches[ sel ] === undefined ) {
+							matches[ sel ] = handleObj.needsContext ?
+								jQuery( sel, this ).index( cur ) > -1 :
+								jQuery.find( sel, this, null, [ cur ] ).length;
+						}
+						if ( matches[ sel ] ) {
+							matches.push( handleObj );
+						}
+					}
+					if ( matches.length ) {
+						handlerQueue.push( { elem: cur, handlers: matches } );
+					}
+				}
+			}
+		}
+
+		// Add the remaining (directly-bound) handlers
+		if ( delegateCount < handlers.length ) {
+			handlerQueue.push( { elem: this, handlers: handlers.slice( delegateCount ) } );
+		}
+
+		return handlerQueue;
+	},
+
+	// Includes some event props shared by KeyEvent and MouseEvent
+	props: ( "altKey bubbles cancelable ctrlKey currentTarget detail eventPhase " +
+		"metaKey relatedTarget shiftKey target timeStamp view which" ).split( " " ),
+
+	fixHooks: {},
+
+	keyHooks: {
+		props: "char charCode key keyCode".split( " " ),
+		filter: function( event, original ) {
+
+			// Add which for key events
+			if ( event.which == null ) {
+				event.which = original.charCode != null ? original.charCode : original.keyCode;
+			}
+
+			return event;
+		}
+	},
+
+	mouseHooks: {
+		props: ( "button buttons clientX clientY offsetX offsetY pageX pageY " +
+			"screenX screenY toElement" ).split( " " ),
+		filter: function( event, original ) {
+			var eventDoc, doc, body,
+				button = original.button;
+
+			// Calculate pageX/Y if missing and clientX/Y available
+			if ( event.pageX == null && original.clientX != null ) {
+				eventDoc = event.target.ownerDocument || document;
+				doc = eventDoc.documentElement;
+				body = eventDoc.body;
+
+				event.pageX = original.clientX +
+					( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) -
+					( doc && doc.clientLeft || body && body.clientLeft || 0 );
+				event.pageY = original.clientY +
+					( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) -
+					( doc && doc.clientTop  || body && body.clientTop  || 0 );
+			}
+
+			// Add which for click: 1 === left; 2 === middle; 3 === right
+			// Note: button is not normalized, so don't use it
+			if ( !event.which && button !== undefined ) {
+				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+			}
+
+			return event;
+		}
+	},
+
+	fix: function( event ) {
+		if ( event[ jQuery.expando ] ) {
+			return event;
+		}
+
+		// Create a writable copy of the event object and normalize some properties
+		var i, prop, copy,
+			type = event.type,
+			originalEvent = event,
+			fixHook = this.fixHooks[ type ];
+
+		if ( !fixHook ) {
+			this.fixHooks[ type ] = fixHook =
+				rmouseEvent.test( type ) ? this.mouseHooks :
+				rkeyEvent.test( type ) ? this.keyHooks :
+				{};
+		}
+		copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+		event = new jQuery.Event( originalEvent );
+
+		i = copy.length;
+		while ( i-- ) {
+			prop = copy[ i ];
+			event[ prop ] = originalEvent[ prop ];
+		}
+
+		// Support: Cordova 2.5 (WebKit) (#13255)
+		// All events should have a target; Cordova deviceready doesn't
+		if ( !event.target ) {
+			event.target = document;
+		}
+
+		// Support: Safari 6.0+, Chrome<28
+		// Target should not be a text node (#504, #13143)
+		if ( event.target.nodeType === 3 ) {
+			event.target = event.target.parentNode;
+		}
+
+		return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+	},
+
+	special: {
+		load: {
+
+			// Prevent triggered image.load events from bubbling to window.load
+			noBubble: true
+		},
+		focus: {
+
+			// Fire native event if possible so blur/focus sequence is correct
+			trigger: function() {
+				if ( this !== safeActiveElement() && this.focus ) {
+					this.focus();
+					return false;
+				}
+			},
+			delegateType: "focusin"
+		},
+		blur: {
+			trigger: function() {
+				if ( this === safeActiveElement() && this.blur ) {
+					this.blur();
+					return false;
+				}
+			},
+			delegateType: "focusout"
+		},
+		click: {
+
+			// For checkbox, fire native event so checked state will be right
+			trigger: function() {
+				if ( this.type === "checkbox" && this.click && jQuery.nodeName( this, "input" ) ) {
+					this.click();
+					return false;
+				}
+			},
+
+			// For cross-browser consistency, don't fire native .click() on links
+			_default: function( event ) {
+				return jQuery.nodeName( event.target, "a" );
+			}
+		},
+
+		beforeunload: {
+			postDispatch: function( event ) {
+
+				// Support: Firefox 20+
+				// Firefox doesn't alert if the returnValue field is not set.
+				if ( event.result !== undefined && event.originalEvent ) {
+					event.originalEvent.returnValue = event.result;
+				}
+			}
+		}
+	}
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+
+	// This "if" is needed for plain objects
+	if ( elem.removeEventListener ) {
+		elem.removeEventListener( type, handle );
+	}
+};
+
+jQuery.Event = function( src, props ) {
+
+	// Allow instantiation without the 'new' keyword
+	if ( !( this instanceof jQuery.Event ) ) {
+		return new jQuery.Event( src, props );
+	}
+
+	// Event object
+	if ( src && src.type ) {
+		this.originalEvent = src;
+		this.type = src.type;
+
+		// Events bubbling up the document may have been marked as prevented
+		// by a handler lower down the tree; reflect the correct value.
+		this.isDefaultPrevented = src.defaultPrevented ||
+				src.defaultPrevented === undefined &&
+
+				// Support: Android<4.0
+				src.returnValue === false ?
+			returnTrue :
+			returnFalse;
+
+	// Event type
+	} else {
+		this.type = src;
+	}
+
+	// Put explicitly provided properties onto the event object
+	if ( props ) {
+		jQuery.extend( this, props );
+	}
+
+	// Create a timestamp if incoming event doesn't have one
+	this.timeStamp = src && src.timeStamp || jQuery.now();
+
+	// Mark it as fixed
+	this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+	constructor: jQuery.Event,
+	isDefaultPrevented: returnFalse,
+	isPropagationStopped: returnFalse,
+	isImmediatePropagationStopped: returnFalse,
+	isSimulated: false,
+
+	preventDefault: function() {
+		var e = this.originalEvent;
+
+		this.isDefaultPrevented = returnTrue;
+
+		if ( e && !this.isSimulated ) {
+			e.preventDefault();
+		}
+	},
+	stopPropagation: function() {
+		var e = this.originalEvent;
+
+		this.isPropagationStopped = returnTrue;
+
+		if ( e && !this.isSimulated ) {
+			e.stopPropagation();
+		}
+	},
+	stopImmediatePropagation: function() {
+		var e = this.originalEvent;
+
+		this.isImmediatePropagationStopped = returnTrue;
+
+		if ( e && !this.isSimulated ) {
+			e.stopImmediatePropagation();
+		}
+
+		this.stopPropagation();
+	}
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// so that event delegation works in jQuery.
+// Do the same for pointerenter/pointerleave and pointerover/pointerout
+//
+// Support: Safari 7 only
+// Safari sends mouseenter too often; see:
+// https://code.google.com/p/chromium/issues/detail?id=470258
+// for the description of the bug (it existed in older Chrome versions as well).
+jQuery.each( {
+	mouseenter: "mouseover",
+	mouseleave: "mouseout",
+	pointerenter: "pointerover",
+	pointerleave: "pointerout"
+}, function( orig, fix ) {
+	jQuery.event.special[ orig ] = {
+		delegateType: fix,
+		bindType: fix,
+
+		handle: function( event ) {
+			var ret,
+				target = this,
+				related = event.relatedTarget,
+				handleObj = event.handleObj;
+
+			// For mouseenter/leave call the handler if related is outside the target.
+			// NB: No relatedTarget if the mouse left/entered the browser window
+			if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
+				event.type = handleObj.origType;
+				ret = handleObj.handler.apply( this, arguments );
+				event.type = fix;
+			}
+			return ret;
+		}
+	};
+} );
+
+jQuery.fn.extend( {
+	on: function( types, selector, data, fn ) {
+		return on( this, types, selector, data, fn );
+	},
+	one: function( types, selector, data, fn ) {
+		return on( this, types, selector, data, fn, 1 );
+	},
+	off: function( types, selector, fn ) {
+		var handleObj, type;
+		if ( types && types.preventDefault && types.handleObj ) {
+
+			// ( event )  dispatched jQuery.Event
+			handleObj = types.handleObj;
+			jQuery( types.delegateTarget ).off(
+				handleObj.namespace ?
+					handleObj.origType + "." + handleObj.namespace :
+					handleObj.origType,
+				handleObj.selector,
+				handleObj.handler
+			);
+			return this;
+		}
+		if ( typeof types === "object" ) {
+
+			// ( types-object [, selector] )
+			for ( type in types ) {
+				this.off( type, selector, types[ type ] );
+			}
+			return this;
+		}
+		if ( selector === false || typeof selector === "function" ) {
+
+			// ( types [, fn] )
+			fn = selector;
+			selector = undefined;
+		}
+		if ( fn === false ) {
+			fn = returnFalse;
+		}
+		return this.each( function() {
+			jQuery.event.remove( this, types, fn, selector );
+		} );
+	}
+} );
+
+
+var
+	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:-]+)[^>]*)\/>/gi,
+
+	// Support: IE 10-11, Edge 10240+
+	// In IE/Edge using regex groups here causes severe slowdowns.
+	// See https://connect.microsoft.com/IE/feedback/details/1736512/
+	rnoInnerhtml = /<script|<style|<link/i,
+
+	// checked="checked" or checked
+	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+	rscriptTypeMasked = /^true\/(.*)/,
+	rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
+
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+	return jQuery.nodeName( elem, "table" ) &&
+		jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+		elem.getElementsByTagName( "tbody" )[ 0 ] ||
+			elem.appendChild( elem.ownerDocument.createElement( "tbody" ) ) :
+		elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+	elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
+	return elem;
+}
+function restoreScript( elem ) {
+	var match = rscriptTypeMasked.exec( elem.type );
+
+	if ( match ) {
+		elem.type = match[ 1 ];
+	} else {
+		elem.removeAttribute( "type" );
+	}
+
+	return elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+	var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+	if ( dest.nodeType !== 1 ) {
+		return;
+	}
+
+	// 1. Copy private data: events, handlers, etc.
+	if ( dataPriv.hasData( src ) ) {
+		pdataOld = dataPriv.access( src );
+		pdataCur = dataPriv.set( dest, pdataOld );
+		events = pdataOld.events;
+
+		if ( events ) {
+			delete pdataCur.handle;
+			pdataCur.events = {};
+
+			for ( type in events ) {
+				for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+					jQuery.event.add( dest, type, events[ type ][ i ] );
+				}
+			}
+		}
+	}
+
+	// 2. Copy user data
+	if ( dataUser.hasData( src ) ) {
+		udataOld = dataUser.access( src );
+		udataCur = jQuery.extend( {}, udataOld );
+
+		dataUser.set( dest, udataCur );
+	}
+}
+
+// Fix IE bugs, see support tests
+function fixInput( src, dest ) {
+	var nodeName = dest.nodeName.toLowerCase();
+
+	// Fails to persist the checked state of a cloned checkbox or radio button.
+	if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+		dest.checked = src.checked;
+
+	// Fails to return the selected option to the default selected state when cloning options
+	} else if ( nodeName === "input" || nodeName === "textarea" ) {
+		dest.defaultValue = src.defaultValue;
+	}
+}
+
+function domManip( collection, args, callback, ignored ) {
+
+	// Flatten any nested arrays
+	args = concat.apply( [], args );
+
+	var fragment, first, scripts, hasScripts, node, doc,
+		i = 0,
+		l = collection.length,
+		iNoClone = l - 1,
+		value = args[ 0 ],
+		isFunction = jQuery.isFunction( value );
+
+	// We can't cloneNode fragments that contain checked, in WebKit
+	if ( isFunction ||
+			( l > 1 && typeof value === "string" &&
+				!support.checkClone && rchecked.test( value ) ) ) {
+		return collection.each( function( index ) {
+			var self = collection.eq( index );
+			if ( isFunction ) {
+				args[ 0 ] = value.call( this, index, self.html() );
+			}
+			domManip( self, args, callback, ignored );
+		} );
+	}
+
+	if ( l ) {
+		fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
+		first = fragment.firstChild;
+
+		if ( fragment.childNodes.length === 1 ) {
+			fragment = first;
+		}
+
+		// Require either new content or an interest in ignored elements to invoke the callback
+		if ( first || ignored ) {
+			scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+			hasScripts = scripts.length;
+
+			// Use the original fragment for the last item
+			// instead of the first because it can end up
+			// being emptied incorrectly in certain situations (#8070).
+			for ( ; i < l; i++ ) {
+				node = fragment;
+
+				if ( i !== iNoClone ) {
+					node = jQuery.clone( node, true, true );
+
+					// Keep references to cloned scripts for later restoration
+					if ( hasScripts ) {
+
+						// Support: Android<4.1, PhantomJS<2
+						// push.apply(_, arraylike) throws on ancient WebKit
+						jQuery.merge( scripts, getAll( node, "script" ) );
+					}
+				}
+
+				callback.call( collection[ i ], node, i );
+			}
+
+			if ( hasScripts ) {
+				doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+				// Reenable scripts
+				jQuery.map( scripts, restoreScript );
+
+				// Evaluate executable scripts on first document insertion
+				for ( i = 0; i < hasScripts; i++ ) {
+					node = scripts[ i ];
+					if ( rscriptType.test( node.type || "" ) &&
+						!dataPriv.access( node, "globalEval" ) &&
+						jQuery.contains( doc, node ) ) {
+
+						if ( node.src ) {
+
+							// Optional AJAX dependency, but won't run scripts if not present
+							if ( jQuery._evalUrl ) {
+								jQuery._evalUrl( node.src );
+							}
+						} else {
+							jQuery.globalEval( node.textContent.replace( rcleanScript, "" ) );
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return collection;
+}
+
+function remove( elem, selector, keepData ) {
+	var node,
+		nodes = selector ? jQuery.filter( selector, elem ) : elem,
+		i = 0;
+
+	for ( ; ( node = nodes[ i ] ) != null; i++ ) {
+		if ( !keepData && node.nodeType === 1 ) {
+			jQuery.cleanData( getAll( node ) );
+		}
+
+		if ( node.parentNode ) {
+			if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
+				setGlobalEval( getAll( node, "script" ) );
+			}
+			node.parentNode.removeChild( node );
+		}
+	}
+
+	return elem;
+}
+
+jQuery.extend( {
+	htmlPrefilter: function( html ) {
+		return html.replace( rxhtmlTag, "<$1></$2>" );
+	},
+
+	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+		var i, l, srcElements, destElements,
+			clone = elem.cloneNode( true ),
+			inPage = jQuery.contains( elem.ownerDocument, elem );
+
+		// Fix IE cloning issues
+		if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+				!jQuery.isXMLDoc( elem ) ) {
+
+			// We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+			destElements = getAll( clone );
+			srcElements = getAll( elem );
+
+			for ( i = 0, l = srcElements.length; i < l; i++ ) {
+				fixInput( srcElements[ i ], destElements[ i ] );
+			}
+		}
+
+		// Copy the events from the original to the clone
+		if ( dataAndEvents ) {
+			if ( deepDataAndEvents ) {
+				srcElements = srcElements || getAll( elem );
+				destElements = destElements || getAll( clone );
+
+				for ( i = 0, l = srcElements.length; i < l; i++ ) {
+					cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+				}
+			} else {
+				cloneCopyEvent( elem, clone );
+			}
+		}
+
+		// Preserve script evaluation history
+		destElements = getAll( clone, "script" );
+		if ( destElements.length > 0 ) {
+			setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+		}
+
+		// Return the cloned set
+		return clone;
+	},
+
+	cleanData: function( elems ) {
+		var data, elem, type,
+			special = jQuery.event.special,
+			i = 0;
+
+		for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
+			if ( acceptData( elem ) ) {
+				if ( ( data = elem[ dataPriv.expando ] ) ) {
+					if ( data.events ) {
+						for ( type in data.events ) {
+							if ( special[ type ] ) {
+								jQuery.event.remove( elem, type );
+
+							// This is a shortcut to avoid jQuery.event.remove's overhead
+							} else {
+								jQuery.removeEvent( elem, type, data.handle );
+							}
+						}
+					}
+
+					// Support: Chrome <= 35-45+
+					// Assign undefined instead of using delete, see Data#remove
+					elem[ dataPriv.expando ] = undefined;
+				}
+				if ( elem[ dataUser.expando ] ) {
+
+					// Support: Chrome <= 35-45+
+					// Assign undefined instead of using delete, see Data#remove
+					elem[ dataUser.expando ] = undefined;
+				}
+			}
+		}
+	}
+} );
+
+jQuery.fn.extend( {
+
+	// Keep domManip exposed until 3.0 (gh-2225)
+	domManip: domManip,
+
+	detach: function( selector ) {
+		return remove( this, selector, true );
+	},
+
+	remove: function( selector ) {
+		return remove( this, selector );
+	},
+
+	text: function( value ) {
+		return access( this, function( value ) {
+			return value === undefined ?
+				jQuery.text( this ) :
+				this.empty().each( function() {
+					if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+						this.textContent = value;
+					}
+				} );
+		}, null, value, arguments.length );
+	},
+
+	append: function() {
+		return domManip( this, arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.appendChild( elem );
+			}
+		} );
+	},
+
+	prepend: function() {
+		return domManip( this, arguments, function( elem ) {
+			if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+				var target = manipulationTarget( this, elem );
+				target.insertBefore( elem, target.firstChild );
+			}
+		} );
+	},
+
+	before: function() {
+		return domManip( this, arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this );
+			}
+		} );
+	},
+
+	after: function() {
+		return domManip( this, arguments, function( elem ) {
+			if ( this.parentNode ) {
+				this.parentNode.insertBefore( elem, this.nextSibling );
+			}
+		} );
+	},
+
+	empty: function() {
+		var elem,
+			i = 0;
+
+		for ( ; ( elem = this[ i ] ) != null; i++ ) {
+			if ( elem.nodeType === 1 ) {
+
+				// Prevent memory leaks
+				jQuery.cleanData( getAll( elem, false ) );
+
+				// Remove any remaining nodes
+				elem.textContent = "";
+			}
+		}
+
+		return this;
+	},
+
+	clone: function( dataAndEvents, deepDataAndEvents ) {
+		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+		return this.map( function() {
+			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+		} );
+	},
+
+	html: function( value ) {
+		return access( this, function( value ) {
+			var elem = this[ 0 ] || {},
+				i = 0,
+				l = this.length;
+
+			if ( value === undefined && elem.nodeType === 1 ) {
+				return elem.innerHTML;
+			}
+
+			// See if we can take a shortcut and just use innerHTML
+			if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+				!wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+				value = jQuery.htmlPrefilter( value );
+
+				try {
+					for ( ; i < l; i++ ) {
+						elem = this[ i ] || {};
+
+						// Remove element nodes and prevent memory leaks
+						if ( elem.nodeType === 1 ) {
+							jQuery.cleanData( getAll( elem, false ) );
+							elem.innerHTML = value;
+						}
+					}
+
+					elem = 0;
+
+				// If using innerHTML throws an exception, use the fallback method
+				} catch ( e ) {}
+			}
+
+			if ( elem ) {
+				this.empty().append( value );
+			}
+		}, null, value, arguments.length );
+	},
+
+	replaceWith: function() {
+		var ignored = [];
+
+		// Make the changes, replacing each non-ignored context element with the new content
+		return domManip( this, arguments, function( elem ) {
+			var parent = this.parentNode;
+
+			if ( jQuery.inArray( this, ignored ) < 0 ) {
+				jQuery.cleanData( getAll( this ) );
+				if ( parent ) {
+					parent.replaceChild( elem, this );
+				}
+			}
+
+		// Force callback invocation
+		}, ignored );
+	}
+} );
+
+jQuery.each( {
+	appendTo: "append",
+	prependTo: "prepend",
+	insertBefore: "before",
+	insertAfter: "after",
+	replaceAll: "replaceWith"
+}, function( name, original ) {
+	jQuery.fn[ name ] = function( selector ) {
+		var elems,
+			ret = [],
+			insert = jQuery( selector ),
+			last = insert.length - 1,
+			i = 0;
+
+		for ( ; i <= last; i++ ) {
+			elems = i === last ? this : this.clone( true );
+			jQuery( insert[ i ] )[ original ]( elems );
+
+			// Support: QtWebKit
+			// .get() because push.apply(_, arraylike) throws
+			push.apply( ret, elems.get() );
+		}
+
+		return this.pushStack( ret );
+	};
+} );
+
+
+var iframe,
+	elemdisplay = {
+
+		// Support: Firefox
+		// We have to pre-define these values for FF (#10227)
+		HTML: "block",
+		BODY: "block"
+	};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+	var elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+		display = jQuery.css( elem[ 0 ], "display" );
+
+	// We don't have any data stored on the element,
+	// so use "detach" method as fast way to get rid of the element
+	elem.detach();
+
+	return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+	var doc = document,
+		display = elemdisplay[ nodeName ];
+
+	if ( !display ) {
+		display = actualDisplay( nodeName, doc );
+
+		// If the simple way fails, read from inside an iframe
+		if ( display === "none" || !display ) {
+
+			// Use the already-created iframe if possible
+			iframe = ( iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" ) )
+				.appendTo( doc.documentElement );
+
+			// Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+			doc = iframe[ 0 ].contentDocument;
+
+			// Support: IE
+			doc.write();
+			doc.close();
+
+			display = actualDisplay( nodeName, doc );
+			iframe.detach();
+		}
+
+		// Store the correct default display
+		elemdisplay[ nodeName ] = display;
+	}
+
+	return display;
+}
+var rmargin = ( /^margin/ );
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+var getStyles = function( elem ) {
+
+		// Support: IE<=11+, Firefox<=30+ (#15098, #14150)
+		// IE throws on elements created in popups
+		// FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+		var view = elem.ownerDocument.defaultView;
+
+		if ( !view || !view.opener ) {
+			view = window;
+		}
+
+		return view.getComputedStyle( elem );
+	};
+
+var swap = function( elem, options, callback, args ) {
+	var ret, name,
+		old = {};
+
+	// Remember the old values, and insert the new ones
+	for ( name in options ) {
+		old[ name ] = elem.style[ name ];
+		elem.style[ name ] = options[ name ];
+	}
+
+	ret = callback.apply( elem, args || [] );
+
+	// Revert the old values
+	for ( name in options ) {
+		elem.style[ name ] = old[ name ];
+	}
+
+	return ret;
+};
+
+
+var documentElement = document.documentElement;
+
+
+
+( function() {
+	var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
+		container = document.createElement( "div" ),
+		div = document.createElement( "div" );
+
+	// Finish early in limited (non-browser) environments
+	if ( !div.style ) {
+		return;
+	}
+
+	// Support: IE9-11+
+	// Style of cloned element affects source element cloned (#8908)
+	div.style.backgroundClip = "content-box";
+	div.cloneNode( true ).style.backgroundClip = "";
+	support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+	container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
+		"padding:0;margin-top:1px;position:absolute";
+	container.appendChild( div );
+
+	// Executing both pixelPosition & boxSizingReliable tests require only one layout
+	// so they're executed at the same time to save the second computation.
+	function computeStyleTests() {
+		div.style.cssText =
+
+			// Support: Firefox<29, Android 2.3
+			// Vendor-prefix box-sizing
+			"-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;" +
+			"position:relative;display:block;" +
+			"margin:auto;border:1px;padding:1px;" +
+			"top:1%;width:50%";
+		div.innerHTML = "";
+		documentElement.appendChild( container );
+
+		var divStyle = window.getComputedStyle( div );
+		pixelPositionVal = divStyle.top !== "1%";
+		reliableMarginLeftVal = divStyle.marginLeft === "2px";
+		boxSizingReliableVal = divStyle.width === "4px";
+
+		// Support: Android 4.0 - 4.3 only
+		// Some styles come back with percentage values, even though they shouldn't
+		div.style.marginRight = "50%";
+		pixelMarginRightVal = divStyle.marginRight === "4px";
+
+		documentElement.removeChild( container );
+	}
+
+	jQuery.extend( support, {
+		pixelPosition: function() {
+
+			// This test is executed only once but we still do memoizing
+			// since we can use the boxSizingReliable pre-computing.
+			// No need to check if the test was already performed, though.
+			computeStyleTests();
+			return pixelPositionVal;
+		},
+		boxSizingReliable: function() {
+			if ( boxSizingReliableVal == null ) {
+				computeStyleTests();
+			}
+			return boxSizingReliableVal;
+		},
+		pixelMarginRight: function() {
+
+			// Support: Android 4.0-4.3
+			// We're checking for boxSizingReliableVal here instead of pixelMarginRightVal
+			// since that compresses better and they're computed together anyway.
+			if ( boxSizingReliableVal == null ) {
+				computeStyleTests();
+			}
+			return pixelMarginRightVal;
+		},
+		reliableMarginLeft: function() {
+
+			// Support: IE <=8 only, Android 4.0 - 4.3 only, Firefox <=3 - 37
+			if ( boxSizingReliableVal == null ) {
+				computeStyleTests();
+			}
+			return reliableMarginLeftVal;
+		},
+		reliableMarginRight: function() {
+
+			// Support: Android 2.3
+			// Check if div with explicit width and no margin-right incorrectly
+			// gets computed margin-right based on width of container. (#3333)
+			// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+			// This support function is only executed once so no memoizing is needed.
+			var ret,
+				marginDiv = div.appendChild( document.createElement( "div" ) );
+
+			// Reset CSS: box-sizing; display; margin; border; padding
+			marginDiv.style.cssText = div.style.cssText =
+
+				// Support: Android 2.3
+				// Vendor-prefix box-sizing
+				"-webkit-box-sizing:content-box;box-sizing:content-box;" +
+				"display:block;margin:0;border:0;padding:0";
+			marginDiv.style.marginRight = marginDiv.style.width = "0";
+			div.style.width = "1px";
+			documentElement.appendChild( container );
+
+			ret = !parseFloat( window.getComputedStyle( marginDiv ).marginRight );
+
+			documentElement.removeChild( container );
+			div.removeChild( marginDiv );
+
+			return ret;
+		}
+	} );
+} )();
+
+
+function curCSS( elem, name, computed ) {
+	var width, minWidth, maxWidth, ret,
+		style = elem.style;
+
+	computed = computed || getStyles( elem );
+	ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+	// Support: Opera 12.1x only
+	// Fall back to style even without computed
+	// computed is undefined for elems on document fragments
+	if ( ( ret === "" || ret === undefined ) && !jQuery.contains( elem.ownerDocument, elem ) ) {
+		ret = jQuery.style( elem, name );
+	}
+
+	// Support: IE9
+	// getPropertyValue is only needed for .css('filter') (#12537)
+	if ( computed ) {
+
+		// A tribute to the "awesome hack by Dean Edwards"
+		// Android Browser returns percentage for some values,
+		// but width seems to be reliably pixels.
+		// This is against the CSSOM draft spec:
+		// http://dev.w3.org/csswg/cssom/#resolved-values
+		if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+			// Remember the original values
+			width = style.width;
+			minWidth = style.minWidth;
+			maxWidth = style.maxWidth;
+
+			// Put in the new values to get a computed value out
+			style.minWidth = style.maxWidth = style.width = ret;
+			ret = computed.width;
+
+			// Revert the changed values
+			style.width = width;
+			style.minWidth = minWidth;
+			style.maxWidth = maxWidth;
+		}
+	}
+
+	return ret !== undefined ?
+
+		// Support: IE9-11+
+		// IE returns zIndex value as an integer.
+		ret + "" :
+		ret;
+}
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+
+	// Define the hook, we'll check on the first run if it's really needed.
+	return {
+		get: function() {
+			if ( conditionFn() ) {
+
+				// Hook not needed (or it's not possible to use it due
+				// to missing dependency), remove it.
+				delete this.get;
+				return;
+			}
+
+			// Hook needed; redefine it so that the support test is not executed again.
+			return ( this.get = hookFn ).apply( this, arguments );
+		}
+	};
+}
+
+
+var
+
+	// Swappable if display is none or starts with table
+	// except "table", "table-cell", or "table-caption"
+	// See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+	rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+
+	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+	cssNormalTransform = {
+		letterSpacing: "0",
+		fontWeight: "400"
+	},
+
+	cssPrefixes = [ "Webkit", "O", "Moz", "ms" ],
+	emptyStyle = document.createElement( "div" ).style;
+
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( name ) {
+
+	// Shortcut for names that are not vendor prefixed
+	if ( name in emptyStyle ) {
+		return name;
+	}
+
+	// Check for vendor prefixed names
+	var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
+		i = cssPrefixes.length;
+
+	while ( i-- ) {
+		name = cssPrefixes[ i ] + capName;
+		if ( name in emptyStyle ) {
+			return name;
+		}
+	}
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+
+	// Any relative (+/-) values have already been
+	// normalized at this point
+	var matches = rcssNum.exec( value );
+	return matches ?
+
+		// Guard against undefined "subtract", e.g., when used as in cssHooks
+		Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
+		value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+	var i = extra === ( isBorderBox ? "border" : "content" ) ?
+
+		// If we already have the right measurement, avoid augmentation
+		4 :
+
+		// Otherwise initialize for horizontal or vertical properties
+		name === "width" ? 1 : 0,
+
+		val = 0;
+
+	for ( ; i < 4; i += 2 ) {
+
+		// Both box models exclude margin, so add it if we want it
+		if ( extra === "margin" ) {
+			val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+		}
+
+		if ( isBorderBox ) {
+
+			// border-box includes padding, so remove it if we want content
+			if ( extra === "content" ) {
+				val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+			}
+
+			// At this point, extra isn't border nor margin, so remove border
+			if ( extra !== "margin" ) {
+				val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		} else {
+
+			// At this point, extra isn't content, so add padding
+			val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+			// At this point, extra isn't content nor padding, so add border
+			if ( extra !== "padding" ) {
+				val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+			}
+		}
+	}
+
+	return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+	// Start with offset property, which is equivalent to the border-box value
+	var valueIsBorderBox = true,
+		val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+		styles = getStyles( elem ),
+		isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+	// Some non-html elements return undefined for offsetWidth, so check for null/undefined
+	// svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+	// MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+	if ( val <= 0 || val == null ) {
+
+		// Fall back to computed then uncomputed css if necessary
+		val = curCSS( elem, name, styles );
+		if ( val < 0 || val == null ) {
+			val = elem.style[ name ];
+		}
+
+		// Computed unit is not pixels. Stop here and return.
+		if ( rnumnonpx.test( val ) ) {
+			return val;
+		}
+
+		// Check for style in case a browser which returns unreliable values
+		// for getComputedStyle silently falls back to the reliable elem.style
+		valueIsBorderBox = isBorderBox &&
+			( support.boxSizingReliable() || val === elem.style[ name ] );
+
+		// Normalize "", auto, and prepare for extra
+		val = parseFloat( val ) || 0;
+	}
+
+	// Use the active box-sizing model to add/subtract irrelevant styles
+	return ( val +
+		augmentWidthOrHeight(
+			elem,
+			name,
+			extra || ( isBorderBox ? "border" : "content" ),
+			valueIsBorderBox,
+			styles
+		)
+	) + "px";
+}
+
+function showHide( elements, show ) {
+	var display, elem, hidden,
+		values = [],
+		index = 0,
+		length = elements.length;
+
+	for ( ; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+
+		values[ index ] = dataPriv.get( elem, "olddisplay" );
+		display = elem.style.display;
+		if ( show ) {
+
+			// Reset the inline display of this element to learn if it is
+			// being hidden by cascaded rules or not
+			if ( !values[ index ] && display === "none" ) {
+				elem.style.display = "";
+			}
+
+			// Set elements which have been overridden with display: none
+			// in a stylesheet to whatever the default browser style is
+			// for such an element
+			if ( elem.style.display === "" && isHidden( elem ) ) {
+				values[ index ] = dataPriv.access(
+					elem,
+					"olddisplay",
+					defaultDisplay( elem.nodeName )
+				);
+			}
+		} else {
+			hidden = isHidden( elem );
+
+			if ( display !== "none" || !hidden ) {
+				dataPriv.set(
+					elem,
+					"olddisplay",
+					hidden ? display : jQuery.css( elem, "display" )
+				);
+			}
+		}
+	}
+
+	// Set the display of most of the elements in a second loop
+	// to avoid the constant reflow
+	for ( index = 0; index < length; index++ ) {
+		elem = elements[ index ];
+		if ( !elem.style ) {
+			continue;
+		}
+		if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+			elem.style.display = show ? values[ index ] || "" : "none";
+		}
+	}
+
+	return elements;
+}
+
+jQuery.extend( {
+
+	// Add in style property hooks for overriding the default
+	// behavior of getting and setting a style property
+	cssHooks: {
+		opacity: {
+			get: function( elem, computed ) {
+				if ( computed ) {
+
+					// We should always get a number back from opacity
+					var ret = curCSS( elem, "opacity" );
+					return ret === "" ? "1" : ret;
+				}
+			}
+		}
+	},
+
+	// Don't automatically add "px" to these possibly-unitless properties
+	cssNumber: {
+		"animationIterationCount": true,
+		"columnCount": true,
+		"fillOpacity": true,
+		"flexGrow": true,
+		"flexShrink": true,
+		"fontWeight": true,
+		"lineHeight": true,
+		"opacity": true,
+		"order": true,
+		"orphans": true,
+		"widows": true,
+		"zIndex": true,
+		"zoom": true
+	},
+
+	// Add in properties whose names you wish to fix before
+	// setting or getting the value
+	cssProps: {
+		"float": "cssFloat"
+	},
+
+	// Get and set the style property on a DOM Node
+	style: function( elem, name, value, extra ) {
+
+		// Don't set styles on text and comment nodes
+		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+			return;
+		}
+
+		// Make sure that we're working with the right name
+		var ret, type, hooks,
+			origName = jQuery.camelCase( name ),
+			style = elem.style;
+
+		name = jQuery.cssProps[ origName ] ||
+			( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
+
+		// Gets hook for the prefixed version, then unprefixed version
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// Check if we're setting a value
+		if ( value !== undefined ) {
+			type = typeof value;
+
+			// Convert "+=" or "-=" to relative numbers (#7345)
+			if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
+				value = adjustCSS( elem, name, ret );
+
+				// Fixes bug #9237
+				type = "number";
+			}
+
+			// Make sure that null and NaN values aren't set (#7116)
+			if ( value == null || value !== value ) {
+				return;
+			}
+
+			// If a number was passed in, add the unit (except for certain CSS properties)
+			if ( type === "number" ) {
+				value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
+			}
+
+			// Support: IE9-11+
+			// background-* props affect original clone's values
+			if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
+				style[ name ] = "inherit";
+			}
+
+			// If a hook was provided, use that value, otherwise just set the specified value
+			if ( !hooks || !( "set" in hooks ) ||
+				( value = hooks.set( elem, value, extra ) ) !== undefined ) {
+
+				style[ name ] = value;
+			}
+
+		} else {
+
+			// If a hook was provided get the non-computed value from there
+			if ( hooks && "get" in hooks &&
+				( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
+
+				return ret;
+			}
+
+			// Otherwise just get the value from the style object
+			return style[ name ];
+		}
+	},
+
+	css: function( elem, name, extra, styles ) {
+		var val, num, hooks,
+			origName = jQuery.camelCase( name );
+
+		// Make sure that we're working with the right name
+		name = jQuery.cssProps[ origName ] ||
+			( jQuery.cssProps[ origName ] = vendorPropName( origName ) || origName );
+
+		// Try prefixed name followed by the unprefixed name
+		hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+		// If a hook was provided get the computed value from there
+		if ( hooks && "get" in hooks ) {
+			val = hooks.get( elem, true, extra );
+		}
+
+		// Otherwise, if a way to get the computed value exists, use that
+		if ( val === undefined ) {
+			val = curCSS( elem, name, styles );
+		}
+
+		// Convert "normal" to computed value
+		if ( val === "normal" && name in cssNormalTransform ) {
+			val = cssNormalTransform[ name ];
+		}
+
+		// Make numeric if forced or a qualifier was provided and val looks numeric
+		if ( extra === "" || extra ) {
+			num = parseFloat( val );
+			return extra === true || isFinite( num ) ? num || 0 : val;
+		}
+		return val;
+	}
+} );
+
+jQuery.each( [ "height", "width" ], function( i, name ) {
+	jQuery.cssHooks[ name ] = {
+		get: function( elem, computed, extra ) {
+			if ( computed ) {
+
+				// Certain elements can have dimension info if we invisibly show them
+				// but it must have a current display style that would benefit
+				return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
+					elem.offsetWidth === 0 ?
+						swap( elem, cssShow, function() {
+							return getWidthOrHeight( elem, name, extra );
+						} ) :
+						getWidthOrHeight( elem, name, extra );
+			}
+		},
+
+		set: function( elem, value, extra ) {
+			var matches,
+				styles = extra && getStyles( elem ),
+				subtract = extra && augmentWidthOrHeight(
+					elem,
+					name,
+					extra,
+					jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+					styles
+				);
+
+			// Convert to pixels if value adjustment is needed
+			if ( subtract && ( matches = rcssNum.exec( value ) ) &&
+				( matches[ 3 ] || "px" ) !== "px" ) {
+
+				elem.style[ name ] = value;
+				value = jQuery.css( elem, name );
+			}
+
+			return setPositiveNumber( elem, value, subtract );
+		}
+	};
+} );
+
+jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
+	function( elem, computed ) {
+		if ( computed ) {
+			return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
+				elem.getBoundingClientRect().left -
+					swap( elem, { marginLeft: 0 }, function() {
+						return elem.getBoundingClientRect().left;
+					} )
+				) + "px";
+		}
+	}
+);
+
+// Support: Android 2.3
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+	function( elem, computed ) {
+		if ( computed ) {
+			return swap( elem, { "display": "inline-block" },
+				curCSS, [ elem, "marginRight" ] );
+		}
+	}
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each( {
+	margin: "",
+	padding: "",
+	border: "Width"
+}, function( prefix, suffix ) {
+	jQuery.cssHooks[ prefix + suffix ] = {
+		expand: function( value ) {
+			var i = 0,
+				expanded = {},
+
+				// Assumes a single number if not a string
+				parts = typeof value === "string" ? value.split( " " ) : [ value ];
+
+			for ( ; i < 4; i++ ) {
+				expanded[ prefix + cssExpand[ i ] + suffix ] =
+					parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+			}
+
+			return expanded;
+		}
+	};
+
+	if ( !rmargin.test( prefix ) ) {
+		jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+	}
+} );
+
+jQuery.fn.extend( {
+	css: function( name, value ) {
+		return access( this, function( elem, name, value ) {
+			var styles, len,
+				map = {},
+				i = 0;
+
+			if ( jQuery.isArray( name ) ) {
+				styles = getStyles( elem );
+				len = name.length;
+
+				for ( ; i < len; i++ ) {
+					map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+				}
+
+				return map;
+			}
+
+			return value !== undefined ?
+				jQuery.style( elem, name, value ) :
+				jQuery.css( elem, name );
+		}, name, value, arguments.length > 1 );
+	},
+	show: function() {
+		return showHide( this, true );
+	},
+	hide: function() {
+		return showHide( this );
+	},
+	toggle: function( state ) {
+		if ( typeof state === "boolean" ) {
+			return state ? this.show() : this.hide();
+		}
+
+		return this.each( function() {
+			if ( isHidden( this ) ) {
+				jQuery( this ).show();
+			} else {
+				jQuery( this ).hide();
+			}
+		} );
+	}
+} );
+
+
+function Tween( elem, options, prop, end, easing ) {
+	return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+	constructor: Tween,
+	init: function( elem, options, prop, end, easing, unit ) {
+		this.elem = elem;
+		this.prop = prop;
+		this.easing = easing || jQuery.easing._default;
+		this.options = options;
+		this.start = this.now = this.cur();
+		this.end = end;
+		this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+	},
+	cur: function() {
+		var hooks = Tween.propHooks[ this.prop ];
+
+		return hooks && hooks.get ?
+			hooks.get( this ) :
+			Tween.propHooks._default.get( this );
+	},
+	run: function( percent ) {
+		var eased,
+			hooks = Tween.propHooks[ this.prop ];
+
+		if ( this.options.duration ) {
+			this.pos = eased = jQuery.easing[ this.easing ](
+				percent, this.options.duration * percent, 0, 1, this.options.duration
+			);
+		} else {
+			this.pos = eased = percent;
+		}
+		this.now = ( this.end - this.start ) * eased + this.start;
+
+		if ( this.options.step ) {
+			this.options.step.call( this.elem, this.now, this );
+		}
+
+		if ( hooks && hooks.set ) {
+			hooks.set( this );
+		} else {
+			Tween.propHooks._default.set( this );
+		}
+		return this;
+	}
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+	_default: {
+		get: function( tween ) {
+			var result;
+
+			// Use a property on the element directly when it is not a DOM element,
+			// or when there is no matching style property that exists.
+			if ( tween.elem.nodeType !== 1 ||
+				tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
+				return tween.elem[ tween.prop ];
+			}
+
+			// Passing an empty string as a 3rd parameter to .css will automatically
+			// attempt a parseFloat and fallback to a string if the parse fails.
+			// Simple values such as "10px" are parsed to Float;
+			// complex values such as "rotate(1rad)" are returned as-is.
+			result = jQuery.css( tween.elem, tween.prop, "" );
+
+			// Empty strings, null, undefined and "auto" are converted to 0.
+			return !result || result === "auto" ? 0 : result;
+		},
+		set: function( tween ) {
+
+			// Use step hook for back compat.
+			// Use cssHook if its there.
+			// Use .style if available and use plain properties where available.
+			if ( jQuery.fx.step[ tween.prop ] ) {
+				jQuery.fx.step[ tween.prop ]( tween );
+			} else if ( tween.elem.nodeType === 1 &&
+				( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
+					jQuery.cssHooks[ tween.prop ] ) ) {
+				jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+			} else {
+				tween.elem[ tween.prop ] = tween.now;
+			}
+		}
+	}
+};
+
+// Support: IE9
+// Panic based approach to setting things on disconnected nodes
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+	set: function( tween ) {
+		if ( tween.elem.nodeType && tween.elem.parentNode ) {
+			tween.elem[ tween.prop ] = tween.now;
+		}
+	}
+};
+
+jQuery.easing = {
+	linear: function( p ) {
+		return p;
+	},
+	swing: function( p ) {
+		return 0.5 - Math.cos( p * Math.PI ) / 2;
+	},
+	_default: "swing"
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+	fxNow, timerId,
+	rfxtypes = /^(?:toggle|show|hide)$/,
+	rrun = /queueHooks$/;
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+	window.setTimeout( function() {
+		fxNow = undefined;
+	} );
+	return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+	var which,
+		i = 0,
+		attrs = { height: type };
+
+	// If we include width, step value is 1 to do all cssExpand values,
+	// otherwise step value is 2 to skip over Left and Right
+	includeWidth = includeWidth ? 1 : 0;
+	for ( ; i < 4 ; i += 2 - includeWidth ) {
+		which = cssExpand[ i ];
+		attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+	}
+
+	if ( includeWidth ) {
+		attrs.opacity = attrs.width = type;
+	}
+
+	return attrs;
+}
+
+function createTween( value, prop, animation ) {
+	var tween,
+		collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
+		index = 0,
+		length = collection.length;
+	for ( ; index < length; index++ ) {
+		if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
+
+			// We're done with this property
+			return tween;
+		}
+	}
+}
+
+function defaultPrefilter( elem, props, opts ) {
+	/* jshint validthis: true */
+	var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+		anim = this,
+		orig = {},
+		style = elem.style,
+		hidden = elem.nodeType && isHidden( elem ),
+		dataShow = dataPriv.get( elem, "fxshow" );
+
+	// Handle queue: false promises
+	if ( !opts.queue ) {
+		hooks = jQuery._queueHooks( elem, "fx" );
+		if ( hooks.unqueued == null ) {
+			hooks.unqueued = 0;
+			oldfire = hooks.empty.fire;
+			hooks.empty.fire = function() {
+				if ( !hooks.unqueued ) {
+					oldfire();
+				}
+			};
+		}
+		hooks.unqueued++;
+
+		anim.always( function() {
+
+			// Ensure the complete handler is called before this completes
+			anim.always( function() {
+				hooks.unqueued--;
+				if ( !jQuery.queue( elem, "fx" ).length ) {
+					hooks.empty.fire();
+				}
+			} );
+		} );
+	}
+
+	// Height/width overflow pass
+	if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+
+		// Make sure that nothing sneaks out
+		// Record all 3 overflow attributes because IE9-10 do not
+		// change the overflow attribute when overflowX and
+		// overflowY are set to the same value
+		opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+		// Set display property to inline-block for height/width
+		// animations on inline elements that are having width/height animated
+		display = jQuery.css( elem, "display" );
+
+		// Test default display if display is currently "none"
+		checkDisplay = display === "none" ?
+			dataPriv.get( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+		if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+			style.display = "inline-block";
+		}
+	}
+
+	if ( opts.overflow ) {
+		style.overflow = "hidden";
+		anim.always( function() {
+			style.overflow = opts.overflow[ 0 ];
+			style.overflowX = opts.overflow[ 1 ];
+			style.overflowY = opts.overflow[ 2 ];
+		} );
+	}
+
+	// show/hide pass
+	for ( prop in props ) {
+		value = props[ prop ];
+		if ( rfxtypes.exec( value ) ) {
+			delete props[ prop ];
+			toggle = toggle || value === "toggle";
+			if ( value === ( hidden ? "hide" : "show" ) ) {
+
+				// If there is dataShow left over from a stopped hide or show
+				// and we are going to proceed with show, we should pretend to be hidden
+				if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+					hidden = true;
+				} else {
+					continue;
+				}
+			}
+			orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+		// Any non-fx value stops us from restoring the original display value
+		} else {
+			display = undefined;
+		}
+	}
+
+	if ( !jQuery.isEmptyObject( orig ) ) {
+		if ( dataShow ) {
+			if ( "hidden" in dataShow ) {
+				hidden = dataShow.hidden;
+			}
+		} else {
+			dataShow = dataPriv.access( elem, "fxshow", {} );
+		}
+
+		// Store state if its toggle - enables .stop().toggle() to "reverse"
+		if ( toggle ) {
+			dataShow.hidden = !hidden;
+		}
+		if ( hidden ) {
+			jQuery( elem ).show();
+		} else {
+			anim.done( function() {
+				jQuery( elem ).hide();
+			} );
+		}
+		anim.done( function() {
+			var prop;
+
+			dataPriv.remove( elem, "fxshow" );
+			for ( prop in orig ) {
+				jQuery.style( elem, prop, orig[ prop ] );
+			}
+		} );
+		for ( prop in orig ) {
+			tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+			if ( !( prop in dataShow ) ) {
+				dataShow[ prop ] = tween.start;
+				if ( hidden ) {
+					tween.end = tween.start;
+					tween.start = prop === "width" || prop === "height" ? 1 : 0;
+				}
+			}
+		}
+
+	// If this is a noop like .hide().hide(), restore an overwritten display value
+	} else if ( ( display === "none" ? defaultDisplay( elem.nodeName ) : display ) === "inline" ) {
+		style.display = display;
+	}
+}
+
+function propFilter( props, specialEasing ) {
+	var index, name, easing, value, hooks;
+
+	// camelCase, specialEasing and expand cssHook pass
+	for ( index in props ) {
+		name = jQuery.camelCase( index );
+		easing = specialEasing[ name ];
+		value = props[ index ];
+		if ( jQuery.isArray( value ) ) {
+			easing = value[ 1 ];
+			value = props[ index ] = value[ 0 ];
+		}
+
+		if ( index !== name ) {
+			props[ name ] = value;
+			delete props[ index ];
+		}
+
+		hooks = jQuery.cssHooks[ name ];
+		if ( hooks && "expand" in hooks ) {
+			value = hooks.expand( value );
+			delete props[ name ];
+
+			// Not quite $.extend, this won't overwrite existing keys.
+			// Reusing 'index' because we have the correct "name"
+			for ( index in value ) {
+				if ( !( index in props ) ) {
+					props[ index ] = value[ index ];
+					specialEasing[ index ] = easing;
+				}
+			}
+		} else {
+			specialEasing[ name ] = easing;
+		}
+	}
+}
+
+function Animation( elem, properties, options ) {
+	var result,
+		stopped,
+		index = 0,
+		length = Animation.prefilters.length,
+		deferred = jQuery.Deferred().always( function() {
+
+			// Don't match elem in the :animated selector
+			delete tick.elem;
+		} ),
+		tick = function() {
+			if ( stopped ) {
+				return false;
+			}
+			var currentTime = fxNow || createFxNow(),
+				remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+
+				// Support: Android 2.3
+				// Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
+				temp = remaining / animation.duration || 0,
+				percent = 1 - temp,
+				index = 0,
+				length = animation.tweens.length;
+
+			for ( ; index < length ; index++ ) {
+				animation.tweens[ index ].run( percent );
+			}
+
+			deferred.notifyWith( elem, [ animation, percent, remaining ] );
+
+			if ( percent < 1 && length ) {
+				return remaining;
+			} else {
+				deferred.resolveWith( elem, [ animation ] );
+				return false;
+			}
+		},
+		animation = deferred.promise( {
+			elem: elem,
+			props: jQuery.extend( {}, properties ),
+			opts: jQuery.extend( true, {
+				specialEasing: {},
+				easing: jQuery.easing._default
+			}, options ),
+			originalProperties: properties,
+			originalOptions: options,
+			startTime: fxNow || createFxNow(),
+			duration: options.duration,
+			tweens: [],
+			createTween: function( prop, end ) {
+				var tween = jQuery.Tween( elem, animation.opts, prop, end,
+						animation.opts.specialEasing[ prop ] || animation.opts.easing );
+				animation.tweens.push( tween );
+				return tween;
+			},
+			stop: function( gotoEnd ) {
+				var index = 0,
+
+					// If we are going to the end, we want to run all the tweens
+					// otherwise we skip this part
+					length = gotoEnd ? animation.tweens.length : 0;
+				if ( stopped ) {
+					return this;
+				}
+				stopped = true;
+				for ( ; index < length ; index++ ) {
+					animation.tweens[ index ].run( 1 );
+				}
+
+				// Resolve when we played the last frame; otherwise, reject
+				if ( gotoEnd ) {
+					deferred.notifyWith( elem, [ animation, 1, 0 ] );
+					deferred.resolveWith( elem, [ animation, gotoEnd ] );
+				} else {
+					deferred.rejectWith( elem, [ animation, gotoEnd ] );
+				}
+				return this;
+			}
+		} ),
+		props = animation.props;
+
+	propFilter( props, animation.opts.specialEasing );
+
+	for ( ; index < length ; index++ ) {
+		result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
+		if ( result ) {
+			if ( jQuery.isFunction( result.stop ) ) {
+				jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
+					jQuery.proxy( result.stop, result );
+			}
+			return result;
+		}
+	}
+
+	jQuery.map( props, createTween, animation );
+
+	if ( jQuery.isFunction( animation.opts.start ) ) {
+		animation.opts.start.call( elem, animation );
+	}
+
+	jQuery.fx.timer(
+		jQuery.extend( tick, {
+			elem: elem,
+			anim: animation,
+			queue: animation.opts.queue
+		} )
+	);
+
+	// attach callbacks from options
+	return animation.progress( animation.opts.progress )
+		.done( animation.opts.done, animation.opts.complete )
+		.fail( animation.opts.fail )
+		.always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+	tweeners: {
+		"*": [ function( prop, value ) {
+			var tween = this.createTween( prop, value );
+			adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
+			return tween;
+		} ]
+	},
+
+	tweener: function( props, callback ) {
+		if ( jQuery.isFunction( props ) ) {
+			callback = props;
+			props = [ "*" ];
+		} else {
+			props = props.match( rnotwhite );
+		}
+
+		var prop,
+			index = 0,
+			length = props.length;
+
+		for ( ; index < length ; index++ ) {
+			prop = props[ index ];
+			Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
+			Animation.tweeners[ prop ].unshift( callback );
+		}
+	},
+
+	prefilters: [ defaultPrefilter ],
+
+	prefilter: function( callback, prepend ) {
+		if ( prepend ) {
+			Animation.prefilters.unshift( callback );
+		} else {
+			Animation.prefilters.push( callback );
+		}
+	}
+} );
+
+jQuery.speed = function( speed, easing, fn ) {
+	var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+		complete: fn || !fn && easing ||
+			jQuery.isFunction( speed ) && speed,
+		duration: speed,
+		easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+	};
+
+	opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ?
+		opt.duration : opt.duration in jQuery.fx.speeds ?
+			jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+	// Normalize opt.queue - true/undefined/null -> "fx"
+	if ( opt.queue == null || opt.queue === true ) {
+		opt.queue = "fx";
+	}
+
+	// Queueing
+	opt.old = opt.complete;
+
+	opt.complete = function() {
+		if ( jQuery.isFunction( opt.old ) ) {
+			opt.old.call( this );
+		}
+
+		if ( opt.queue ) {
+			jQuery.dequeue( this, opt.queue );
+		}
+	};
+
+	return opt;
+};
+
+jQuery.fn.extend( {
+	fadeTo: function( speed, to, easing, callback ) {
+
+		// Show any hidden elements after setting opacity to 0
+		return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+			// Animate to the value specified
+			.end().animate( { opacity: to }, speed, easing, callback );
+	},
+	animate: function( prop, speed, easing, callback ) {
+		var empty = jQuery.isEmptyObject( prop ),
+			optall = jQuery.speed( speed, easing, callback ),
+			doAnimation = function() {
+
+				// Operate on a copy of prop so per-property easing won't be lost
+				var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+				// Empty animations, or finishing resolves immediately
+				if ( empty || dataPriv.get( this, "finish" ) ) {
+					anim.stop( true );
+				}
+			};
+			doAnimation.finish = doAnimation;
+
+		return empty || optall.queue === false ?
+			this.each( doAnimation ) :
+			this.queue( optall.queue, doAnimation );
+	},
+	stop: function( type, clearQueue, gotoEnd ) {
+		var stopQueue = function( hooks ) {
+			var stop = hooks.stop;
+			delete hooks.stop;
+			stop( gotoEnd );
+		};
+
+		if ( typeof type !== "string" ) {
+			gotoEnd = clearQueue;
+			clearQueue = type;
+			type = undefined;
+		}
+		if ( clearQueue && type !== false ) {
+			this.queue( type || "fx", [] );
+		}
+
+		return this.each( function() {
+			var dequeue = true,
+				index = type != null && type + "queueHooks",
+				timers = jQuery.timers,
+				data = dataPriv.get( this );
+
+			if ( index ) {
+				if ( data[ index ] && data[ index ].stop ) {
+					stopQueue( data[ index ] );
+				}
+			} else {
+				for ( index in data ) {
+					if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+						stopQueue( data[ index ] );
+					}
+				}
+			}
+
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this &&
+					( type == null || timers[ index ].queue === type ) ) {
+
+					timers[ index ].anim.stop( gotoEnd );
+					dequeue = false;
+					timers.splice( index, 1 );
+				}
+			}
+
+			// Start the next in the queue if the last step wasn't forced.
+			// Timers currently will call their complete callbacks, which
+			// will dequeue but only if they were gotoEnd.
+			if ( dequeue || !gotoEnd ) {
+				jQuery.dequeue( this, type );
+			}
+		} );
+	},
+	finish: function( type ) {
+		if ( type !== false ) {
+			type = type || "fx";
+		}
+		return this.each( function() {
+			var index,
+				data = dataPriv.get( this ),
+				queue = data[ type + "queue" ],
+				hooks = data[ type + "queueHooks" ],
+				timers = jQuery.timers,
+				length = queue ? queue.length : 0;
+
+			// Enable finishing flag on private data
+			data.finish = true;
+
+			// Empty the queue first
+			jQuery.queue( this, type, [] );
+
+			if ( hooks && hooks.stop ) {
+				hooks.stop.call( this, true );
+			}
+
+			// Look for any active animations, and finish them
+			for ( index = timers.length; index--; ) {
+				if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+					timers[ index ].anim.stop( true );
+					timers.splice( index, 1 );
+				}
+			}
+
+			// Look for any animations in the old queue and finish them
+			for ( index = 0; index < length; index++ ) {
+				if ( queue[ index ] && queue[ index ].finish ) {
+					queue[ index ].finish.call( this );
+				}
+			}
+
+			// Turn off finishing flag
+			delete data.finish;
+		} );
+	}
+} );
+
+jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
+	var cssFn = jQuery.fn[ name ];
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return speed == null || typeof speed === "boolean" ?
+			cssFn.apply( this, arguments ) :
+			this.animate( genFx( name, true ), speed, easing, callback );
+	};
+} );
+
+// Generate shortcuts for custom animations
+jQuery.each( {
+	slideDown: genFx( "show" ),
+	slideUp: genFx( "hide" ),
+	slideToggle: genFx( "toggle" ),
+	fadeIn: { opacity: "show" },
+	fadeOut: { opacity: "hide" },
+	fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+	jQuery.fn[ name ] = function( speed, easing, callback ) {
+		return this.animate( props, speed, easing, callback );
+	};
+} );
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+	var timer,
+		i = 0,
+		timers = jQuery.timers;
+
+	fxNow = jQuery.now();
+
+	for ( ; i < timers.length; i++ ) {
+		timer = timers[ i ];
+
+		// Checks the timer has not already been removed
+		if ( !timer() && timers[ i ] === timer ) {
+			timers.splice( i--, 1 );
+		}
+	}
+
+	if ( !timers.length ) {
+		jQuery.fx.stop();
+	}
+	fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+	jQuery.timers.push( timer );
+	if ( timer() ) {
+		jQuery.fx.start();
+	} else {
+		jQuery.timers.pop();
+	}
+};
+
+jQuery.fx.interval = 13;
+jQuery.fx.start = function() {
+	if ( !timerId ) {
+		timerId = window.setInterval( jQuery.fx.tick, jQuery.fx.interval );
+	}
+};
+
+jQuery.fx.stop = function() {
+	window.clearInterval( timerId );
+
+	timerId = null;
+};
+
+jQuery.fx.speeds = {
+	slow: 600,
+	fast: 200,
+
+	// Default speed
+	_default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+	time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+	type = type || "fx";
+
+	return this.queue( type, function( next, hooks ) {
+		var timeout = window.setTimeout( next, time );
+		hooks.stop = function() {
+			window.clearTimeout( timeout );
+		};
+	} );
+};
+
+
+( function() {
+	var input = document.createElement( "input" ),
+		select = document.createElement( "select" ),
+		opt = select.appendChild( document.createElement( "option" ) );
+
+	input.type = "checkbox";
+
+	// Support: iOS<=5.1, Android<=4.2+
+	// Default value for a checkbox should be "on"
+	support.checkOn = input.value !== "";
+
+	// Support: IE<=11+
+	// Must access selectedIndex to make default options select
+	support.optSelected = opt.selected;
+
+	// Support: Android<=2.3
+	// Options inside disabled selects are incorrectly marked as disabled
+	select.disabled = true;
+	support.optDisabled = !opt.disabled;
+
+	// Support: IE<=11+
+	// An input loses its value after becoming a radio
+	input = document.createElement( "input" );
+	input.value = "t";
+	input.type = "radio";
+	support.radioValue = input.value === "t";
+} )();
+
+
+var boolHook,
+	attrHandle = jQuery.expr.attrHandle;
+
+jQuery.fn.extend( {
+	attr: function( name, value ) {
+		return access( this, jQuery.attr, name, value, arguments.length > 1 );
+	},
+
+	removeAttr: function( name ) {
+		return this.each( function() {
+			jQuery.removeAttr( this, name );
+		} );
+	}
+} );
+
+jQuery.extend( {
+	attr: function( elem, name, value ) {
+		var ret, hooks,
+			nType = elem.nodeType;
+
+		// Don't get/set attributes on text, comment and attribute nodes
+		if ( nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		// Fallback to prop when attributes are not supported
+		if ( typeof elem.getAttribute === "undefined" ) {
+			return jQuery.prop( elem, name, value );
+		}
+
+		// All attributes are lowercase
+		// Grab necessary hook if one is defined
+		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+			name = name.toLowerCase();
+			hooks = jQuery.attrHooks[ name ] ||
+				( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
+		}
+
+		if ( value !== undefined ) {
+			if ( value === null ) {
+				jQuery.removeAttr( elem, name );
+				return;
+			}
+
+			if ( hooks && "set" in hooks &&
+				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+				return ret;
+			}
+
+			elem.setAttribute( name, value + "" );
+			return value;
+		}
+
+		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+			return ret;
+		}
+
+		ret = jQuery.find.attr( elem, name );
+
+		// Non-existent attributes return null, we normalize to undefined
+		return ret == null ? undefined : ret;
+	},
+
+	attrHooks: {
+		type: {
+			set: function( elem, value ) {
+				if ( !support.radioValue && value === "radio" &&
+					jQuery.nodeName( elem, "input" ) ) {
+					var val = elem.value;
+					elem.setAttribute( "type", value );
+					if ( val ) {
+						elem.value = val;
+					}
+					return value;
+				}
+			}
+		}
+	},
+
+	removeAttr: function( elem, value ) {
+		var name, propName,
+			i = 0,
+			attrNames = value && value.match( rnotwhite );
+
+		if ( attrNames && elem.nodeType === 1 ) {
+			while ( ( name = attrNames[ i++ ] ) ) {
+				propName = jQuery.propFix[ name ] || name;
+
+				// Boolean attributes get special treatment (#10870)
+				if ( jQuery.expr.match.bool.test( name ) ) {
+
+					// Set corresponding property to false
+					elem[ propName ] = false;
+				}
+
+				elem.removeAttribute( name );
+			}
+		}
+	}
+} );
+
+// Hooks for boolean attributes
+boolHook = {
+	set: function( elem, value, name ) {
+		if ( value === false ) {
+
+			// Remove boolean attributes when set to false
+			jQuery.removeAttr( elem, name );
+		} else {
+			elem.setAttribute( name, name );
+		}
+		return name;
+	}
+};
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+	var getter = attrHandle[ name ] || jQuery.find.attr;
+
+	attrHandle[ name ] = function( elem, name, isXML ) {
+		var ret, handle;
+		if ( !isXML ) {
+
+			// Avoid an infinite loop by temporarily removing this function from the getter
+			handle = attrHandle[ name ];
+			attrHandle[ name ] = ret;
+			ret = getter( elem, name, isXML ) != null ?
+				name.toLowerCase() :
+				null;
+			attrHandle[ name ] = handle;
+		}
+		return ret;
+	};
+} );
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button)$/i,
+	rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend( {
+	prop: function( name, value ) {
+		return access( this, jQuery.prop, name, value, arguments.length > 1 );
+	},
+
+	removeProp: function( name ) {
+		return this.each( function() {
+			delete this[ jQuery.propFix[ name ] || name ];
+		} );
+	}
+} );
+
+jQuery.extend( {
+	prop: function( elem, name, value ) {
+		var ret, hooks,
+			nType = elem.nodeType;
+
+		// Don't get/set properties on text, comment and attribute nodes
+		if ( nType === 3 || nType === 8 || nType === 2 ) {
+			return;
+		}
+
+		if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+
+			// Fix name and attach hooks
+			name = jQuery.propFix[ name ] || name;
+			hooks = jQuery.propHooks[ name ];
+		}
+
+		if ( value !== undefined ) {
+			if ( hooks && "set" in hooks &&
+				( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+				return ret;
+			}
+
+			return ( elem[ name ] = value );
+		}
+
+		if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+			return ret;
+		}
+
+		return elem[ name ];
+	},
+
+	propHooks: {
+		tabIndex: {
+			get: function( elem ) {
+
+				// elem.tabIndex doesn't always return the
+				// correct value when it hasn't been explicitly set
+				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+				// Use proper attribute retrieval(#12072)
+				var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+				return tabindex ?
+					parseInt( tabindex, 10 ) :
+					rfocusable.test( elem.nodeName ) ||
+						rclickable.test( elem.nodeName ) && elem.href ?
+							0 :
+							-1;
+			}
+		}
+	},
+
+	propFix: {
+		"for": "htmlFor",
+		"class": "className"
+	}
+} );
+
+// Support: IE <=11 only
+// Accessing the selectedIndex property
+// forces the browser to respect setting selected
+// on the option
+// The getter ensures a default option is selected
+// when in an optgroup
+if ( !support.optSelected ) {
+	jQuery.propHooks.selected = {
+		get: function( elem ) {
+			var parent = elem.parentNode;
+			if ( parent && parent.parentNode ) {
+				parent.parentNode.selectedIndex;
+			}
+			return null;
+		},
+		set: function( elem ) {
+			var parent = elem.parentNode;
+			if ( parent ) {
+				parent.selectedIndex;
+
+				if ( parent.parentNode ) {
+					parent.parentNode.selectedIndex;
+				}
+			}
+		}
+	};
+}
+
+jQuery.each( [
+	"tabIndex",
+	"readOnly",
+	"maxLength",
+	"cellSpacing",
+	"cellPadding",
+	"rowSpan",
+	"colSpan",
+	"useMap",
+	"frameBorder",
+	"contentEditable"
+], function() {
+	jQuery.propFix[ this.toLowerCase() ] = this;
+} );
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+function getClass( elem ) {
+	return elem.getAttribute && elem.getAttribute( "class" ) || "";
+}
+
+jQuery.fn.extend( {
+	addClass: function( value ) {
+		var classes, elem, cur, curValue, clazz, j, finalValue,
+			i = 0;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each( function( j ) {
+				jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
+			} );
+		}
+
+		if ( typeof value === "string" && value ) {
+			classes = value.match( rnotwhite ) || [];
+
+			while ( ( elem = this[ i++ ] ) ) {
+				curValue = getClass( elem );
+				cur = elem.nodeType === 1 &&
+					( " " + curValue + " " ).replace( rclass, " " );
+
+				if ( cur ) {
+					j = 0;
+					while ( ( clazz = classes[ j++ ] ) ) {
+						if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+							cur += clazz + " ";
+						}
+					}
+
+					// Only assign if different to avoid unneeded rendering.
+					finalValue = jQuery.trim( cur );
+					if ( curValue !== finalValue ) {
+						elem.setAttribute( "class", finalValue );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	removeClass: function( value ) {
+		var classes, elem, cur, curValue, clazz, j, finalValue,
+			i = 0;
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each( function( j ) {
+				jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
+			} );
+		}
+
+		if ( !arguments.length ) {
+			return this.attr( "class", "" );
+		}
+
+		if ( typeof value === "string" && value ) {
+			classes = value.match( rnotwhite ) || [];
+
+			while ( ( elem = this[ i++ ] ) ) {
+				curValue = getClass( elem );
+
+				// This expression is here for better compressibility (see addClass)
+				cur = elem.nodeType === 1 &&
+					( " " + curValue + " " ).replace( rclass, " " );
+
+				if ( cur ) {
+					j = 0;
+					while ( ( clazz = classes[ j++ ] ) ) {
+
+						// Remove *all* instances
+						while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
+							cur = cur.replace( " " + clazz + " ", " " );
+						}
+					}
+
+					// Only assign if different to avoid unneeded rendering.
+					finalValue = jQuery.trim( cur );
+					if ( curValue !== finalValue ) {
+						elem.setAttribute( "class", finalValue );
+					}
+				}
+			}
+		}
+
+		return this;
+	},
+
+	toggleClass: function( value, stateVal ) {
+		var type = typeof value;
+
+		if ( typeof stateVal === "boolean" && type === "string" ) {
+			return stateVal ? this.addClass( value ) : this.removeClass( value );
+		}
+
+		if ( jQuery.isFunction( value ) ) {
+			return this.each( function( i ) {
+				jQuery( this ).toggleClass(
+					value.call( this, i, getClass( this ), stateVal ),
+					stateVal
+				);
+			} );
+		}
+
+		return this.each( function() {
+			var className, i, self, classNames;
+
+			if ( type === "string" ) {
+
+				// Toggle individual class names
+				i = 0;
+				self = jQuery( this );
+				classNames = value.match( rnotwhite ) || [];
+
+				while ( ( className = classNames[ i++ ] ) ) {
+
+					// Check each className given, space separated list
+					if ( self.hasClass( className ) ) {
+						self.removeClass( className );
+					} else {
+						self.addClass( className );
+					}
+				}
+
+			// Toggle whole class name
+			} else if ( value === undefined || type === "boolean" ) {
+				className = getClass( this );
+				if ( className ) {
+
+					// Store className if set
+					dataPriv.set( this, "__className__", className );
+				}
+
+				// If the element has a class name or if we're passed `false`,
+				// then remove the whole classname (if there was one, the above saved it).
+				// Otherwise bring back whatever was previously saved (if anything),
+				// falling back to the empty string if nothing was stored.
+				if ( this.setAttribute ) {
+					this.setAttribute( "class",
+						className || value === false ?
+						"" :
+						dataPriv.get( this, "__className__" ) || ""
+					);
+				}
+			}
+		} );
+	},
+
+	hasClass: function( selector ) {
+		var className, elem,
+			i = 0;
+
+		className = " " + selector + " ";
+		while ( ( elem = this[ i++ ] ) ) {
+			if ( elem.nodeType === 1 &&
+				( " " + getClass( elem ) + " " ).replace( rclass, " " )
+					.indexOf( className ) > -1
+			) {
+				return true;
+			}
+		}
+
+		return false;
+	}
+} );
+
+
+
+
+var rreturn = /\r/g,
+	rspaces = /[\x20\t\r\n\f]+/g;
+
+jQuery.fn.extend( {
+	val: function( value ) {
+		var hooks, ret, isFunction,
+			elem = this[ 0 ];
+
+		if ( !arguments.length ) {
+			if ( elem ) {
+				hooks = jQuery.valHooks[ elem.type ] ||
+					jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+				if ( hooks &&
+					"get" in hooks &&
+					( ret = hooks.get( elem, "value" ) ) !== undefined
+				) {
+					return ret;
+				}
+
+				ret = elem.value;
+
+				return typeof ret === "string" ?
+
+					// Handle most common string cases
+					ret.replace( rreturn, "" ) :
+
+					// Handle cases where value is null/undef or number
+					ret == null ? "" : ret;
+			}
+
+			return;
+		}
+
+		isFunction = jQuery.isFunction( value );
+
+		return this.each( function( i ) {
+			var val;
+
+			if ( this.nodeType !== 1 ) {
+				return;
+			}
+
+			if ( isFunction ) {
+				val = value.call( this, i, jQuery( this ).val() );
+			} else {
+				val = value;
+			}
+
+			// Treat null/undefined as ""; convert numbers to string
+			if ( val == null ) {
+				val = "";
+
+			} else if ( typeof val === "number" ) {
+				val += "";
+
+			} else if ( jQuery.isArray( val ) ) {
+				val = jQuery.map( val, function( value ) {
+					return value == null ? "" : value + "";
+				} );
+			}
+
+			hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+			// If set returns undefined, fall back to normal setting
+			if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
+				this.value = val;
+			}
+		} );
+	}
+} );
+
+jQuery.extend( {
+	valHooks: {
+		option: {
+			get: function( elem ) {
+
+				var val = jQuery.find.attr( elem, "value" );
+				return val != null ?
+					val :
+
+					// Support: IE10-11+
+					// option.text throws exceptions (#14686, #14858)
+					// Strip and collapse whitespace
+					// https://html.spec.whatwg.org/#strip-and-collapse-whitespace
+					jQuery.trim( jQuery.text( elem ) ).replace( rspaces, " " );
+			}
+		},
+		select: {
+			get: function( elem ) {
+				var value, option,
+					options = elem.options,
+					index = elem.selectedIndex,
+					one = elem.type === "select-one" || index < 0,
+					values = one ? null : [],
+					max = one ? index + 1 : options.length,
+					i = index < 0 ?
+						max :
+						one ? index : 0;
+
+				// Loop through all the selected options
+				for ( ; i < max; i++ ) {
+					option = options[ i ];
+
+					// IE8-9 doesn't update selected after form reset (#2551)
+					if ( ( option.selected || i === index ) &&
+
+							// Don't return options that are disabled or in a disabled optgroup
+							( support.optDisabled ?
+								!option.disabled : option.getAttribute( "disabled" ) === null ) &&
+							( !option.parentNode.disabled ||
+								!jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+						// Get the specific value for the option
+						value = jQuery( option ).val();
+
+						// We don't need an array for one selects
+						if ( one ) {
+							return value;
+						}
+
+						// Multi-Selects return an array
+						values.push( value );
+					}
+				}
+
+				return values;
+			},
+
+			set: function( elem, value ) {
+				var optionSet, option,
+					options = elem.options,
+					values = jQuery.makeArray( value ),
+					i = options.length;
+
+				while ( i-- ) {
+					option = options[ i ];
+					if ( option.selected =
+						jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
+					) {
+						optionSet = true;
+					}
+				}
+
+				// Force browsers to behave consistently when non-matching value is set
+				if ( !optionSet ) {
+					elem.selectedIndex = -1;
+				}
+				return values;
+			}
+		}
+	}
+} );
+
+// Radios and checkboxes getter/setter
+jQuery.each( [ "radio", "checkbox" ], function() {
+	jQuery.valHooks[ this ] = {
+		set: function( elem, value ) {
+			if ( jQuery.isArray( value ) ) {
+				return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
+			}
+		}
+	};
+	if ( !support.checkOn ) {
+		jQuery.valHooks[ this ].get = function( elem ) {
+			return elem.getAttribute( "value" ) === null ? "on" : elem.value;
+		};
+	}
+} );
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
+
+jQuery.extend( jQuery.event, {
+
+	trigger: function( event, data, elem, onlyHandlers ) {
+
+		var i, cur, tmp, bubbleType, ontype, handle, special,
+			eventPath = [ elem || document ],
+			type = hasOwn.call( event, "type" ) ? event.type : event,
+			namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
+
+		cur = tmp = elem = elem || document;
+
+		// Don't do events on text and comment nodes
+		if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+			return;
+		}
+
+		// focus/blur morphs to focusin/out; ensure we're not firing them right now
+		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+			return;
+		}
+
+		if ( type.indexOf( "." ) > -1 ) {
+
+			// Namespaced trigger; create a regexp to match event type in handle()
+			namespaces = type.split( "." );
+			type = namespaces.shift();
+			namespaces.sort();
+		}
+		ontype = type.indexOf( ":" ) < 0 && "on" + type;
+
+		// Caller can pass in a jQuery.Event object, Object, or just an event type string
+		event = event[ jQuery.expando ] ?
+			event :
+			new jQuery.Event( type, typeof event === "object" && event );
+
+		// Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+		event.isTrigger = onlyHandlers ? 2 : 3;
+		event.namespace = namespaces.join( "." );
+		event.rnamespace = event.namespace ?
+			new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
+			null;
+
+		// Clean up the event in case it is being reused
+		event.result = undefined;
+		if ( !event.target ) {
+			event.target = elem;
+		}
+
+		// Clone any incoming data and prepend the event, creating the handler arg list
+		data = data == null ?
+			[ event ] :
+			jQuery.makeArray( data, [ event ] );
+
+		// Allow special events to draw outside the lines
+		special = jQuery.event.special[ type ] || {};
+		if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+			return;
+		}
+
+		// Determine event propagation path in advance, per W3C events spec (#9951)
+		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+			bubbleType = special.delegateType || type;
+			if ( !rfocusMorph.test( bubbleType + type ) ) {
+				cur = cur.parentNode;
+			}
+			for ( ; cur; cur = cur.parentNode ) {
+				eventPath.push( cur );
+				tmp = cur;
+			}
+
+			// Only add window if we got to document (e.g., not plain obj or detached DOM)
+			if ( tmp === ( elem.ownerDocument || document ) ) {
+				eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+			}
+		}
+
+		// Fire handlers on the event path
+		i = 0;
+		while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
+
+			event.type = i > 1 ?
+				bubbleType :
+				special.bindType || type;
+
+			// jQuery handler
+			handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
+				dataPriv.get( cur, "handle" );
+			if ( handle ) {
+				handle.apply( cur, data );
+			}
+
+			// Native handler
+			handle = ontype && cur[ ontype ];
+			if ( handle && handle.apply && acceptData( cur ) ) {
+				event.result = handle.apply( cur, data );
+				if ( event.result === false ) {
+					event.preventDefault();
+				}
+			}
+		}
+		event.type = type;
+
+		// If nobody prevented the default action, do it now
+		if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+			if ( ( !special._default ||
+				special._default.apply( eventPath.pop(), data ) === false ) &&
+				acceptData( elem ) ) {
+
+				// Call a native DOM method on the target with the same name name as the event.
+				// Don't do default actions on window, that's where global variables be (#6170)
+				if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+					// Don't re-trigger an onFOO event when we call its FOO() method
+					tmp = elem[ ontype ];
+
+					if ( tmp ) {
+						elem[ ontype ] = null;
+					}
+
+					// Prevent re-triggering of the same event, since we already bubbled it above
+					jQuery.event.triggered = type;
+					elem[ type ]();
+					jQuery.event.triggered = undefined;
+
+					if ( tmp ) {
+						elem[ ontype ] = tmp;
+					}
+				}
+			}
+		}
+
+		return event.result;
+	},
+
+	// Piggyback on a donor event to simulate a different one
+	// Used only for `focus(in | out)` events
+	simulate: function( type, elem, event ) {
+		var e = jQuery.extend(
+			new jQuery.Event(),
+			event,
+			{
+				type: type,
+				isSimulated: true
+			}
+		);
+
+		jQuery.event.trigger( e, null, elem );
+	}
+
+} );
+
+jQuery.fn.extend( {
+
+	trigger: function( type, data ) {
+		return this.each( function() {
+			jQuery.event.trigger( type, data, this );
+		} );
+	},
+	triggerHandler: function( type, data ) {
+		var elem = this[ 0 ];
+		if ( elem ) {
+			return jQuery.event.trigger( type, data, elem, true );
+		}
+	}
+} );
+
+
+jQuery.each( ( "blur focus focusin focusout load resize scroll unload click dblclick " +
+	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+	"change select submit keydown keypress keyup error contextmenu" ).split( " " ),
+	function( i, name ) {
+
+	// Handle event binding
+	jQuery.fn[ name ] = function( data, fn ) {
+		return arguments.length > 0 ?
+			this.on( name, null, data, fn ) :
+			this.trigger( name );
+	};
+} );
+
+jQuery.fn.extend( {
+	hover: function( fnOver, fnOut ) {
+		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+	}
+} );
+
+
+
+
+support.focusin = "onfocusin" in window;
+
+
+// Support: Firefox
+// Firefox doesn't have focus(in | out) events
+// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
+//
+// Support: Chrome, Safari
+// focus(in | out) events fire after focus & blur events,
+// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
+// Related ticket - https://code.google.com/p/chromium/issues/detail?id=449857
+if ( !support.focusin ) {
+	jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+		// Attach a single capturing handler on the document while someone wants focusin/focusout
+		var handler = function( event ) {
+			jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
+		};
+
+		jQuery.event.special[ fix ] = {
+			setup: function() {
+				var doc = this.ownerDocument || this,
+					attaches = dataPriv.access( doc, fix );
+
+				if ( !attaches ) {
+					doc.addEventListener( orig, handler, true );
+				}
+				dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
+			},
+			teardown: function() {
+				var doc = this.ownerDocument || this,
+					attaches = dataPriv.access( doc, fix ) - 1;
+
+				if ( !attaches ) {
+					doc.removeEventListener( orig, handler, true );
+					dataPriv.remove( doc, fix );
+
+				} else {
+					dataPriv.access( doc, fix, attaches );
+				}
+			}
+		};
+	} );
+}
+var location = window.location;
+
+var nonce = jQuery.now();
+
+var rquery = ( /\?/ );
+
+
+
+// Support: Android 2.3
+// Workaround failure to string-cast null input
+jQuery.parseJSON = function( data ) {
+	return JSON.parse( data + "" );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+	var xml;
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+
+	// Support: IE9
+	try {
+		xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
+	} catch ( e ) {
+		xml = undefined;
+	}
+
+	if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+		jQuery.error( "Invalid XML: " + data );
+	}
+	return xml;
+};
+
+
+var
+	rhash = /#.*$/,
+	rts = /([?&])_=[^&]*/,
+	rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+
+	// #7653, #8125, #8152: local protocol detection
+	rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+	rnoContent = /^(?:GET|HEAD)$/,
+	rprotocol = /^\/\//,
+
+	/* Prefilters
+	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+	 * 2) These are called:
+	 *    - BEFORE asking for a transport
+	 *    - AFTER param serialization (s.data is a string if s.processData is true)
+	 * 3) key is the dataType
+	 * 4) the catchall symbol "*" can be used
+	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+	 */
+	prefilters = {},
+
+	/* Transports bindings
+	 * 1) key is the dataType
+	 * 2) the catchall symbol "*" can be used
+	 * 3) selection will start with transport dataType and THEN go to "*" if needed
+	 */
+	transports = {},
+
+	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+	allTypes = "*/".concat( "*" ),
+
+	// Anchor tag for parsing the document origin
+	originAnchor = document.createElement( "a" );
+	originAnchor.href = location.href;
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+	// dataTypeExpression is optional and defaults to "*"
+	return function( dataTypeExpression, func ) {
+
+		if ( typeof dataTypeExpression !== "string" ) {
+			func = dataTypeExpression;
+			dataTypeExpression = "*";
+		}
+
+		var dataType,
+			i = 0,
+			dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+		if ( jQuery.isFunction( func ) ) {
+
+			// For each dataType in the dataTypeExpression
+			while ( ( dataType = dataTypes[ i++ ] ) ) {
+
+				// Prepend if requested
+				if ( dataType[ 0 ] === "+" ) {
+					dataType = dataType.slice( 1 ) || "*";
+					( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
+
+				// Otherwise append
+				} else {
+					( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
+				}
+			}
+		}
+	};
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+	var inspected = {},
+		seekingTransport = ( structure === transports );
+
+	function inspect( dataType ) {
+		var selected;
+		inspected[ dataType ] = true;
+		jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+			var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+			if ( typeof dataTypeOrTransport === "string" &&
+				!seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+
+				options.dataTypes.unshift( dataTypeOrTransport );
+				inspect( dataTypeOrTransport );
+				return false;
+			} else if ( seekingTransport ) {
+				return !( selected = dataTypeOrTransport );
+			}
+		} );
+		return selected;
+	}
+
+	return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+	var key, deep,
+		flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+	for ( key in src ) {
+		if ( src[ key ] !== undefined ) {
+			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+		}
+	}
+	if ( deep ) {
+		jQuery.extend( true, target, deep );
+	}
+
+	return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+	var ct, type, finalDataType, firstDataType,
+		contents = s.contents,
+		dataTypes = s.dataTypes;
+
+	// Remove auto dataType and get content-type in the process
+	while ( dataTypes[ 0 ] === "*" ) {
+		dataTypes.shift();
+		if ( ct === undefined ) {
+			ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
+		}
+	}
+
+	// Check if we're dealing with a known content-type
+	if ( ct ) {
+		for ( type in contents ) {
+			if ( contents[ type ] && contents[ type ].test( ct ) ) {
+				dataTypes.unshift( type );
+				break;
+			}
+		}
+	}
+
+	// Check to see if we have a response for the expected dataType
+	if ( dataTypes[ 0 ] in responses ) {
+		finalDataType = dataTypes[ 0 ];
+	} else {
+
+		// Try convertible dataTypes
+		for ( type in responses ) {
+			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
+				finalDataType = type;
+				break;
+			}
+			if ( !firstDataType ) {
+				firstDataType = type;
+			}
+		}
+
+		// Or just use first one
+		finalDataType = finalDataType || firstDataType;
+	}
+
+	// If we found a dataType
+	// We add the dataType to the list if needed
+	// and return the corresponding response
+	if ( finalDataType ) {
+		if ( finalDataType !== dataTypes[ 0 ] ) {
+			dataTypes.unshift( finalDataType );
+		}
+		return responses[ finalDataType ];
+	}
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+	var conv2, current, conv, tmp, prev,
+		converters = {},
+
+		// Work with a copy of dataTypes in case we need to modify it for conversion
+		dataTypes = s.dataTypes.slice();
+
+	// Create converters map with lowercased keys
+	if ( dataTypes[ 1 ] ) {
+		for ( conv in s.converters ) {
+			converters[ conv.toLowerCase() ] = s.converters[ conv ];
+		}
+	}
+
+	current = dataTypes.shift();
+
+	// Convert to each sequential dataType
+	while ( current ) {
+
+		if ( s.responseFields[ current ] ) {
+			jqXHR[ s.responseFields[ current ] ] = response;
+		}
+
+		// Apply the dataFilter if provided
+		if ( !prev && isSuccess && s.dataFilter ) {
+			response = s.dataFilter( response, s.dataType );
+		}
+
+		prev = current;
+		current = dataTypes.shift();
+
+		if ( current ) {
+
+		// There's only work to do if current dataType is non-auto
+			if ( current === "*" ) {
+
+				current = prev;
+
+			// Convert response if prev dataType is non-auto and differs from current
+			} else if ( prev !== "*" && prev !== current ) {
+
+				// Seek a direct converter
+				conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+				// If none found, seek a pair
+				if ( !conv ) {
+					for ( conv2 in converters ) {
+
+						// If conv2 outputs current
+						tmp = conv2.split( " " );
+						if ( tmp[ 1 ] === current ) {
+
+							// If prev can be converted to accepted input
+							conv = converters[ prev + " " + tmp[ 0 ] ] ||
+								converters[ "* " + tmp[ 0 ] ];
+							if ( conv ) {
+
+								// Condense equivalence converters
+								if ( conv === true ) {
+									conv = converters[ conv2 ];
+
+								// Otherwise, insert the intermediate dataType
+								} else if ( converters[ conv2 ] !== true ) {
+									current = tmp[ 0 ];
+									dataTypes.unshift( tmp[ 1 ] );
+								}
+								break;
+							}
+						}
+					}
+				}
+
+				// Apply converter (if not an equivalence)
+				if ( conv !== true ) {
+
+					// Unless errors are allowed to bubble, catch and return them
+					if ( conv && s.throws ) {
+						response = conv( response );
+					} else {
+						try {
+							response = conv( response );
+						} catch ( e ) {
+							return {
+								state: "parsererror",
+								error: conv ? e : "No conversion from " + prev + " to " + current
+							};
+						}
+					}
+				}
+			}
+		}
+	}
+
+	return { state: "success", data: response };
+}
+
+jQuery.extend( {
+
+	// Counter for holding the number of active queries
+	active: 0,
+
+	// Last-Modified header cache for next request
+	lastModified: {},
+	etag: {},
+
+	ajaxSettings: {
+		url: location.href,
+		type: "GET",
+		isLocal: rlocalProtocol.test( location.protocol ),
+		global: true,
+		processData: true,
+		async: true,
+		contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+		/*
+		timeout: 0,
+		data: null,
+		dataType: null,
+		username: null,
+		password: null,
+		cache: null,
+		throws: false,
+		traditional: false,
+		headers: {},
+		*/
+
+		accepts: {
+			"*": allTypes,
+			text: "text/plain",
+			html: "text/html",
+			xml: "application/xml, text/xml",
+			json: "application/json, text/javascript"
+		},
+
+		contents: {
+			xml: /\bxml\b/,
+			html: /\bhtml/,
+			json: /\bjson\b/
+		},
+
+		responseFields: {
+			xml: "responseXML",
+			text: "responseText",
+			json: "responseJSON"
+		},
+
+		// Data converters
+		// Keys separate source (or catchall "*") and destination types with a single space
+		converters: {
+
+			// Convert anything to text
+			"* text": String,
+
+			// Text to html (true = no transformation)
+			"text html": true,
+
+			// Evaluate text as a json expression
+			"text json": jQuery.parseJSON,
+
+			// Parse text as xml
+			"text xml": jQuery.parseXML
+		},
+
+		// For options that shouldn't be deep extended:
+		// you can add your own custom options here if
+		// and when you create one that shouldn't be
+		// deep extended (see ajaxExtend)
+		flatOptions: {
+			url: true,
+			context: true
+		}
+	},
+
+	// Creates a full fledged settings object into target
+	// with both ajaxSettings and settings fields.
+	// If target is omitted, writes into ajaxSettings.
+	ajaxSetup: function( target, settings ) {
+		return settings ?
+
+			// Building a settings object
+			ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+			// Extending ajaxSettings
+			ajaxExtend( jQuery.ajaxSettings, target );
+	},
+
+	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+	ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+	// Main method
+	ajax: function( url, options ) {
+
+		// If url is an object, simulate pre-1.5 signature
+		if ( typeof url === "object" ) {
+			options = url;
+			url = undefined;
+		}
+
+		// Force options to be an object
+		options = options || {};
+
+		var transport,
+
+			// URL without anti-cache param
+			cacheURL,
+
+			// Response headers
+			responseHeadersString,
+			responseHeaders,
+
+			// timeout handle
+			timeoutTimer,
+
+			// Url cleanup var
+			urlAnchor,
+
+			// To know if global events are to be dispatched
+			fireGlobals,
+
+			// Loop variable
+			i,
+
+			// Create the final options object
+			s = jQuery.ajaxSetup( {}, options ),
+
+			// Callbacks context
+			callbackContext = s.context || s,
+
+			// Context for global events is callbackContext if it is a DOM node or jQuery collection
+			globalEventContext = s.context &&
+				( callbackContext.nodeType || callbackContext.jquery ) ?
+					jQuery( callbackContext ) :
+					jQuery.event,
+
+			// Deferreds
+			deferred = jQuery.Deferred(),
+			completeDeferred = jQuery.Callbacks( "once memory" ),
+
+			// Status-dependent callbacks
+			statusCode = s.statusCode || {},
+
+			// Headers (they are sent all at once)
+			requestHeaders = {},
+			requestHeadersNames = {},
+
+			// The jqXHR state
+			state = 0,
+
+			// Default abort message
+			strAbort = "canceled",
+
+			// Fake xhr
+			jqXHR = {
+				readyState: 0,
+
+				// Builds headers hashtable if needed
+				getResponseHeader: function( key ) {
+					var match;
+					if ( state === 2 ) {
+						if ( !responseHeaders ) {
+							responseHeaders = {};
+							while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
+								responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
+							}
+						}
+						match = responseHeaders[ key.toLowerCase() ];
+					}
+					return match == null ? null : match;
+				},
+
+				// Raw string
+				getAllResponseHeaders: function() {
+					return state === 2 ? responseHeadersString : null;
+				},
+
+				// Caches the header
+				setRequestHeader: function( name, value ) {
+					var lname = name.toLowerCase();
+					if ( !state ) {
+						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+						requestHeaders[ name ] = value;
+					}
+					return this;
+				},
+
+				// Overrides response content-type header
+				overrideMimeType: function( type ) {
+					if ( !state ) {
+						s.mimeType = type;
+					}
+					return this;
+				},
+
+				// Status-dependent callbacks
+				statusCode: function( map ) {
+					var code;
+					if ( map ) {
+						if ( state < 2 ) {
+							for ( code in map ) {
+
+								// Lazy-add the new callback in a way that preserves old ones
+								statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+							}
+						} else {
+
+							// Execute the appropriate callbacks
+							jqXHR.always( map[ jqXHR.status ] );
+						}
+					}
+					return this;
+				},
+
+				// Cancel the request
+				abort: function( statusText ) {
+					var finalText = statusText || strAbort;
+					if ( transport ) {
+						transport.abort( finalText );
+					}
+					done( 0, finalText );
+					return this;
+				}
+			};
+
+		// Attach deferreds
+		deferred.promise( jqXHR ).complete = completeDeferred.add;
+		jqXHR.success = jqXHR.done;
+		jqXHR.error = jqXHR.fail;
+
+		// Remove hash character (#7531: and string promotion)
+		// Add protocol if not provided (prefilters might expect it)
+		// Handle falsy url in the settings object (#10093: consistency with old signature)
+		// We also use the url parameter if available
+		s.url = ( ( url || s.url || location.href ) + "" ).replace( rhash, "" )
+			.replace( rprotocol, location.protocol + "//" );
+
+		// Alias method option to type as per ticket #12004
+		s.type = options.method || options.type || s.method || s.type;
+
+		// Extract dataTypes list
+		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+		// A cross-domain request is in order when the origin doesn't match the current origin.
+		if ( s.crossDomain == null ) {
+			urlAnchor = document.createElement( "a" );
+
+			// Support: IE8-11+
+			// IE throws exception if url is malformed, e.g. http://example.com:80x/
+			try {
+				urlAnchor.href = s.url;
+
+				// Support: IE8-11+
+				// Anchor's host property isn't correctly set when s.url is relative
+				urlAnchor.href = urlAnchor.href;
+				s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+					urlAnchor.protocol + "//" + urlAnchor.host;
+			} catch ( e ) {
+
+				// If there is an error parsing the URL, assume it is crossDomain,
+				// it can be rejected by the transport if it is invalid
+				s.crossDomain = true;
+			}
+		}
+
+		// Convert data if not already a string
+		if ( s.data && s.processData && typeof s.data !== "string" ) {
+			s.data = jQuery.param( s.data, s.traditional );
+		}
+
+		// Apply prefilters
+		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+		// If request was aborted inside a prefilter, stop there
+		if ( state === 2 ) {
+			return jqXHR;
+		}
+
+		// We can fire global events as of now if asked to
+		// Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+		fireGlobals = jQuery.event && s.global;
+
+		// Watch for a new set of requests
+		if ( fireGlobals && jQuery.active++ === 0 ) {
+			jQuery.event.trigger( "ajaxStart" );
+		}
+
+		// Uppercase the type
+		s.type = s.type.toUpperCase();
+
+		// Determine if request has content
+		s.hasContent = !rnoContent.test( s.type );
+
+		// Save the URL in case we're toying with the If-Modified-Since
+		// and/or If-None-Match header later on
+		cacheURL = s.url;
+
+		// More options handling for requests with no content
+		if ( !s.hasContent ) {
+
+			// If data is available, append data to url
+			if ( s.data ) {
+				cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+
+				// #9682: remove data so that it's not used in an eventual retry
+				delete s.data;
+			}
+
+			// Add anti-cache in url if needed
+			if ( s.cache === false ) {
+				s.url = rts.test( cacheURL ) ?
+
+					// If there is already a '_' parameter, set its value
+					cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+					// Otherwise add one to the end
+					cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+			}
+		}
+
+		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+		if ( s.ifModified ) {
+			if ( jQuery.lastModified[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+			}
+			if ( jQuery.etag[ cacheURL ] ) {
+				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+			}
+		}
+
+		// Set the correct header, if data is being sent
+		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+			jqXHR.setRequestHeader( "Content-Type", s.contentType );
+		}
+
+		// Set the Accepts header for the server, depending on the dataType
+		jqXHR.setRequestHeader(
+			"Accept",
+			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
+				s.accepts[ s.dataTypes[ 0 ] ] +
+					( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+				s.accepts[ "*" ]
+		);
+
+		// Check for headers option
+		for ( i in s.headers ) {
+			jqXHR.setRequestHeader( i, s.headers[ i ] );
+		}
+
+		// Allow custom headers/mimetypes and early abort
+		if ( s.beforeSend &&
+			( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+
+			// Abort if not done already and return
+			return jqXHR.abort();
+		}
+
+		// Aborting is no longer a cancellation
+		strAbort = "abort";
+
+		// Install callbacks on deferreds
+		for ( i in { success: 1, error: 1, complete: 1 } ) {
+			jqXHR[ i ]( s[ i ] );
+		}
+
+		// Get transport
+		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+		// If no transport, we auto-abort
+		if ( !transport ) {
+			done( -1, "No Transport" );
+		} else {
+			jqXHR.readyState = 1;
+
+			// Send global event
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+			}
+
+			// If request was aborted inside ajaxSend, stop there
+			if ( state === 2 ) {
+				return jqXHR;
+			}
+
+			// Timeout
+			if ( s.async && s.timeout > 0 ) {
+				timeoutTimer = window.setTimeout( function() {
+					jqXHR.abort( "timeout" );
+				}, s.timeout );
+			}
+
+			try {
+				state = 1;
+				transport.send( requestHeaders, done );
+			} catch ( e ) {
+
+				// Propagate exception as error if not done
+				if ( state < 2 ) {
+					done( -1, e );
+
+				// Simply rethrow otherwise
+				} else {
+					throw e;
+				}
+			}
+		}
+
+		// Callback for when everything is done
+		function done( status, nativeStatusText, responses, headers ) {
+			var isSuccess, success, error, response, modified,
+				statusText = nativeStatusText;
+
+			// Called once
+			if ( state === 2 ) {
+				return;
+			}
+
+			// State is "done" now
+			state = 2;
+
+			// Clear timeout if it exists
+			if ( timeoutTimer ) {
+				window.clearTimeout( timeoutTimer );
+			}
+
+			// Dereference transport for early garbage collection
+			// (no matter how long the jqXHR object will be used)
+			transport = undefined;
+
+			// Cache response headers
+			responseHeadersString = headers || "";
+
+			// Set readyState
+			jqXHR.readyState = status > 0 ? 4 : 0;
+
+			// Determine if successful
+			isSuccess = status >= 200 && status < 300 || status === 304;
+
+			// Get response data
+			if ( responses ) {
+				response = ajaxHandleResponses( s, jqXHR, responses );
+			}
+
+			// Convert no matter what (that way responseXXX fields are always set)
+			response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+			// If successful, handle type chaining
+			if ( isSuccess ) {
+
+				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+				if ( s.ifModified ) {
+					modified = jqXHR.getResponseHeader( "Last-Modified" );
+					if ( modified ) {
+						jQuery.lastModified[ cacheURL ] = modified;
+					}
+					modified = jqXHR.getResponseHeader( "etag" );
+					if ( modified ) {
+						jQuery.etag[ cacheURL ] = modified;
+					}
+				}
+
+				// if no content
+				if ( status === 204 || s.type === "HEAD" ) {
+					statusText = "nocontent";
+
+				// if not modified
+				} else if ( status === 304 ) {
+					statusText = "notmodified";
+
+				// If we have data, let's convert it
+				} else {
+					statusText = response.state;
+					success = response.data;
+					error = response.error;
+					isSuccess = !error;
+				}
+			} else {
+
+				// Extract error from statusText and normalize for non-aborts
+				error = statusText;
+				if ( status || !statusText ) {
+					statusText = "error";
+					if ( status < 0 ) {
+						status = 0;
+					}
+				}
+			}
+
+			// Set data for the fake xhr object
+			jqXHR.status = status;
+			jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+			// Success/Error
+			if ( isSuccess ) {
+				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+			} else {
+				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+			}
+
+			// Status-dependent callbacks
+			jqXHR.statusCode( statusCode );
+			statusCode = undefined;
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+					[ jqXHR, s, isSuccess ? success : error ] );
+			}
+
+			// Complete
+			completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+			if ( fireGlobals ) {
+				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+
+				// Handle the global AJAX counter
+				if ( !( --jQuery.active ) ) {
+					jQuery.event.trigger( "ajaxStop" );
+				}
+			}
+		}
+
+		return jqXHR;
+	},
+
+	getJSON: function( url, data, callback ) {
+		return jQuery.get( url, data, callback, "json" );
+	},
+
+	getScript: function( url, callback ) {
+		return jQuery.get( url, undefined, callback, "script" );
+	}
+} );
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+	jQuery[ method ] = function( url, data, callback, type ) {
+
+		// Shift arguments if data argument was omitted
+		if ( jQuery.isFunction( data ) ) {
+			type = type || callback;
+			callback = data;
+			data = undefined;
+		}
+
+		// The url can be an options object (which then must have .url)
+		return jQuery.ajax( jQuery.extend( {
+			url: url,
+			type: method,
+			dataType: type,
+			data: data,
+			success: callback
+		}, jQuery.isPlainObject( url ) && url ) );
+	};
+} );
+
+
+jQuery._evalUrl = function( url ) {
+	return jQuery.ajax( {
+		url: url,
+
+		// Make this explicit, since user can override this through ajaxSetup (#11264)
+		type: "GET",
+		dataType: "script",
+		async: false,
+		global: false,
+		"throws": true
+	} );
+};
+
+
+jQuery.fn.extend( {
+	wrapAll: function( html ) {
+		var wrap;
+
+		if ( jQuery.isFunction( html ) ) {
+			return this.each( function( i ) {
+				jQuery( this ).wrapAll( html.call( this, i ) );
+			} );
+		}
+
+		if ( this[ 0 ] ) {
+
+			// The elements to wrap the target around
+			wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+			if ( this[ 0 ].parentNode ) {
+				wrap.insertBefore( this[ 0 ] );
+			}
+
+			wrap.map( function() {
+				var elem = this;
+
+				while ( elem.firstElementChild ) {
+					elem = elem.firstElementChild;
+				}
+
+				return elem;
+			} ).append( this );
+		}
+
+		return this;
+	},
+
+	wrapInner: function( html ) {
+		if ( jQuery.isFunction( html ) ) {
+			return this.each( function( i ) {
+				jQuery( this ).wrapInner( html.call( this, i ) );
+			} );
+		}
+
+		return this.each( function() {
+			var self = jQuery( this ),
+				contents = self.contents();
+
+			if ( contents.length ) {
+				contents.wrapAll( html );
+
+			} else {
+				self.append( html );
+			}
+		} );
+	},
+
+	wrap: function( html ) {
+		var isFunction = jQuery.isFunction( html );
+
+		return this.each( function( i ) {
+			jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
+		} );
+	},
+
+	unwrap: function() {
+		return this.parent().each( function() {
+			if ( !jQuery.nodeName( this, "body" ) ) {
+				jQuery( this ).replaceWith( this.childNodes );
+			}
+		} ).end();
+	}
+} );
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+	return !jQuery.expr.filters.visible( elem );
+};
+jQuery.expr.filters.visible = function( elem ) {
+
+	// Support: Opera <= 12.12
+	// Opera reports offsetWidths and offsetHeights less than zero on some elements
+	// Use OR instead of AND as the element is not visible if either is true
+	// See tickets #10406 and #13132
+	return elem.offsetWidth > 0 || elem.offsetHeight > 0 || elem.getClientRects().length > 0;
+};
+
+
+
+
+var r20 = /%20/g,
+	rbracket = /\[\]$/,
+	rCRLF = /\r?\n/g,
+	rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+	rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+	var name;
+
+	if ( jQuery.isArray( obj ) ) {
+
+		// Serialize array item.
+		jQuery.each( obj, function( i, v ) {
+			if ( traditional || rbracket.test( prefix ) ) {
+
+				// Treat each array item as a scalar.
+				add( prefix, v );
+
+			} else {
+
+				// Item is non-scalar (array or object), encode its numeric index.
+				buildParams(
+					prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
+					v,
+					traditional,
+					add
+				);
+			}
+		} );
+
+	} else if ( !traditional && jQuery.type( obj ) === "object" ) {
+
+		// Serialize object item.
+		for ( name in obj ) {
+			buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+		}
+
+	} else {
+
+		// Serialize scalar item.
+		add( prefix, obj );
+	}
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+	var prefix,
+		s = [],
+		add = function( key, value ) {
+
+			// If value is a function, invoke it and return its value
+			value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+			s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+		};
+
+	// Set traditional to true for jQuery <= 1.3.2 behavior.
+	if ( traditional === undefined ) {
+		traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+	}
+
+	// If an array was passed in, assume that it is an array of form elements.
+	if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+
+		// Serialize the form elements
+		jQuery.each( a, function() {
+			add( this.name, this.value );
+		} );
+
+	} else {
+
+		// If traditional, encode the "old" way (the way 1.3.2 or older
+		// did it), otherwise encode params recursively.
+		for ( prefix in a ) {
+			buildParams( prefix, a[ prefix ], traditional, add );
+		}
+	}
+
+	// Return the resulting serialization
+	return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend( {
+	serialize: function() {
+		return jQuery.param( this.serializeArray() );
+	},
+	serializeArray: function() {
+		return this.map( function() {
+
+			// Can add propHook for "elements" to filter or add form elements
+			var elements = jQuery.prop( this, "elements" );
+			return elements ? jQuery.makeArray( elements ) : this;
+		} )
+		.filter( function() {
+			var type = this.type;
+
+			// Use .is( ":disabled" ) so that fieldset[disabled] works
+			return this.name && !jQuery( this ).is( ":disabled" ) &&
+				rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+				( this.checked || !rcheckableType.test( type ) );
+		} )
+		.map( function( i, elem ) {
+			var val = jQuery( this ).val();
+
+			return val == null ?
+				null :
+				jQuery.isArray( val ) ?
+					jQuery.map( val, function( val ) {
+						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+					} ) :
+					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+		} ).get();
+	}
+} );
+
+
+jQuery.ajaxSettings.xhr = function() {
+	try {
+		return new window.XMLHttpRequest();
+	} catch ( e ) {}
+};
+
+var xhrSuccessStatus = {
+
+		// File protocol always yields status code 0, assume 200
+		0: 200,
+
+		// Support: IE9
+		// #1450: sometimes IE returns 1223 when it should be 204
+		1223: 204
+	},
+	xhrSupported = jQuery.ajaxSettings.xhr();
+
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport( function( options ) {
+	var callback, errorCallback;
+
+	// Cross domain only allowed if supported through XMLHttpRequest
+	if ( support.cors || xhrSupported && !options.crossDomain ) {
+		return {
+			send: function( headers, complete ) {
+				var i,
+					xhr = options.xhr();
+
+				xhr.open(
+					options.type,
+					options.url,
+					options.async,
+					options.username,
+					options.password
+				);
+
+				// Apply custom fields if provided
+				if ( options.xhrFields ) {
+					for ( i in options.xhrFields ) {
+						xhr[ i ] = options.xhrFields[ i ];
+					}
+				}
+
+				// Override mime type if needed
+				if ( options.mimeType && xhr.overrideMimeType ) {
+					xhr.overrideMimeType( options.mimeType );
+				}
+
+				// X-Requested-With header
+				// For cross-domain requests, seeing as conditions for a preflight are
+				// akin to a jigsaw puzzle, we simply never set it to be sure.
+				// (it can always be set on a per-request basis or even using ajaxSetup)
+				// For same-domain requests, won't change header if already provided.
+				if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
+					headers[ "X-Requested-With" ] = "XMLHttpRequest";
+				}
+
+				// Set headers
+				for ( i in headers ) {
+					xhr.setRequestHeader( i, headers[ i ] );
+				}
+
+				// Callback
+				callback = function( type ) {
+					return function() {
+						if ( callback ) {
+							callback = errorCallback = xhr.onload =
+								xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
+
+							if ( type === "abort" ) {
+								xhr.abort();
+							} else if ( type === "error" ) {
+
+								// Support: IE9
+								// On a manual native abort, IE9 throws
+								// errors on any property access that is not readyState
+								if ( typeof xhr.status !== "number" ) {
+									complete( 0, "error" );
+								} else {
+									complete(
+
+										// File: protocol always yields status 0; see #8605, #14207
+										xhr.status,
+										xhr.statusText
+									);
+								}
+							} else {
+								complete(
+									xhrSuccessStatus[ xhr.status ] || xhr.status,
+									xhr.statusText,
+
+									// Support: IE9 only
+									// IE9 has no XHR2 but throws on binary (trac-11426)
+									// For XHR2 non-text, let the caller handle it (gh-2498)
+									( xhr.responseType || "text" ) !== "text"  ||
+									typeof xhr.responseText !== "string" ?
+										{ binary: xhr.response } :
+										{ text: xhr.responseText },
+									xhr.getAllResponseHeaders()
+								);
+							}
+						}
+					};
+				};
+
+				// Listen to events
+				xhr.onload = callback();
+				errorCallback = xhr.onerror = callback( "error" );
+
+				// Support: IE9
+				// Use onreadystatechange to replace onabort
+				// to handle uncaught aborts
+				if ( xhr.onabort !== undefined ) {
+					xhr.onabort = errorCallback;
+				} else {
+					xhr.onreadystatechange = function() {
+
+						// Check readyState before timeout as it changes
+						if ( xhr.readyState === 4 ) {
+
+							// Allow onerror to be called first,
+							// but that will not handle a native abort
+							// Also, save errorCallback to a variable
+							// as xhr.onerror cannot be accessed
+							window.setTimeout( function() {
+								if ( callback ) {
+									errorCallback();
+								}
+							} );
+						}
+					};
+				}
+
+				// Create the abort callback
+				callback = callback( "abort" );
+
+				try {
+
+					// Do send the request (this may raise an exception)
+					xhr.send( options.hasContent && options.data || null );
+				} catch ( e ) {
+
+					// #14683: Only rethrow if this hasn't been notified as an error yet
+					if ( callback ) {
+						throw e;
+					}
+				}
+			},
+
+			abort: function() {
+				if ( callback ) {
+					callback();
+				}
+			}
+		};
+	}
+} );
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup( {
+	accepts: {
+		script: "text/javascript, application/javascript, " +
+			"application/ecmascript, application/x-ecmascript"
+	},
+	contents: {
+		script: /\b(?:java|ecma)script\b/
+	},
+	converters: {
+		"text script": function( text ) {
+			jQuery.globalEval( text );
+			return text;
+		}
+	}
+} );
+
+// Handle cache's special case and crossDomain
+jQuery.ajaxPrefilter( "script", function( s ) {
+	if ( s.cache === undefined ) {
+		s.cache = false;
+	}
+	if ( s.crossDomain ) {
+		s.type = "GET";
+	}
+} );
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function( s ) {
+
+	// This transport only deals with cross domain requests
+	if ( s.crossDomain ) {
+		var script, callback;
+		return {
+			send: function( _, complete ) {
+				script = jQuery( "<script>" ).prop( {
+					charset: s.scriptCharset,
+					src: s.url
+				} ).on(
+					"load error",
+					callback = function( evt ) {
+						script.remove();
+						callback = null;
+						if ( evt ) {
+							complete( evt.type === "error" ? 404 : 200, evt.type );
+						}
+					}
+				);
+
+				// Use native DOM manipulation to avoid our domManip AJAX trickery
+				document.head.appendChild( script[ 0 ] );
+			},
+			abort: function() {
+				if ( callback ) {
+					callback();
+				}
+			}
+		};
+	}
+} );
+
+
+
+
+var oldCallbacks = [],
+	rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup( {
+	jsonp: "callback",
+	jsonpCallback: function() {
+		var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+		this[ callback ] = true;
+		return callback;
+	}
+} );
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+	var callbackName, overwritten, responseContainer,
+		jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+			"url" :
+			typeof s.data === "string" &&
+				( s.contentType || "" )
+					.indexOf( "application/x-www-form-urlencoded" ) === 0 &&
+				rjsonp.test( s.data ) && "data"
+		);
+
+	// Handle iff the expected data type is "jsonp" or we have a parameter to set
+	if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+		// Get callback name, remembering preexisting value associated with it
+		callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+			s.jsonpCallback() :
+			s.jsonpCallback;
+
+		// Insert callback into url or form data
+		if ( jsonProp ) {
+			s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+		} else if ( s.jsonp !== false ) {
+			s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+		}
+
+		// Use data converter to retrieve json after script execution
+		s.converters[ "script json" ] = function() {
+			if ( !responseContainer ) {
+				jQuery.error( callbackName + " was not called" );
+			}
+			return responseContainer[ 0 ];
+		};
+
+		// Force json dataType
+		s.dataTypes[ 0 ] = "json";
+
+		// Install callback
+		overwritten = window[ callbackName ];
+		window[ callbackName ] = function() {
+			responseContainer = arguments;
+		};
+
+		// Clean-up function (fires after converters)
+		jqXHR.always( function() {
+
+			// If previous value didn't exist - remove it
+			if ( overwritten === undefined ) {
+				jQuery( window ).removeProp( callbackName );
+
+			// Otherwise restore preexisting value
+			} else {
+				window[ callbackName ] = overwritten;
+			}
+
+			// Save back as free
+			if ( s[ callbackName ] ) {
+
+				// Make sure that re-using the options doesn't screw things around
+				s.jsonpCallback = originalSettings.jsonpCallback;
+
+				// Save the callback name for future use
+				oldCallbacks.push( callbackName );
+			}
+
+			// Call if it was a function and we have a response
+			if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+				overwritten( responseContainer[ 0 ] );
+			}
+
+			responseContainer = overwritten = undefined;
+		} );
+
+		// Delegate to script
+		return "script";
+	}
+} );
+
+
+
+
+// Argument "data" should be string of html
+// context (optional): If specified, the fragment will be created in this context,
+// defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+	if ( !data || typeof data !== "string" ) {
+		return null;
+	}
+	if ( typeof context === "boolean" ) {
+		keepScripts = context;
+		context = false;
+	}
+	context = context || document;
+
+	var parsed = rsingleTag.exec( data ),
+		scripts = !keepScripts && [];
+
+	// Single tag
+	if ( parsed ) {
+		return [ context.createElement( parsed[ 1 ] ) ];
+	}
+
+	parsed = buildFragment( [ data ], context, scripts );
+
+	if ( scripts && scripts.length ) {
+		jQuery( scripts ).remove();
+	}
+
+	return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+	if ( typeof url !== "string" && _load ) {
+		return _load.apply( this, arguments );
+	}
+
+	var selector, type, response,
+		self = this,
+		off = url.indexOf( " " );
+
+	if ( off > -1 ) {
+		selector = jQuery.trim( url.slice( off ) );
+		url = url.slice( 0, off );
+	}
+
+	// If it's a function
+	if ( jQuery.isFunction( params ) ) {
+
+		// We assume that it's the callback
+		callback = params;
+		params = undefined;
+
+	// Otherwise, build a param string
+	} else if ( params && typeof params === "object" ) {
+		type = "POST";
+	}
+
+	// If we have elements to modify, make the request
+	if ( self.length > 0 ) {
+		jQuery.ajax( {
+			url: url,
+
+			// If "type" variable is undefined, then "GET" method will be used.
+			// Make value of this field explicit since
+			// user can override it through ajaxSetup method
+			type: type || "GET",
+			dataType: "html",
+			data: params
+		} ).done( function( responseText ) {
+
+			// Save response for use in complete callback
+			response = arguments;
+
+			self.html( selector ?
+
+				// If a selector was specified, locate the right elements in a dummy div
+				// Exclude scripts to avoid IE 'Permission Denied' errors
+				jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+				// Otherwise use the full result
+				responseText );
+
+		// If the request succeeds, this function gets "data", "status", "jqXHR"
+		// but they are ignored because response was set above.
+		// If it fails, this function gets "jqXHR", "status", "error"
+		} ).always( callback && function( jqXHR, status ) {
+			self.each( function() {
+				callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
+			} );
+		} );
+	}
+
+	return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [
+	"ajaxStart",
+	"ajaxStop",
+	"ajaxComplete",
+	"ajaxError",
+	"ajaxSuccess",
+	"ajaxSend"
+], function( i, type ) {
+	jQuery.fn[ type ] = function( fn ) {
+		return this.on( type, fn );
+	};
+} );
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+	return jQuery.grep( jQuery.timers, function( fn ) {
+		return elem === fn.elem;
+	} ).length;
+};
+
+
+
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+	return jQuery.isWindow( elem ) ? elem : elem.nodeType === 9 && elem.defaultView;
+}
+
+jQuery.offset = {
+	setOffset: function( elem, options, i ) {
+		var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+			position = jQuery.css( elem, "position" ),
+			curElem = jQuery( elem ),
+			props = {};
+
+		// Set position first, in-case top/left are set even on static elem
+		if ( position === "static" ) {
+			elem.style.position = "relative";
+		}
+
+		curOffset = curElem.offset();
+		curCSSTop = jQuery.css( elem, "top" );
+		curCSSLeft = jQuery.css( elem, "left" );
+		calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+			( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
+
+		// Need to be able to calculate position if either
+		// top or left is auto and position is either absolute or fixed
+		if ( calculatePosition ) {
+			curPosition = curElem.position();
+			curTop = curPosition.top;
+			curLeft = curPosition.left;
+
+		} else {
+			curTop = parseFloat( curCSSTop ) || 0;
+			curLeft = parseFloat( curCSSLeft ) || 0;
+		}
+
+		if ( jQuery.isFunction( options ) ) {
+
+			// Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
+			options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
+		}
+
+		if ( options.top != null ) {
+			props.top = ( options.top - curOffset.top ) + curTop;
+		}
+		if ( options.left != null ) {
+			props.left = ( options.left - curOffset.left ) + curLeft;
+		}
+
+		if ( "using" in options ) {
+			options.using.call( elem, props );
+
+		} else {
+			curElem.css( props );
+		}
+	}
+};
+
+jQuery.fn.extend( {
+	offset: function( options ) {
+		if ( arguments.length ) {
+			return options === undefined ?
+				this :
+				this.each( function( i ) {
+					jQuery.offset.setOffset( this, options, i );
+				} );
+		}
+
+		var docElem, win,
+			elem = this[ 0 ],
+			box = { top: 0, left: 0 },
+			doc = elem && elem.ownerDocument;
+
+		if ( !doc ) {
+			return;
+		}
+
+		docElem = doc.documentElement;
+
+		// Make sure it's not a disconnected DOM node
+		if ( !jQuery.contains( docElem, elem ) ) {
+			return box;
+		}
+
+		box = elem.getBoundingClientRect();
+		win = getWindow( doc );
+		return {
+			top: box.top + win.pageYOffset - docElem.clientTop,
+			left: box.left + win.pageXOffset - docElem.clientLeft
+		};
+	},
+
+	position: function() {
+		if ( !this[ 0 ] ) {
+			return;
+		}
+
+		var offsetParent, offset,
+			elem = this[ 0 ],
+			parentOffset = { top: 0, left: 0 };
+
+		// Fixed elements are offset from window (parentOffset = {top:0, left: 0},
+		// because it is its only offset parent
+		if ( jQuery.css( elem, "position" ) === "fixed" ) {
+
+			// Assume getBoundingClientRect is there when computed position is fixed
+			offset = elem.getBoundingClientRect();
+
+		} else {
+
+			// Get *real* offsetParent
+			offsetParent = this.offsetParent();
+
+			// Get correct offsets
+			offset = this.offset();
+			if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+				parentOffset = offsetParent.offset();
+			}
+
+			// Add offsetParent borders
+			parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+			parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+		}
+
+		// Subtract parent offsets and element margins
+		return {
+			top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+			left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+		};
+	},
+
+	// This method will return documentElement in the following cases:
+	// 1) For the element inside the iframe without offsetParent, this method will return
+	//    documentElement of the parent window
+	// 2) For the hidden or detached element
+	// 3) For body or html element, i.e. in case of the html node - it will return itself
+	//
+	// but those exceptions were never presented as a real life use-cases
+	// and might be considered as more preferable results.
+	//
+	// This logic, however, is not guaranteed and can change at any point in the future
+	offsetParent: function() {
+		return this.map( function() {
+			var offsetParent = this.offsetParent;
+
+			while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
+				offsetParent = offsetParent.offsetParent;
+			}
+
+			return offsetParent || documentElement;
+		} );
+	}
+} );
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+	var top = "pageYOffset" === prop;
+
+	jQuery.fn[ method ] = function( val ) {
+		return access( this, function( elem, method, val ) {
+			var win = getWindow( elem );
+
+			if ( val === undefined ) {
+				return win ? win[ prop ] : elem[ method ];
+			}
+
+			if ( win ) {
+				win.scrollTo(
+					!top ? val : win.pageXOffset,
+					top ? val : win.pageYOffset
+				);
+
+			} else {
+				elem[ method ] = val;
+			}
+		}, method, val, arguments.length );
+	};
+} );
+
+// Support: Safari<7-8+, Chrome<37-44+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// Blink bug: https://code.google.com/p/chromium/issues/detail?id=229280
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+	jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+		function( elem, computed ) {
+			if ( computed ) {
+				computed = curCSS( elem, prop );
+
+				// If curCSS returns percentage, fallback to offset
+				return rnumnonpx.test( computed ) ?
+					jQuery( elem ).position()[ prop ] + "px" :
+					computed;
+			}
+		}
+	);
+} );
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+	jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
+		function( defaultExtra, funcName ) {
+
+		// Margin is only for outerHeight, outerWidth
+		jQuery.fn[ funcName ] = function( margin, value ) {
+			var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+				extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+			return access( this, function( elem, type, value ) {
+				var doc;
+
+				if ( jQuery.isWindow( elem ) ) {
+
+					// As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+					// isn't a whole lot we can do. See pull request at this URL for discussion:
+					// https://github.com/jquery/jquery/pull/764
+					return elem.document.documentElement[ "client" + name ];
+				}
+
+				// Get document width or height
+				if ( elem.nodeType === 9 ) {
+					doc = elem.documentElement;
+
+					// Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+					// whichever is greatest
+					return Math.max(
+						elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+						elem.body[ "offset" + name ], doc[ "offset" + name ],
+						doc[ "client" + name ]
+					);
+				}
+
+				return value === undefined ?
+
+					// Get width or height on the element, requesting but not forcing parseFloat
+					jQuery.css( elem, type, extra ) :
+
+					// Set width or height on the element
+					jQuery.style( elem, type, value, extra );
+			}, type, chainable ? margin : undefined, chainable, null );
+		};
+	} );
+} );
+
+
+jQuery.fn.extend( {
+
+	bind: function( types, data, fn ) {
+		return this.on( types, null, data, fn );
+	},
+	unbind: function( types, fn ) {
+		return this.off( types, null, fn );
+	},
+
+	delegate: function( selector, types, data, fn ) {
+		return this.on( types, selector, data, fn );
+	},
+	undelegate: function( selector, types, fn ) {
+
+		// ( namespace ) or ( selector, types [, fn] )
+		return arguments.length === 1 ?
+			this.off( selector, "**" ) :
+			this.off( types, selector || "**", fn );
+	},
+	size: function() {
+		return this.length;
+	}
+} );
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+	define( "jquery", [], function() {
+		return jQuery;
+	} );
+}
+
+
+
+var
+
+	// Map over jQuery in case of overwrite
+	_jQuery = window.jQuery,
+
+	// Map over the $ in case of overwrite
+	_$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+	if ( window.$ === jQuery ) {
+		window.$ = _$;
+	}
+
+	if ( deep && window.jQuery === jQuery ) {
+		window.jQuery = _jQuery;
+	}
+
+	return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( !noGlobal ) {
+	window.jQuery = window.$ = jQuery;
+}
+
+return jQuery;
+}));
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.min.js
new file mode 100644
index 0000000..4024b66
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.min.js
@@ -0,0 +1,4 @@
+/*! jQuery v2.2.4 | (c) jQuery Foundation | jquery.org/license */
+!function(a,b){"object"==typeof module&&"object"==typeof module.exports?module.exports=a.document?b(a,!0):function(a){if(!a.document)throw new Error("jQuery requires a window with a document");return b(a)}:b(a)}("undefined"!=typeof window?window:this,function(a,b){var c=[],d=a.document,e=c.slice,f=c.concat,g=c.push,h=c.indexOf,i={},j=i.toString,k=i.hasOwnProperty,l={},m="2.2.4",n=function(a,b){return new n.fn.init(a,b)},o=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,p=/^-ms-/,q=/-([\da-z])/gi,r= [...]
+}catch(e){}O.set(a,b,c)}else c=void 0;return c}n.extend({hasData:function(a){return O.hasData(a)||N.hasData(a)},data:function(a,b,c){return O.access(a,b,c)},removeData:function(a,b){O.remove(a,b)},_data:function(a,b,c){return N.access(a,b,c)},_removeData:function(a,b){N.remove(a,b)}}),n.fn.extend({data:function(a,b){var c,d,e,f=this[0],g=f&&f.attributes;if(void 0===a){if(this.length&&(e=O.get(f),1===f.nodeType&&!N.get(f,"hasDataAttrs"))){c=g.length;while(c--)g[c]&&(d=g[c].name,0===d.inde [...]
+void 0!==c?e&&"set"in e&&void 0!==(d=e.set(a,c,b))?d:a[b]=c:e&&"get"in e&&null!==(d=e.get(a,b))?d:a[b]},propHooks:{tabIndex:{get:function(a){var b=n.find.attr(a,"tabindex");return b?parseInt(b,10):cb.test(a.nodeName)||db.test(a.nodeName)&&a.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),l.optSelected||(n.propHooks.selected={get:function(a){var b=a.parentNode;return b&&b.parentNode&&b.parentNode.selectedIndex,null},set:function(a){var b=a.parentNode;b&&(b.selectedIndex,b.par [...]
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.min.map b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.min.map
new file mode 100644
index 0000000..49efa4b
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/jquery/jquery-2.2.4.min.map
@@ -0,0 +1 @@
+{"version":3,"sources":["jquery.js"],"names":["global","factory","module","exports","document","w","Error","window","this","noGlobal","arr","slice","concat","push","indexOf","class2type","toString","hasOwn","hasOwnProperty","support","version","jQuery","selector","context","fn","init","rtrim","rmsPrefix","rdashAlpha","fcamelCase","all","letter","toUpperCase","prototype","jquery","constructor","length","toArray","call","get","num","pushStack","elems","ret","merge","prevObject","each","cal [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/moment/2.13.0/moment-with-locales.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/moment/2.13.0/moment-with-locales.js
new file mode 100644
index 0000000..b8f0313
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/moment/2.13.0/moment-with-locales.js
@@ -0,0 +1,12051 @@
+;(function (global, factory) {
+    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+    typeof define === 'function' && define.amd ? define(factory) :
+    global.moment = factory()
+}(this, function () { 'use strict';
+
+    var hookCallback;
+
+    function utils_hooks__hooks () {
+        return hookCallback.apply(null, arguments);
+    }
+
+    // This is done to register the method called with moment()
+    // without creating circular dependencies.
+    function setHookCallback (callback) {
+        hookCallback = callback;
+    }
+
+    function isArray(input) {
+        return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
+    }
+
+    function isDate(input) {
+        return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
+    }
+
+    function map(arr, fn) {
+        var res = [], i;
+        for (i = 0; i < arr.length; ++i) {
+            res.push(fn(arr[i], i));
+        }
+        return res;
+    }
+
+    function hasOwnProp(a, b) {
+        return Object.prototype.hasOwnProperty.call(a, b);
+    }
+
+    function extend(a, b) {
+        for (var i in b) {
+            if (hasOwnProp(b, i)) {
+                a[i] = b[i];
+            }
+        }
+
+        if (hasOwnProp(b, 'toString')) {
+            a.toString = b.toString;
+        }
+
+        if (hasOwnProp(b, 'valueOf')) {
+            a.valueOf = b.valueOf;
+        }
+
+        return a;
+    }
+
+    function create_utc__createUTC (input, format, locale, strict) {
+        return createLocalOrUTC(input, format, locale, strict, true).utc();
+    }
+
+    function defaultParsingFlags() {
+        // We need to deep clone this object.
+        return {
+            empty           : false,
+            unusedTokens    : [],
+            unusedInput     : [],
+            overflow        : -2,
+            charsLeftOver   : 0,
+            nullInput       : false,
+            invalidMonth    : null,
+            invalidFormat   : false,
+            userInvalidated : false,
+            iso             : false,
+            parsedDateParts : [],
+            meridiem        : null
+        };
+    }
+
+    function getParsingFlags(m) {
+        if (m._pf == null) {
+            m._pf = defaultParsingFlags();
+        }
+        return m._pf;
+    }
+
+    var some;
+    if (Array.prototype.some) {
+        some = Array.prototype.some;
+    } else {
+        some = function (fun) {
+            var t = Object(this);
+            var len = t.length >>> 0;
+
+            for (var i = 0; i < len; i++) {
+                if (i in t && fun.call(this, t[i], i, t)) {
+                    return true;
+                }
+            }
+
+            return false;
+        };
+    }
+
+    function valid__isValid(m) {
+        if (m._isValid == null) {
+            var flags = getParsingFlags(m);
+            var parsedParts = some.call(flags.parsedDateParts, function (i) {
+                return i != null;
+            });
+            m._isValid = !isNaN(m._d.getTime()) &&
+                flags.overflow < 0 &&
+                !flags.empty &&
+                !flags.invalidMonth &&
+                !flags.invalidWeekday &&
+                !flags.nullInput &&
+                !flags.invalidFormat &&
+                !flags.userInvalidated &&
+                (!flags.meridiem || (flags.meridiem && parsedParts));
+
+            if (m._strict) {
+                m._isValid = m._isValid &&
+                    flags.charsLeftOver === 0 &&
+                    flags.unusedTokens.length === 0 &&
+                    flags.bigHour === undefined;
+            }
+        }
+        return m._isValid;
+    }
+
+    function valid__createInvalid (flags) {
+        var m = create_utc__createUTC(NaN);
+        if (flags != null) {
+            extend(getParsingFlags(m), flags);
+        }
+        else {
+            getParsingFlags(m).userInvalidated = true;
+        }
+
+        return m;
+    }
+
+    function isUndefined(input) {
+        return input === void 0;
+    }
+
+    // Plugins that add properties should also add the key here (null value),
+    // so we can properly clone ourselves.
+    var momentProperties = utils_hooks__hooks.momentProperties = [];
+
+    function copyConfig(to, from) {
+        var i, prop, val;
+
+        if (!isUndefined(from._isAMomentObject)) {
+            to._isAMomentObject = from._isAMomentObject;
+        }
+        if (!isUndefined(from._i)) {
+            to._i = from._i;
+        }
+        if (!isUndefined(from._f)) {
+            to._f = from._f;
+        }
+        if (!isUndefined(from._l)) {
+            to._l = from._l;
+        }
+        if (!isUndefined(from._strict)) {
+            to._strict = from._strict;
+        }
+        if (!isUndefined(from._tzm)) {
+            to._tzm = from._tzm;
+        }
+        if (!isUndefined(from._isUTC)) {
+            to._isUTC = from._isUTC;
+        }
+        if (!isUndefined(from._offset)) {
+            to._offset = from._offset;
+        }
+        if (!isUndefined(from._pf)) {
+            to._pf = getParsingFlags(from);
+        }
+        if (!isUndefined(from._locale)) {
+            to._locale = from._locale;
+        }
+
+        if (momentProperties.length > 0) {
+            for (i in momentProperties) {
+                prop = momentProperties[i];
+                val = from[prop];
+                if (!isUndefined(val)) {
+                    to[prop] = val;
+                }
+            }
+        }
+
+        return to;
+    }
+
+    var updateInProgress = false;
+
+    // Moment prototype object
+    function Moment(config) {
+        copyConfig(this, config);
+        this._d = new Date(config._d != null ? config._d.getTime() : NaN);
+        // Prevent infinite loop in case updateOffset creates new moment
+        // objects.
+        if (updateInProgress === false) {
+            updateInProgress = true;
+            utils_hooks__hooks.updateOffset(this);
+            updateInProgress = false;
+        }
+    }
+
+    function isMoment (obj) {
+        return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
+    }
+
+    function absFloor (number) {
+        if (number < 0) {
+            return Math.ceil(number);
+        } else {
+            return Math.floor(number);
+        }
+    }
+
+    function toInt(argumentForCoercion) {
+        var coercedNumber = +argumentForCoercion,
+            value = 0;
+
+        if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+            value = absFloor(coercedNumber);
+        }
+
+        return value;
+    }
+
+    // compare two arrays, return the number of differences
+    function compareArrays(array1, array2, dontConvert) {
+        var len = Math.min(array1.length, array2.length),
+            lengthDiff = Math.abs(array1.length - array2.length),
+            diffs = 0,
+            i;
+        for (i = 0; i < len; i++) {
+            if ((dontConvert && array1[i] !== array2[i]) ||
+                (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
+                diffs++;
+            }
+        }
+        return diffs + lengthDiff;
+    }
+
+    function warn(msg) {
+        if (utils_hooks__hooks.suppressDeprecationWarnings === false &&
+                (typeof console !==  'undefined') && console.warn) {
+            console.warn('Deprecation warning: ' + msg);
+        }
+    }
+
+    function deprecate(msg, fn) {
+        var firstTime = true;
+
+        return extend(function () {
+            if (utils_hooks__hooks.deprecationHandler != null) {
+                utils_hooks__hooks.deprecationHandler(null, msg);
+            }
+            if (firstTime) {
+                warn(msg + '\nArguments: ' + Array.prototype.slice.call(arguments).join(', ') + '\n' + (new Error()).stack);
+                firstTime = false;
+            }
+            return fn.apply(this, arguments);
+        }, fn);
+    }
+
+    var deprecations = {};
+
+    function deprecateSimple(name, msg) {
+        if (utils_hooks__hooks.deprecationHandler != null) {
+            utils_hooks__hooks.deprecationHandler(name, msg);
+        }
+        if (!deprecations[name]) {
+            warn(msg);
+            deprecations[name] = true;
+        }
+    }
+
+    utils_hooks__hooks.suppressDeprecationWarnings = false;
+    utils_hooks__hooks.deprecationHandler = null;
+
+    function isFunction(input) {
+        return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
+    }
+
+    function isObject(input) {
+        return Object.prototype.toString.call(input) === '[object Object]';
+    }
+
+    function locale_set__set (config) {
+        var prop, i;
+        for (i in config) {
+            prop = config[i];
+            if (isFunction(prop)) {
+                this[i] = prop;
+            } else {
+                this['_' + i] = prop;
+            }
+        }
+        this._config = config;
+        // Lenient ordinal parsing accepts just a number in addition to
+        // number + (possibly) stuff coming from _ordinalParseLenient.
+        this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + (/\d{1,2}/).source);
+    }
+
+    function mergeConfigs(parentConfig, childConfig) {
+        var res = extend({}, parentConfig), prop;
+        for (prop in childConfig) {
+            if (hasOwnProp(childConfig, prop)) {
+                if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
+                    res[prop] = {};
+                    extend(res[prop], parentConfig[prop]);
+                    extend(res[prop], childConfig[prop]);
+                } else if (childConfig[prop] != null) {
+                    res[prop] = childConfig[prop];
+                } else {
+                    delete res[prop];
+                }
+            }
+        }
+        return res;
+    }
+
+    function Locale(config) {
+        if (config != null) {
+            this.set(config);
+        }
+    }
+
+    var keys;
+
+    if (Object.keys) {
+        keys = Object.keys;
+    } else {
+        keys = function (obj) {
+            var i, res = [];
+            for (i in obj) {
+                if (hasOwnProp(obj, i)) {
+                    res.push(i);
+                }
+            }
+            return res;
+        };
+    }
+
+    // internal storage for locale config files
+    var locales = {};
+    var globalLocale;
+
+    function normalizeLocale(key) {
+        return key ? key.toLowerCase().replace('_', '-') : key;
+    }
+
+    // pick the locale from the array
+    // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+    // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+    function chooseLocale(names) {
+        var i = 0, j, next, locale, split;
+
+        while (i < names.length) {
+            split = normalizeLocale(names[i]).split('-');
+            j = split.length;
+            next = normalizeLocale(names[i + 1]);
+            next = next ? next.split('-') : null;
+            while (j > 0) {
+                locale = loadLocale(split.slice(0, j).join('-'));
+                if (locale) {
+                    return locale;
+                }
+                if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
+                    //the next array item is better than a shallower substring of this one
+                    break;
+                }
+                j--;
+            }
+            i++;
+        }
+        return null;
+    }
+
+    function loadLocale(name) {
+        var oldLocale = null;
+        // TODO: Find a better way to register and load all the locales in Node
+        if (!locales[name] && (typeof module !== 'undefined') &&
+                module && module.exports) {
+            try {
+                oldLocale = globalLocale._abbr;
+                require('./locale/' + name);
+                // because defineLocale currently also sets the global locale, we
+                // want to undo that for lazy loaded locales
+                locale_locales__getSetGlobalLocale(oldLocale);
+            } catch (e) { }
+        }
+        return locales[name];
+    }
+
+    // This function will load locale and then set the global locale.  If
+    // no arguments are passed in, it will simply return the current global
+    // locale key.
+    function locale_locales__getSetGlobalLocale (key, values) {
+        var data;
+        if (key) {
+            if (isUndefined(values)) {
+                data = locale_locales__getLocale(key);
+            }
+            else {
+                data = defineLocale(key, values);
+            }
+
+            if (data) {
+                // moment.duration._locale = moment._locale = data;
+                globalLocale = data;
+            }
+        }
+
+        return globalLocale._abbr;
+    }
+
+    function defineLocale (name, config) {
+        if (config !== null) {
+            config.abbr = name;
+            if (locales[name] != null) {
+                deprecateSimple('defineLocaleOverride',
+                        'use moment.updateLocale(localeName, config) to change ' +
+                        'an existing locale. moment.defineLocale(localeName, ' +
+                        'config) should only be used for creating a new locale');
+                config = mergeConfigs(locales[name]._config, config);
+            } else if (config.parentLocale != null) {
+                if (locales[config.parentLocale] != null) {
+                    config = mergeConfigs(locales[config.parentLocale]._config, config);
+                } else {
+                    // treat as if there is no base config
+                    deprecateSimple('parentLocaleUndefined',
+                            'specified parentLocale is not defined yet');
+                }
+            }
+            locales[name] = new Locale(config);
+
+            // backwards compat for now: also set the locale
+            locale_locales__getSetGlobalLocale(name);
+
+            return locales[name];
+        } else {
+            // useful for testing
+            delete locales[name];
+            return null;
+        }
+    }
+
+    function updateLocale(name, config) {
+        if (config != null) {
+            var locale;
+            if (locales[name] != null) {
+                config = mergeConfigs(locales[name]._config, config);
+            }
+            locale = new Locale(config);
+            locale.parentLocale = locales[name];
+            locales[name] = locale;
+
+            // backwards compat for now: also set the locale
+            locale_locales__getSetGlobalLocale(name);
+        } else {
+            // pass null for config to unupdate, useful for tests
+            if (locales[name] != null) {
+                if (locales[name].parentLocale != null) {
+                    locales[name] = locales[name].parentLocale;
+                } else if (locales[name] != null) {
+                    delete locales[name];
+                }
+            }
+        }
+        return locales[name];
+    }
+
+    // returns locale data
+    function locale_locales__getLocale (key) {
+        var locale;
+
+        if (key && key._locale && key._locale._abbr) {
+            key = key._locale._abbr;
+        }
+
+        if (!key) {
+            return globalLocale;
+        }
+
+        if (!isArray(key)) {
+            //short-circuit everything else
+            locale = loadLocale(key);
+            if (locale) {
+                return locale;
+            }
+            key = [key];
+        }
+
+        return chooseLocale(key);
+    }
+
+    function locale_locales__listLocales() {
+        return keys(locales);
+    }
+
+    var aliases = {};
+
+    function addUnitAlias (unit, shorthand) {
+        var lowerCase = unit.toLowerCase();
+        aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
+    }
+
+    function normalizeUnits(units) {
+        return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
+    }
+
+    function normalizeObjectUnits(inputObject) {
+        var normalizedInput = {},
+            normalizedProp,
+            prop;
+
+        for (prop in inputObject) {
+            if (hasOwnProp(inputObject, prop)) {
+                normalizedProp = normalizeUnits(prop);
+                if (normalizedProp) {
+                    normalizedInput[normalizedProp] = inputObject[prop];
+                }
+            }
+        }
+
+        return normalizedInput;
+    }
+
+    function makeGetSet (unit, keepTime) {
+        return function (value) {
+            if (value != null) {
+                get_set__set(this, unit, value);
+                utils_hooks__hooks.updateOffset(this, keepTime);
+                return this;
+            } else {
+                return get_set__get(this, unit);
+            }
+        };
+    }
+
+    function get_set__get (mom, unit) {
+        return mom.isValid() ?
+            mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
+    }
+
+    function get_set__set (mom, unit, value) {
+        if (mom.isValid()) {
+            mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+        }
+    }
+
+    // MOMENTS
+
+    function getSet (units, value) {
+        var unit;
+        if (typeof units === 'object') {
+            for (unit in units) {
+                this.set(unit, units[unit]);
+            }
+        } else {
+            units = normalizeUnits(units);
+            if (isFunction(this[units])) {
+                return this[units](value);
+            }
+        }
+        return this;
+    }
+
+    function zeroFill(number, targetLength, forceSign) {
+        var absNumber = '' + Math.abs(number),
+            zerosToFill = targetLength - absNumber.length,
+            sign = number >= 0;
+        return (sign ? (forceSign ? '+' : '') : '-') +
+            Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
+    }
+
+    var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
+
+    var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
+
+    var formatFunctions = {};
+
+    var formatTokenFunctions = {};
+
+    // token:    'M'
+    // padded:   ['MM', 2]
+    // ordinal:  'Mo'
+    // callback: function () { this.month() + 1 }
+    function addFormatToken (token, padded, ordinal, callback) {
+        var func = callback;
+        if (typeof callback === 'string') {
+            func = function () {
+                return this[callback]();
+            };
+        }
+        if (token) {
+            formatTokenFunctions[token] = func;
+        }
+        if (padded) {
+            formatTokenFunctions[padded[0]] = function () {
+                return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
+            };
+        }
+        if (ordinal) {
+            formatTokenFunctions[ordinal] = function () {
+                return this.localeData().ordinal(func.apply(this, arguments), token);
+            };
+        }
+    }
+
+    function removeFormattingTokens(input) {
+        if (input.match(/\[[\s\S]/)) {
+            return input.replace(/^\[|\]$/g, '');
+        }
+        return input.replace(/\\/g, '');
+    }
+
+    function makeFormatFunction(format) {
+        var array = format.match(formattingTokens), i, length;
+
+        for (i = 0, length = array.length; i < length; i++) {
+            if (formatTokenFunctions[array[i]]) {
+                array[i] = formatTokenFunctions[array[i]];
+            } else {
+                array[i] = removeFormattingTokens(array[i]);
+            }
+        }
+
+        return function (mom) {
+            var output = '', i;
+            for (i = 0; i < length; i++) {
+                output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
+            }
+            return output;
+        };
+    }
+
+    // format date using native date object
+    function formatMoment(m, format) {
+        if (!m.isValid()) {
+            return m.localeData().invalidDate();
+        }
+
+        format = expandFormat(format, m.localeData());
+        formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
+
+        return formatFunctions[format](m);
+    }
+
+    function expandFormat(format, locale) {
+        var i = 5;
+
+        function replaceLongDateFormatTokens(input) {
+            return locale.longDateFormat(input) || input;
+        }
+
+        localFormattingTokens.lastIndex = 0;
+        while (i >= 0 && localFormattingTokens.test(format)) {
+            format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+            localFormattingTokens.lastIndex = 0;
+            i -= 1;
+        }
+
+        return format;
+    }
+
+    var match1         = /\d/;            //       0 - 9
+    var match2         = /\d\d/;          //      00 - 99
+    var match3         = /\d{3}/;         //     000 - 999
+    var match4         = /\d{4}/;         //    0000 - 9999
+    var match6         = /[+-]?\d{6}/;    // -999999 - 999999
+    var match1to2      = /\d\d?/;         //       0 - 99
+    var match3to4      = /\d\d\d\d?/;     //     999 - 9999
+    var match5to6      = /\d\d\d\d\d\d?/; //   99999 - 999999
+    var match1to3      = /\d{1,3}/;       //       0 - 999
+    var match1to4      = /\d{1,4}/;       //       0 - 9999
+    var match1to6      = /[+-]?\d{1,6}/;  // -999999 - 999999
+
+    var matchUnsigned  = /\d+/;           //       0 - inf
+    var matchSigned    = /[+-]?\d+/;      //    -inf - inf
+
+    var matchOffset    = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
+    var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
+
+    var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
+
+    // any word (or two) characters or numbers including two/three word month in arabic.
+    // includes scottish gaelic two word and hyphenated months
+    var matchWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i;
+
+
+    var regexes = {};
+
+    function addRegexToken (token, regex, strictRegex) {
+        regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
+            return (isStrict && strictRegex) ? strictRegex : regex;
+        };
+    }
+
+    function getParseRegexForToken (token, config) {
+        if (!hasOwnProp(regexes, token)) {
+            return new RegExp(unescapeFormat(token));
+        }
+
+        return regexes[token](config._strict, config._locale);
+    }
+
+    // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+    function unescapeFormat(s) {
+        return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
+            return p1 || p2 || p3 || p4;
+        }));
+    }
+
+    function regexEscape(s) {
+        return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+    }
+
+    var tokens = {};
+
+    function addParseToken (token, callback) {
+        var i, func = callback;
+        if (typeof token === 'string') {
+            token = [token];
+        }
+        if (typeof callback === 'number') {
+            func = function (input, array) {
+                array[callback] = toInt(input);
+            };
+        }
+        for (i = 0; i < token.length; i++) {
+            tokens[token[i]] = func;
+        }
+    }
+
+    function addWeekParseToken (token, callback) {
+        addParseToken(token, function (input, array, config, token) {
+            config._w = config._w || {};
+            callback(input, config._w, config, token);
+        });
+    }
+
+    function addTimeToArrayFromToken(token, input, config) {
+        if (input != null && hasOwnProp(tokens, token)) {
+            tokens[token](input, config._a, config, token);
+        }
+    }
+
+    var YEAR = 0;
+    var MONTH = 1;
+    var DATE = 2;
+    var HOUR = 3;
+    var MINUTE = 4;
+    var SECOND = 5;
+    var MILLISECOND = 6;
+    var WEEK = 7;
+    var WEEKDAY = 8;
+
+    var indexOf;
+
+    if (Array.prototype.indexOf) {
+        indexOf = Array.prototype.indexOf;
+    } else {
+        indexOf = function (o) {
+            // I know
+            var i;
+            for (i = 0; i < this.length; ++i) {
+                if (this[i] === o) {
+                    return i;
+                }
+            }
+            return -1;
+        };
+    }
+
+    function daysInMonth(year, month) {
+        return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
+    }
+
+    // FORMATTING
+
+    addFormatToken('M', ['MM', 2], 'Mo', function () {
+        return this.month() + 1;
+    });
+
+    addFormatToken('MMM', 0, 0, function (format) {
+        return this.localeData().monthsShort(this, format);
+    });
+
+    addFormatToken('MMMM', 0, 0, function (format) {
+        return this.localeData().months(this, format);
+    });
+
+    // ALIASES
+
+    addUnitAlias('month', 'M');
+
+    // PARSING
+
+    addRegexToken('M',    match1to2);
+    addRegexToken('MM',   match1to2, match2);
+    addRegexToken('MMM',  function (isStrict, locale) {
+        return locale.monthsShortRegex(isStrict);
+    });
+    addRegexToken('MMMM', function (isStrict, locale) {
+        return locale.monthsRegex(isStrict);
+    });
+
+    addParseToken(['M', 'MM'], function (input, array) {
+        array[MONTH] = toInt(input) - 1;
+    });
+
+    addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
+        var month = config._locale.monthsParse(input, token, config._strict);
+        // if we didn't find a month name, mark the date as invalid.
+        if (month != null) {
+            array[MONTH] = month;
+        } else {
+            getParsingFlags(config).invalidMonth = input;
+        }
+    });
+
+    // LOCALES
+
+    var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s+)+MMMM?/;
+    var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
+    function localeMonths (m, format) {
+        return isArray(this._months) ? this._months[m.month()] :
+            this._months[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
+    }
+
+    var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
+    function localeMonthsShort (m, format) {
+        return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
+            this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
+    }
+
+    function units_month__handleStrictParse(monthName, format, strict) {
+        var i, ii, mom, llc = monthName.toLocaleLowerCase();
+        if (!this._monthsParse) {
+            // this is not used
+            this._monthsParse = [];
+            this._longMonthsParse = [];
+            this._shortMonthsParse = [];
+            for (i = 0; i < 12; ++i) {
+                mom = create_utc__createUTC([2000, i]);
+                this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
+                this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
+            }
+        }
+
+        if (strict) {
+            if (format === 'MMM') {
+                ii = indexOf.call(this._shortMonthsParse, llc);
+                return ii !== -1 ? ii : null;
+            } else {
+                ii = indexOf.call(this._longMonthsParse, llc);
+                return ii !== -1 ? ii : null;
+            }
+        } else {
+            if (format === 'MMM') {
+                ii = indexOf.call(this._shortMonthsParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._longMonthsParse, llc);
+                return ii !== -1 ? ii : null;
+            } else {
+                ii = indexOf.call(this._longMonthsParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._shortMonthsParse, llc);
+                return ii !== -1 ? ii : null;
+            }
+        }
+    }
+
+    function localeMonthsParse (monthName, format, strict) {
+        var i, mom, regex;
+
+        if (this._monthsParseExact) {
+            return units_month__handleStrictParse.call(this, monthName, format, strict);
+        }
+
+        if (!this._monthsParse) {
+            this._monthsParse = [];
+            this._longMonthsParse = [];
+            this._shortMonthsParse = [];
+        }
+
+        // TODO: add sorting
+        // Sorting makes sure if one month (or abbr) is a prefix of another
+        // see sorting in computeMonthsParse
+        for (i = 0; i < 12; i++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, i]);
+            if (strict && !this._longMonthsParse[i]) {
+                this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
+                this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
+            }
+            if (!strict && !this._monthsParse[i]) {
+                regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+                this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+            }
+            // test the regex
+            if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
+                return i;
+            } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
+                return i;
+            } else if (!strict && this._monthsParse[i].test(monthName)) {
+                return i;
+            }
+        }
+    }
+
+    // MOMENTS
+
+    function setMonth (mom, value) {
+        var dayOfMonth;
+
+        if (!mom.isValid()) {
+            // No op
+            return mom;
+        }
+
+        if (typeof value === 'string') {
+            if (/^\d+$/.test(value)) {
+                value = toInt(value);
+            } else {
+                value = mom.localeData().monthsParse(value);
+                // TODO: Another silent failure?
+                if (typeof value !== 'number') {
+                    return mom;
+                }
+            }
+        }
+
+        dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
+        mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+        return mom;
+    }
+
+    function getSetMonth (value) {
+        if (value != null) {
+            setMonth(this, value);
+            utils_hooks__hooks.updateOffset(this, true);
+            return this;
+        } else {
+            return get_set__get(this, 'Month');
+        }
+    }
+
+    function getDaysInMonth () {
+        return daysInMonth(this.year(), this.month());
+    }
+
+    var defaultMonthsShortRegex = matchWord;
+    function monthsShortRegex (isStrict) {
+        if (this._monthsParseExact) {
+            if (!hasOwnProp(this, '_monthsRegex')) {
+                computeMonthsParse.call(this);
+            }
+            if (isStrict) {
+                return this._monthsShortStrictRegex;
+            } else {
+                return this._monthsShortRegex;
+            }
+        } else {
+            return this._monthsShortStrictRegex && isStrict ?
+                this._monthsShortStrictRegex : this._monthsShortRegex;
+        }
+    }
+
+    var defaultMonthsRegex = matchWord;
+    function monthsRegex (isStrict) {
+        if (this._monthsParseExact) {
+            if (!hasOwnProp(this, '_monthsRegex')) {
+                computeMonthsParse.call(this);
+            }
+            if (isStrict) {
+                return this._monthsStrictRegex;
+            } else {
+                return this._monthsRegex;
+            }
+        } else {
+            return this._monthsStrictRegex && isStrict ?
+                this._monthsStrictRegex : this._monthsRegex;
+        }
+    }
+
+    function computeMonthsParse () {
+        function cmpLenRev(a, b) {
+            return b.length - a.length;
+        }
+
+        var shortPieces = [], longPieces = [], mixedPieces = [],
+            i, mom;
+        for (i = 0; i < 12; i++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, i]);
+            shortPieces.push(this.monthsShort(mom, ''));
+            longPieces.push(this.months(mom, ''));
+            mixedPieces.push(this.months(mom, ''));
+            mixedPieces.push(this.monthsShort(mom, ''));
+        }
+        // Sorting makes sure if one month (or abbr) is a prefix of another it
+        // will match the longer piece.
+        shortPieces.sort(cmpLenRev);
+        longPieces.sort(cmpLenRev);
+        mixedPieces.sort(cmpLenRev);
+        for (i = 0; i < 12; i++) {
+            shortPieces[i] = regexEscape(shortPieces[i]);
+            longPieces[i] = regexEscape(longPieces[i]);
+            mixedPieces[i] = regexEscape(mixedPieces[i]);
+        }
+
+        this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+        this._monthsShortRegex = this._monthsRegex;
+        this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
+        this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
+    }
+
+    function checkOverflow (m) {
+        var overflow;
+        var a = m._a;
+
+        if (a && getParsingFlags(m).overflow === -2) {
+            overflow =
+                a[MONTH]       < 0 || a[MONTH]       > 11  ? MONTH :
+                a[DATE]        < 1 || a[DATE]        > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
+                a[HOUR]        < 0 || a[HOUR]        > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
+                a[MINUTE]      < 0 || a[MINUTE]      > 59  ? MINUTE :
+                a[SECOND]      < 0 || a[SECOND]      > 59  ? SECOND :
+                a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
+                -1;
+
+            if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
+                overflow = DATE;
+            }
+            if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
+                overflow = WEEK;
+            }
+            if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
+                overflow = WEEKDAY;
+            }
+
+            getParsingFlags(m).overflow = overflow;
+        }
+
+        return m;
+    }
+
+    // iso 8601 regex
+    // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
+    var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
+    var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?/;
+
+    var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
+
+    var isoDates = [
+        ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
+        ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
+        ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
+        ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
+        ['YYYY-DDD', /\d{4}-\d{3}/],
+        ['YYYY-MM', /\d{4}-\d\d/, false],
+        ['YYYYYYMMDD', /[+-]\d{10}/],
+        ['YYYYMMDD', /\d{8}/],
+        // YYYYMM is NOT allowed by the standard
+        ['GGGG[W]WWE', /\d{4}W\d{3}/],
+        ['GGGG[W]WW', /\d{4}W\d{2}/, false],
+        ['YYYYDDD', /\d{7}/]
+    ];
+
+    // iso time formats and regexes
+    var isoTimes = [
+        ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
+        ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
+        ['HH:mm:ss', /\d\d:\d\d:\d\d/],
+        ['HH:mm', /\d\d:\d\d/],
+        ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
+        ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
+        ['HHmmss', /\d\d\d\d\d\d/],
+        ['HHmm', /\d\d\d\d/],
+        ['HH', /\d\d/]
+    ];
+
+    var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
+
+    // date from iso format
+    function configFromISO(config) {
+        var i, l,
+            string = config._i,
+            match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
+            allowTime, dateFormat, timeFormat, tzFormat;
+
+        if (match) {
+            getParsingFlags(config).iso = true;
+
+            for (i = 0, l = isoDates.length; i < l; i++) {
+                if (isoDates[i][1].exec(match[1])) {
+                    dateFormat = isoDates[i][0];
+                    allowTime = isoDates[i][2] !== false;
+                    break;
+                }
+            }
+            if (dateFormat == null) {
+                config._isValid = false;
+                return;
+            }
+            if (match[3]) {
+                for (i = 0, l = isoTimes.length; i < l; i++) {
+                    if (isoTimes[i][1].exec(match[3])) {
+                        // match[2] should be 'T' or space
+                        timeFormat = (match[2] || ' ') + isoTimes[i][0];
+                        break;
+                    }
+                }
+                if (timeFormat == null) {
+                    config._isValid = false;
+                    return;
+                }
+            }
+            if (!allowTime && timeFormat != null) {
+                config._isValid = false;
+                return;
+            }
+            if (match[4]) {
+                if (tzRegex.exec(match[4])) {
+                    tzFormat = 'Z';
+                } else {
+                    config._isValid = false;
+                    return;
+                }
+            }
+            config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
+            configFromStringAndFormat(config);
+        } else {
+            config._isValid = false;
+        }
+    }
+
+    // date from iso format or fallback
+    function configFromString(config) {
+        var matched = aspNetJsonRegex.exec(config._i);
+
+        if (matched !== null) {
+            config._d = new Date(+matched[1]);
+            return;
+        }
+
+        configFromISO(config);
+        if (config._isValid === false) {
+            delete config._isValid;
+            utils_hooks__hooks.createFromInputFallback(config);
+        }
+    }
+
+    utils_hooks__hooks.createFromInputFallback = deprecate(
+        'moment construction falls back to js Date. This is ' +
+        'discouraged and will be removed in upcoming major ' +
+        'release. Please refer to ' +
+        'https://github.com/moment/moment/issues/1407 for more info.',
+        function (config) {
+            config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+        }
+    );
+
+    function createDate (y, m, d, h, M, s, ms) {
+        //can't just apply() to create a date:
+        //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
+        var date = new Date(y, m, d, h, M, s, ms);
+
+        //the date constructor remaps years 0-99 to 1900-1999
+        if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
+            date.setFullYear(y);
+        }
+        return date;
+    }
+
+    function createUTCDate (y) {
+        var date = new Date(Date.UTC.apply(null, arguments));
+
+        //the Date.UTC function remaps years 0-99 to 1900-1999
+        if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
+            date.setUTCFullYear(y);
+        }
+        return date;
+    }
+
+    // FORMATTING
+
+    addFormatToken('Y', 0, 0, function () {
+        var y = this.year();
+        return y <= 9999 ? '' + y : '+' + y;
+    });
+
+    addFormatToken(0, ['YY', 2], 0, function () {
+        return this.year() % 100;
+    });
+
+    addFormatToken(0, ['YYYY',   4],       0, 'year');
+    addFormatToken(0, ['YYYYY',  5],       0, 'year');
+    addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
+
+    // ALIASES
+
+    addUnitAlias('year', 'y');
+
+    // PARSING
+
+    addRegexToken('Y',      matchSigned);
+    addRegexToken('YY',     match1to2, match2);
+    addRegexToken('YYYY',   match1to4, match4);
+    addRegexToken('YYYYY',  match1to6, match6);
+    addRegexToken('YYYYYY', match1to6, match6);
+
+    addParseToken(['YYYYY', 'YYYYYY'], YEAR);
+    addParseToken('YYYY', function (input, array) {
+        array[YEAR] = input.length === 2 ? utils_hooks__hooks.parseTwoDigitYear(input) : toInt(input);
+    });
+    addParseToken('YY', function (input, array) {
+        array[YEAR] = utils_hooks__hooks.parseTwoDigitYear(input);
+    });
+    addParseToken('Y', function (input, array) {
+        array[YEAR] = parseInt(input, 10);
+    });
+
+    // HELPERS
+
+    function daysInYear(year) {
+        return isLeapYear(year) ? 366 : 365;
+    }
+
+    function isLeapYear(year) {
+        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+    }
+
+    // HOOKS
+
+    utils_hooks__hooks.parseTwoDigitYear = function (input) {
+        return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+    };
+
+    // MOMENTS
+
+    var getSetYear = makeGetSet('FullYear', true);
+
+    function getIsLeapYear () {
+        return isLeapYear(this.year());
+    }
+
+    // start-of-first-week - start-of-year
+    function firstWeekOffset(year, dow, doy) {
+        var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
+            fwd = 7 + dow - doy,
+            // first-week day local weekday -- which local weekday is fwd
+            fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
+
+        return -fwdlw + fwd - 1;
+    }
+
+    //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+    function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
+        var localWeekday = (7 + weekday - dow) % 7,
+            weekOffset = firstWeekOffset(year, dow, doy),
+            dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
+            resYear, resDayOfYear;
+
+        if (dayOfYear <= 0) {
+            resYear = year - 1;
+            resDayOfYear = daysInYear(resYear) + dayOfYear;
+        } else if (dayOfYear > daysInYear(year)) {
+            resYear = year + 1;
+            resDayOfYear = dayOfYear - daysInYear(year);
+        } else {
+            resYear = year;
+            resDayOfYear = dayOfYear;
+        }
+
+        return {
+            year: resYear,
+            dayOfYear: resDayOfYear
+        };
+    }
+
+    function weekOfYear(mom, dow, doy) {
+        var weekOffset = firstWeekOffset(mom.year(), dow, doy),
+            week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
+            resWeek, resYear;
+
+        if (week < 1) {
+            resYear = mom.year() - 1;
+            resWeek = week + weeksInYear(resYear, dow, doy);
+        } else if (week > weeksInYear(mom.year(), dow, doy)) {
+            resWeek = week - weeksInYear(mom.year(), dow, doy);
+            resYear = mom.year() + 1;
+        } else {
+            resYear = mom.year();
+            resWeek = week;
+        }
+
+        return {
+            week: resWeek,
+            year: resYear
+        };
+    }
+
+    function weeksInYear(year, dow, doy) {
+        var weekOffset = firstWeekOffset(year, dow, doy),
+            weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
+        return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
+    }
+
+    // Pick the first defined of two or three arguments.
+    function defaults(a, b, c) {
+        if (a != null) {
+            return a;
+        }
+        if (b != null) {
+            return b;
+        }
+        return c;
+    }
+
+    function currentDateArray(config) {
+        // hooks is actually the exported moment object
+        var nowValue = new Date(utils_hooks__hooks.now());
+        if (config._useUTC) {
+            return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
+        }
+        return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
+    }
+
+    // convert an array to a date.
+    // the array should mirror the parameters below
+    // note: all values past the year are optional and will default to the lowest possible value.
+    // [year, month, day , hour, minute, second, millisecond]
+    function configFromArray (config) {
+        var i, date, input = [], currentDate, yearToUse;
+
+        if (config._d) {
+            return;
+        }
+
+        currentDate = currentDateArray(config);
+
+        //compute day of the year from weeks and weekdays
+        if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+            dayOfYearFromWeekInfo(config);
+        }
+
+        //if the day of the year is set, figure out what it is
+        if (config._dayOfYear) {
+            yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
+
+            if (config._dayOfYear > daysInYear(yearToUse)) {
+                getParsingFlags(config)._overflowDayOfYear = true;
+            }
+
+            date = createUTCDate(yearToUse, 0, config._dayOfYear);
+            config._a[MONTH] = date.getUTCMonth();
+            config._a[DATE] = date.getUTCDate();
+        }
+
+        // Default to current date.
+        // * if no year, month, day of month are given, default to today
+        // * if day of month is given, default month and year
+        // * if month is given, default only year
+        // * if year is given, don't default anything
+        for (i = 0; i < 3 && config._a[i] == null; ++i) {
+            config._a[i] = input[i] = currentDate[i];
+        }
+
+        // Zero out whatever was not defaulted, including time
+        for (; i < 7; i++) {
+            config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+        }
+
+        // Check for 24:00:00.000
+        if (config._a[HOUR] === 24 &&
+                config._a[MINUTE] === 0 &&
+                config._a[SECOND] === 0 &&
+                config._a[MILLISECOND] === 0) {
+            config._nextDay = true;
+            config._a[HOUR] = 0;
+        }
+
+        config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
+        // Apply timezone offset from input. The actual utcOffset can be changed
+        // with parseZone.
+        if (config._tzm != null) {
+            config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+        }
+
+        if (config._nextDay) {
+            config._a[HOUR] = 24;
+        }
+    }
+
+    function dayOfYearFromWeekInfo(config) {
+        var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
+
+        w = config._w;
+        if (w.GG != null || w.W != null || w.E != null) {
+            dow = 1;
+            doy = 4;
+
+            // TODO: We need to take the current isoWeekYear, but that depends on
+            // how we interpret now (local, utc, fixed offset). So create
+            // a now version of current config (take local/utc/offset flags, and
+            // create now).
+            weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(local__createLocal(), 1, 4).year);
+            week = defaults(w.W, 1);
+            weekday = defaults(w.E, 1);
+            if (weekday < 1 || weekday > 7) {
+                weekdayOverflow = true;
+            }
+        } else {
+            dow = config._locale._week.dow;
+            doy = config._locale._week.doy;
+
+            weekYear = defaults(w.gg, config._a[YEAR], weekOfYear(local__createLocal(), dow, doy).year);
+            week = defaults(w.w, 1);
+
+            if (w.d != null) {
+                // weekday -- low day numbers are considered next week
+                weekday = w.d;
+                if (weekday < 0 || weekday > 6) {
+                    weekdayOverflow = true;
+                }
+            } else if (w.e != null) {
+                // local weekday -- counting starts from begining of week
+                weekday = w.e + dow;
+                if (w.e < 0 || w.e > 6) {
+                    weekdayOverflow = true;
+                }
+            } else {
+                // default to begining of week
+                weekday = dow;
+            }
+        }
+        if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
+            getParsingFlags(config)._overflowWeeks = true;
+        } else if (weekdayOverflow != null) {
+            getParsingFlags(config)._overflowWeekday = true;
+        } else {
+            temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
+            config._a[YEAR] = temp.year;
+            config._dayOfYear = temp.dayOfYear;
+        }
+    }
+
+    // constant that refers to the ISO standard
+    utils_hooks__hooks.ISO_8601 = function () {};
+
+    // date from string and format string
+    function configFromStringAndFormat(config) {
+        // TODO: Move this to another part of the creation flow to prevent circular deps
+        if (config._f === utils_hooks__hooks.ISO_8601) {
+            configFromISO(config);
+            return;
+        }
+
+        config._a = [];
+        getParsingFlags(config).empty = true;
+
+        // This array is used to make a Date, either with `new Date` or `Date.UTC`
+        var string = '' + config._i,
+            i, parsedInput, tokens, token, skipped,
+            stringLength = string.length,
+            totalParsedInputLength = 0;
+
+        tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
+
+        for (i = 0; i < tokens.length; i++) {
+            token = tokens[i];
+            parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
+            // console.log('token', token, 'parsedInput', parsedInput,
+            //         'regex', getParseRegexForToken(token, config));
+            if (parsedInput) {
+                skipped = string.substr(0, string.indexOf(parsedInput));
+                if (skipped.length > 0) {
+                    getParsingFlags(config).unusedInput.push(skipped);
+                }
+                string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
+                totalParsedInputLength += parsedInput.length;
+            }
+            // don't parse if it's not a known token
+            if (formatTokenFunctions[token]) {
+                if (parsedInput) {
+                    getParsingFlags(config).empty = false;
+                }
+                else {
+                    getParsingFlags(config).unusedTokens.push(token);
+                }
+                addTimeToArrayFromToken(token, parsedInput, config);
+            }
+            else if (config._strict && !parsedInput) {
+                getParsingFlags(config).unusedTokens.push(token);
+            }
+        }
+
+        // add remaining unparsed input length to the string
+        getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
+        if (string.length > 0) {
+            getParsingFlags(config).unusedInput.push(string);
+        }
+
+        // clear _12h flag if hour is <= 12
+        if (getParsingFlags(config).bigHour === true &&
+                config._a[HOUR] <= 12 &&
+                config._a[HOUR] > 0) {
+            getParsingFlags(config).bigHour = undefined;
+        }
+
+        getParsingFlags(config).parsedDateParts = config._a.slice(0);
+        getParsingFlags(config).meridiem = config._meridiem;
+        // handle meridiem
+        config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
+
+        configFromArray(config);
+        checkOverflow(config);
+    }
+
+
+    function meridiemFixWrap (locale, hour, meridiem) {
+        var isPm;
+
+        if (meridiem == null) {
+            // nothing to do
+            return hour;
+        }
+        if (locale.meridiemHour != null) {
+            return locale.meridiemHour(hour, meridiem);
+        } else if (locale.isPM != null) {
+            // Fallback
+            isPm = locale.isPM(meridiem);
+            if (isPm && hour < 12) {
+                hour += 12;
+            }
+            if (!isPm && hour === 12) {
+                hour = 0;
+            }
+            return hour;
+        } else {
+            // this is not supposed to happen
+            return hour;
+        }
+    }
+
+    // date from string and array of format strings
+    function configFromStringAndArray(config) {
+        var tempConfig,
+            bestMoment,
+
+            scoreToBeat,
+            i,
+            currentScore;
+
+        if (config._f.length === 0) {
+            getParsingFlags(config).invalidFormat = true;
+            config._d = new Date(NaN);
+            return;
+        }
+
+        for (i = 0; i < config._f.length; i++) {
+            currentScore = 0;
+            tempConfig = copyConfig({}, config);
+            if (config._useUTC != null) {
+                tempConfig._useUTC = config._useUTC;
+            }
+            tempConfig._f = config._f[i];
+            configFromStringAndFormat(tempConfig);
+
+            if (!valid__isValid(tempConfig)) {
+                continue;
+            }
+
+            // if there is any input that was not parsed add a penalty for that format
+            currentScore += getParsingFlags(tempConfig).charsLeftOver;
+
+            //or tokens
+            currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
+
+            getParsingFlags(tempConfig).score = currentScore;
+
+            if (scoreToBeat == null || currentScore < scoreToBeat) {
+                scoreToBeat = currentScore;
+                bestMoment = tempConfig;
+            }
+        }
+
+        extend(config, bestMoment || tempConfig);
+    }
+
+    function configFromObject(config) {
+        if (config._d) {
+            return;
+        }
+
+        var i = normalizeObjectUnits(config._i);
+        config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
+            return obj && parseInt(obj, 10);
+        });
+
+        configFromArray(config);
+    }
+
+    function createFromConfig (config) {
+        var res = new Moment(checkOverflow(prepareConfig(config)));
+        if (res._nextDay) {
+            // Adding is smart enough around DST
+            res.add(1, 'd');
+            res._nextDay = undefined;
+        }
+
+        return res;
+    }
+
+    function prepareConfig (config) {
+        var input = config._i,
+            format = config._f;
+
+        config._locale = config._locale || locale_locales__getLocale(config._l);
+
+        if (input === null || (format === undefined && input === '')) {
+            return valid__createInvalid({nullInput: true});
+        }
+
+        if (typeof input === 'string') {
+            config._i = input = config._locale.preparse(input);
+        }
+
+        if (isMoment(input)) {
+            return new Moment(checkOverflow(input));
+        } else if (isArray(format)) {
+            configFromStringAndArray(config);
+        } else if (format) {
+            configFromStringAndFormat(config);
+        } else if (isDate(input)) {
+            config._d = input;
+        } else {
+            configFromInput(config);
+        }
+
+        if (!valid__isValid(config)) {
+            config._d = null;
+        }
+
+        return config;
+    }
+
+    function configFromInput(config) {
+        var input = config._i;
+        if (input === undefined) {
+            config._d = new Date(utils_hooks__hooks.now());
+        } else if (isDate(input)) {
+            config._d = new Date(input.valueOf());
+        } else if (typeof input === 'string') {
+            configFromString(config);
+        } else if (isArray(input)) {
+            config._a = map(input.slice(0), function (obj) {
+                return parseInt(obj, 10);
+            });
+            configFromArray(config);
+        } else if (typeof(input) === 'object') {
+            configFromObject(config);
+        } else if (typeof(input) === 'number') {
+            // from milliseconds
+            config._d = new Date(input);
+        } else {
+            utils_hooks__hooks.createFromInputFallback(config);
+        }
+    }
+
+    function createLocalOrUTC (input, format, locale, strict, isUTC) {
+        var c = {};
+
+        if (typeof(locale) === 'boolean') {
+            strict = locale;
+            locale = undefined;
+        }
+        // object construction must be done this way.
+        // https://github.com/moment/moment/issues/1423
+        c._isAMomentObject = true;
+        c._useUTC = c._isUTC = isUTC;
+        c._l = locale;
+        c._i = input;
+        c._f = format;
+        c._strict = strict;
+
+        return createFromConfig(c);
+    }
+
+    function local__createLocal (input, format, locale, strict) {
+        return createLocalOrUTC(input, format, locale, strict, false);
+    }
+
+    var prototypeMin = deprecate(
+         'moment().min is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
+         function () {
+             var other = local__createLocal.apply(null, arguments);
+             if (this.isValid() && other.isValid()) {
+                 return other < this ? this : other;
+             } else {
+                 return valid__createInvalid();
+             }
+         }
+     );
+
+    var prototypeMax = deprecate(
+        'moment().max is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
+        function () {
+            var other = local__createLocal.apply(null, arguments);
+            if (this.isValid() && other.isValid()) {
+                return other > this ? this : other;
+            } else {
+                return valid__createInvalid();
+            }
+        }
+    );
+
+    // Pick a moment m from moments so that m[fn](other) is true for all
+    // other. This relies on the function fn to be transitive.
+    //
+    // moments should either be an array of moment objects or an array, whose
+    // first element is an array of moment objects.
+    function pickBy(fn, moments) {
+        var res, i;
+        if (moments.length === 1 && isArray(moments[0])) {
+            moments = moments[0];
+        }
+        if (!moments.length) {
+            return local__createLocal();
+        }
+        res = moments[0];
+        for (i = 1; i < moments.length; ++i) {
+            if (!moments[i].isValid() || moments[i][fn](res)) {
+                res = moments[i];
+            }
+        }
+        return res;
+    }
+
+    // TODO: Use [].sort instead?
+    function min () {
+        var args = [].slice.call(arguments, 0);
+
+        return pickBy('isBefore', args);
+    }
+
+    function max () {
+        var args = [].slice.call(arguments, 0);
+
+        return pickBy('isAfter', args);
+    }
+
+    var now = function () {
+        return Date.now ? Date.now() : +(new Date());
+    };
+
+    function Duration (duration) {
+        var normalizedInput = normalizeObjectUnits(duration),
+            years = normalizedInput.year || 0,
+            quarters = normalizedInput.quarter || 0,
+            months = normalizedInput.month || 0,
+            weeks = normalizedInput.week || 0,
+            days = normalizedInput.day || 0,
+            hours = normalizedInput.hour || 0,
+            minutes = normalizedInput.minute || 0,
+            seconds = normalizedInput.second || 0,
+            milliseconds = normalizedInput.millisecond || 0;
+
+        // representation for dateAddRemove
+        this._milliseconds = +milliseconds +
+            seconds * 1e3 + // 1000
+            minutes * 6e4 + // 1000 * 60
+            hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
+        // Because of dateAddRemove treats 24 hours as different from a
+        // day when working around DST, we need to store them separately
+        this._days = +days +
+            weeks * 7;
+        // It is impossible translate months into days without knowing
+        // which months you are are talking about, so we have to store
+        // it separately.
+        this._months = +months +
+            quarters * 3 +
+            years * 12;
+
+        this._data = {};
+
+        this._locale = locale_locales__getLocale();
+
+        this._bubble();
+    }
+
+    function isDuration (obj) {
+        return obj instanceof Duration;
+    }
+
+    // FORMATTING
+
+    function offset (token, separator) {
+        addFormatToken(token, 0, 0, function () {
+            var offset = this.utcOffset();
+            var sign = '+';
+            if (offset < 0) {
+                offset = -offset;
+                sign = '-';
+            }
+            return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
+        });
+    }
+
+    offset('Z', ':');
+    offset('ZZ', '');
+
+    // PARSING
+
+    addRegexToken('Z',  matchShortOffset);
+    addRegexToken('ZZ', matchShortOffset);
+    addParseToken(['Z', 'ZZ'], function (input, array, config) {
+        config._useUTC = true;
+        config._tzm = offsetFromString(matchShortOffset, input);
+    });
+
+    // HELPERS
+
+    // timezone chunker
+    // '+10:00' > ['10',  '00']
+    // '-1530'  > ['-15', '30']
+    var chunkOffset = /([\+\-]|\d\d)/gi;
+
+    function offsetFromString(matcher, string) {
+        var matches = ((string || '').match(matcher) || []);
+        var chunk   = matches[matches.length - 1] || [];
+        var parts   = (chunk + '').match(chunkOffset) || ['-', 0, 0];
+        var minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+        return parts[0] === '+' ? minutes : -minutes;
+    }
+
+    // Return a moment from input, that is local/utc/zone equivalent to model.
+    function cloneWithOffset(input, model) {
+        var res, diff;
+        if (model._isUTC) {
+            res = model.clone();
+            diff = (isMoment(input) || isDate(input) ? input.valueOf() : local__createLocal(input).valueOf()) - res.valueOf();
+            // Use low-level api, because this fn is low-level api.
+            res._d.setTime(res._d.valueOf() + diff);
+            utils_hooks__hooks.updateOffset(res, false);
+            return res;
+        } else {
+            return local__createLocal(input).local();
+        }
+    }
+
+    function getDateOffset (m) {
+        // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+        // https://github.com/moment/moment/pull/1871
+        return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
+    }
+
+    // HOOKS
+
+    // This function will be called whenever a moment is mutated.
+    // It is intended to keep the offset in sync with the timezone.
+    utils_hooks__hooks.updateOffset = function () {};
+
+    // MOMENTS
+
+    // keepLocalTime = true means only change the timezone, without
+    // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
+    // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
+    // +0200, so we adjust the time as needed, to be valid.
+    //
+    // Keeping the time actually adds/subtracts (one hour)
+    // from the actual represented time. That is why we call updateOffset
+    // a second time. In case it wants us to change the offset again
+    // _changeInProgress == true case, then we have to adjust, because
+    // there is no such time in the given timezone.
+    function getSetOffset (input, keepLocalTime) {
+        var offset = this._offset || 0,
+            localAdjust;
+        if (!this.isValid()) {
+            return input != null ? this : NaN;
+        }
+        if (input != null) {
+            if (typeof input === 'string') {
+                input = offsetFromString(matchShortOffset, input);
+            } else if (Math.abs(input) < 16) {
+                input = input * 60;
+            }
+            if (!this._isUTC && keepLocalTime) {
+                localAdjust = getDateOffset(this);
+            }
+            this._offset = input;
+            this._isUTC = true;
+            if (localAdjust != null) {
+                this.add(localAdjust, 'm');
+            }
+            if (offset !== input) {
+                if (!keepLocalTime || this._changeInProgress) {
+                    add_subtract__addSubtract(this, create__createDuration(input - offset, 'm'), 1, false);
+                } else if (!this._changeInProgress) {
+                    this._changeInProgress = true;
+                    utils_hooks__hooks.updateOffset(this, true);
+                    this._changeInProgress = null;
+                }
+            }
+            return this;
+        } else {
+            return this._isUTC ? offset : getDateOffset(this);
+        }
+    }
+
+    function getSetZone (input, keepLocalTime) {
+        if (input != null) {
+            if (typeof input !== 'string') {
+                input = -input;
+            }
+
+            this.utcOffset(input, keepLocalTime);
+
+            return this;
+        } else {
+            return -this.utcOffset();
+        }
+    }
+
+    function setOffsetToUTC (keepLocalTime) {
+        return this.utcOffset(0, keepLocalTime);
+    }
+
+    function setOffsetToLocal (keepLocalTime) {
+        if (this._isUTC) {
+            this.utcOffset(0, keepLocalTime);
+            this._isUTC = false;
+
+            if (keepLocalTime) {
+                this.subtract(getDateOffset(this), 'm');
+            }
+        }
+        return this;
+    }
+
+    function setOffsetToParsedOffset () {
+        if (this._tzm) {
+            this.utcOffset(this._tzm);
+        } else if (typeof this._i === 'string') {
+            this.utcOffset(offsetFromString(matchOffset, this._i));
+        }
+        return this;
+    }
+
+    function hasAlignedHourOffset (input) {
+        if (!this.isValid()) {
+            return false;
+        }
+        input = input ? local__createLocal(input).utcOffset() : 0;
+
+        return (this.utcOffset() - input) % 60 === 0;
+    }
+
+    function isDaylightSavingTime () {
+        return (
+            this.utcOffset() > this.clone().month(0).utcOffset() ||
+            this.utcOffset() > this.clone().month(5).utcOffset()
+        );
+    }
+
+    function isDaylightSavingTimeShifted () {
+        if (!isUndefined(this._isDSTShifted)) {
+            return this._isDSTShifted;
+        }
+
+        var c = {};
+
+        copyConfig(c, this);
+        c = prepareConfig(c);
+
+        if (c._a) {
+            var other = c._isUTC ? create_utc__createUTC(c._a) : local__createLocal(c._a);
+            this._isDSTShifted = this.isValid() &&
+                compareArrays(c._a, other.toArray()) > 0;
+        } else {
+            this._isDSTShifted = false;
+        }
+
+        return this._isDSTShifted;
+    }
+
+    function isLocal () {
+        return this.isValid() ? !this._isUTC : false;
+    }
+
+    function isUtcOffset () {
+        return this.isValid() ? this._isUTC : false;
+    }
+
+    function isUtc () {
+        return this.isValid() ? this._isUTC && this._offset === 0 : false;
+    }
+
+    // ASP.NET json date format regex
+    var aspNetRegex = /^(\-)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?\d*)?$/;
+
+    // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+    // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+    // and further modified to allow for strings containing both week and day
+    var isoRegex = /^(-)?P(?:(-?[0-9,.]*)Y)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)W)?(?:(-?[0-9,.]*)D)?(?:T(?:(-?[0-9,.]*)H)?(?:(-?[0-9,.]*)M)?(?:(-?[0-9,.]*)S)?)?$/;
+
+    function create__createDuration (input, key) {
+        var duration = input,
+            // matching against regexp is expensive, do it on demand
+            match = null,
+            sign,
+            ret,
+            diffRes;
+
+        if (isDuration(input)) {
+            duration = {
+                ms : input._milliseconds,
+                d  : input._days,
+                M  : input._months
+            };
+        } else if (typeof input === 'number') {
+            duration = {};
+            if (key) {
+                duration[key] = input;
+            } else {
+                duration.milliseconds = input;
+            }
+        } else if (!!(match = aspNetRegex.exec(input))) {
+            sign = (match[1] === '-') ? -1 : 1;
+            duration = {
+                y  : 0,
+                d  : toInt(match[DATE])        * sign,
+                h  : toInt(match[HOUR])        * sign,
+                m  : toInt(match[MINUTE])      * sign,
+                s  : toInt(match[SECOND])      * sign,
+                ms : toInt(match[MILLISECOND]) * sign
+            };
+        } else if (!!(match = isoRegex.exec(input))) {
+            sign = (match[1] === '-') ? -1 : 1;
+            duration = {
+                y : parseIso(match[2], sign),
+                M : parseIso(match[3], sign),
+                w : parseIso(match[4], sign),
+                d : parseIso(match[5], sign),
+                h : parseIso(match[6], sign),
+                m : parseIso(match[7], sign),
+                s : parseIso(match[8], sign)
+            };
+        } else if (duration == null) {// checks for null or undefined
+            duration = {};
+        } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
+            diffRes = momentsDifference(local__createLocal(duration.from), local__createLocal(duration.to));
+
+            duration = {};
+            duration.ms = diffRes.milliseconds;
+            duration.M = diffRes.months;
+        }
+
+        ret = new Duration(duration);
+
+        if (isDuration(input) && hasOwnProp(input, '_locale')) {
+            ret._locale = input._locale;
+        }
+
+        return ret;
+    }
+
+    create__createDuration.fn = Duration.prototype;
+
+    function parseIso (inp, sign) {
+        // We'd normally use ~~inp for this, but unfortunately it also
+        // converts floats to ints.
+        // inp may be undefined, so careful calling replace on it.
+        var res = inp && parseFloat(inp.replace(',', '.'));
+        // apply sign while we're at it
+        return (isNaN(res) ? 0 : res) * sign;
+    }
+
+    function positiveMomentsDifference(base, other) {
+        var res = {milliseconds: 0, months: 0};
+
+        res.months = other.month() - base.month() +
+            (other.year() - base.year()) * 12;
+        if (base.clone().add(res.months, 'M').isAfter(other)) {
+            --res.months;
+        }
+
+        res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
+
+        return res;
+    }
+
+    function momentsDifference(base, other) {
+        var res;
+        if (!(base.isValid() && other.isValid())) {
+            return {milliseconds: 0, months: 0};
+        }
+
+        other = cloneWithOffset(other, base);
+        if (base.isBefore(other)) {
+            res = positiveMomentsDifference(base, other);
+        } else {
+            res = positiveMomentsDifference(other, base);
+            res.milliseconds = -res.milliseconds;
+            res.months = -res.months;
+        }
+
+        return res;
+    }
+
+    function absRound (number) {
+        if (number < 0) {
+            return Math.round(-1 * number) * -1;
+        } else {
+            return Math.round(number);
+        }
+    }
+
+    // TODO: remove 'name' arg after deprecation is removed
+    function createAdder(direction, name) {
+        return function (val, period) {
+            var dur, tmp;
+            //invert the arguments, but complain about it
+            if (period !== null && !isNaN(+period)) {
+                deprecateSimple(name, 'moment().' + name  + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
+                tmp = val; val = period; period = tmp;
+            }
+
+            val = typeof val === 'string' ? +val : val;
+            dur = create__createDuration(val, period);
+            add_subtract__addSubtract(this, dur, direction);
+            return this;
+        };
+    }
+
+    function add_subtract__addSubtract (mom, duration, isAdding, updateOffset) {
+        var milliseconds = duration._milliseconds,
+            days = absRound(duration._days),
+            months = absRound(duration._months);
+
+        if (!mom.isValid()) {
+            // No op
+            return;
+        }
+
+        updateOffset = updateOffset == null ? true : updateOffset;
+
+        if (milliseconds) {
+            mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+        }
+        if (days) {
+            get_set__set(mom, 'Date', get_set__get(mom, 'Date') + days * isAdding);
+        }
+        if (months) {
+            setMonth(mom, get_set__get(mom, 'Month') + months * isAdding);
+        }
+        if (updateOffset) {
+            utils_hooks__hooks.updateOffset(mom, days || months);
+        }
+    }
+
+    var add_subtract__add      = createAdder(1, 'add');
+    var add_subtract__subtract = createAdder(-1, 'subtract');
+
+    function moment_calendar__calendar (time, formats) {
+        // We want to compare the start of today, vs this.
+        // Getting start-of-today depends on whether we're local/utc/offset or not.
+        var now = time || local__createLocal(),
+            sod = cloneWithOffset(now, this).startOf('day'),
+            diff = this.diff(sod, 'days', true),
+            format = diff < -6 ? 'sameElse' :
+                diff < -1 ? 'lastWeek' :
+                diff < 0 ? 'lastDay' :
+                diff < 1 ? 'sameDay' :
+                diff < 2 ? 'nextDay' :
+                diff < 7 ? 'nextWeek' : 'sameElse';
+
+        var output = formats && (isFunction(formats[format]) ? formats[format]() : formats[format]);
+
+        return this.format(output || this.localeData().calendar(format, this, local__createLocal(now)));
+    }
+
+    function clone () {
+        return new Moment(this);
+    }
+
+    function isAfter (input, units) {
+        var localInput = isMoment(input) ? input : local__createLocal(input);
+        if (!(this.isValid() && localInput.isValid())) {
+            return false;
+        }
+        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
+        if (units === 'millisecond') {
+            return this.valueOf() > localInput.valueOf();
+        } else {
+            return localInput.valueOf() < this.clone().startOf(units).valueOf();
+        }
+    }
+
+    function isBefore (input, units) {
+        var localInput = isMoment(input) ? input : local__createLocal(input);
+        if (!(this.isValid() && localInput.isValid())) {
+            return false;
+        }
+        units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
+        if (units === 'millisecond') {
+            return this.valueOf() < localInput.valueOf();
+        } else {
+            return this.clone().endOf(units).valueOf() < localInput.valueOf();
+        }
+    }
+
+    function isBetween (from, to, units, inclusivity) {
+        inclusivity = inclusivity || '()';
+        return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
+            (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
+    }
+
+    function isSame (input, units) {
+        var localInput = isMoment(input) ? input : local__createLocal(input),
+            inputMs;
+        if (!(this.isValid() && localInput.isValid())) {
+            return false;
+        }
+        units = normalizeUnits(units || 'millisecond');
+        if (units === 'millisecond') {
+            return this.valueOf() === localInput.valueOf();
+        } else {
+            inputMs = localInput.valueOf();
+            return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
+        }
+    }
+
+    function isSameOrAfter (input, units) {
+        return this.isSame(input, units) || this.isAfter(input,units);
+    }
+
+    function isSameOrBefore (input, units) {
+        return this.isSame(input, units) || this.isBefore(input,units);
+    }
+
+    function diff (input, units, asFloat) {
+        var that,
+            zoneDelta,
+            delta, output;
+
+        if (!this.isValid()) {
+            return NaN;
+        }
+
+        that = cloneWithOffset(input, this);
+
+        if (!that.isValid()) {
+            return NaN;
+        }
+
+        zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
+
+        units = normalizeUnits(units);
+
+        if (units === 'year' || units === 'month' || units === 'quarter') {
+            output = monthDiff(this, that);
+            if (units === 'quarter') {
+                output = output / 3;
+            } else if (units === 'year') {
+                output = output / 12;
+            }
+        } else {
+            delta = this - that;
+            output = units === 'second' ? delta / 1e3 : // 1000
+                units === 'minute' ? delta / 6e4 : // 1000 * 60
+                units === 'hour' ? delta / 36e5 : // 1000 * 60 * 60
+                units === 'day' ? (delta - zoneDelta) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
+                units === 'week' ? (delta - zoneDelta) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
+                delta;
+        }
+        return asFloat ? output : absFloor(output);
+    }
+
+    function monthDiff (a, b) {
+        // difference in months
+        var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
+            // b is in (anchor - 1 month, anchor + 1 month)
+            anchor = a.clone().add(wholeMonthDiff, 'months'),
+            anchor2, adjust;
+
+        if (b - anchor < 0) {
+            anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
+            // linear across the month
+            adjust = (b - anchor) / (anchor - anchor2);
+        } else {
+            anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
+            // linear across the month
+            adjust = (b - anchor) / (anchor2 - anchor);
+        }
+
+        //check for negative zero, return zero if negative zero
+        return -(wholeMonthDiff + adjust) || 0;
+    }
+
+    utils_hooks__hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
+    utils_hooks__hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
+
+    function toString () {
+        return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
+    }
+
+    function moment_format__toISOString () {
+        var m = this.clone().utc();
+        if (0 < m.year() && m.year() <= 9999) {
+            if (isFunction(Date.prototype.toISOString)) {
+                // native implementation is ~50x faster, use it when we can
+                return this.toDate().toISOString();
+            } else {
+                return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+            }
+        } else {
+            return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+        }
+    }
+
+    function moment_format__format (inputString) {
+        if (!inputString) {
+            inputString = this.isUtc() ? utils_hooks__hooks.defaultFormatUtc : utils_hooks__hooks.defaultFormat;
+        }
+        var output = formatMoment(this, inputString);
+        return this.localeData().postformat(output);
+    }
+
+    function from (time, withoutSuffix) {
+        if (this.isValid() &&
+                ((isMoment(time) && time.isValid()) ||
+                 local__createLocal(time).isValid())) {
+            return create__createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
+        } else {
+            return this.localeData().invalidDate();
+        }
+    }
+
+    function fromNow (withoutSuffix) {
+        return this.from(local__createLocal(), withoutSuffix);
+    }
+
+    function to (time, withoutSuffix) {
+        if (this.isValid() &&
+                ((isMoment(time) && time.isValid()) ||
+                 local__createLocal(time).isValid())) {
+            return create__createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
+        } else {
+            return this.localeData().invalidDate();
+        }
+    }
+
+    function toNow (withoutSuffix) {
+        return this.to(local__createLocal(), withoutSuffix);
+    }
+
+    // If passed a locale key, it will set the locale for this
+    // instance.  Otherwise, it will return the locale configuration
+    // variables for this instance.
+    function locale (key) {
+        var newLocaleData;
+
+        if (key === undefined) {
+            return this._locale._abbr;
+        } else {
+            newLocaleData = locale_locales__getLocale(key);
+            if (newLocaleData != null) {
+                this._locale = newLocaleData;
+            }
+            return this;
+        }
+    }
+
+    var lang = deprecate(
+        'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
+        function (key) {
+            if (key === undefined) {
+                return this.localeData();
+            } else {
+                return this.locale(key);
+            }
+        }
+    );
+
+    function localeData () {
+        return this._locale;
+    }
+
+    function startOf (units) {
+        units = normalizeUnits(units);
+        // the following switch intentionally omits break keywords
+        // to utilize falling through the cases.
+        switch (units) {
+        case 'year':
+            this.month(0);
+            /* falls through */
+        case 'quarter':
+        case 'month':
+            this.date(1);
+            /* falls through */
+        case 'week':
+        case 'isoWeek':
+        case 'day':
+        case 'date':
+            this.hours(0);
+            /* falls through */
+        case 'hour':
+            this.minutes(0);
+            /* falls through */
+        case 'minute':
+            this.seconds(0);
+            /* falls through */
+        case 'second':
+            this.milliseconds(0);
+        }
+
+        // weeks are a special case
+        if (units === 'week') {
+            this.weekday(0);
+        }
+        if (units === 'isoWeek') {
+            this.isoWeekday(1);
+        }
+
+        // quarters are also special
+        if (units === 'quarter') {
+            this.month(Math.floor(this.month() / 3) * 3);
+        }
+
+        return this;
+    }
+
+    function endOf (units) {
+        units = normalizeUnits(units);
+        if (units === undefined || units === 'millisecond') {
+            return this;
+        }
+
+        // 'date' is an alias for 'day', so it should be considered as such.
+        if (units === 'date') {
+            units = 'day';
+        }
+
+        return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
+    }
+
+    function to_type__valueOf () {
+        return this._d.valueOf() - ((this._offset || 0) * 60000);
+    }
+
+    function unix () {
+        return Math.floor(this.valueOf() / 1000);
+    }
+
+    function toDate () {
+        return this._offset ? new Date(this.valueOf()) : this._d;
+    }
+
+    function toArray () {
+        var m = this;
+        return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
+    }
+
+    function toObject () {
+        var m = this;
+        return {
+            years: m.year(),
+            months: m.month(),
+            date: m.date(),
+            hours: m.hours(),
+            minutes: m.minutes(),
+            seconds: m.seconds(),
+            milliseconds: m.milliseconds()
+        };
+    }
+
+    function toJSON () {
+        // new Date(NaN).toJSON() === null
+        return this.isValid() ? this.toISOString() : null;
+    }
+
+    function moment_valid__isValid () {
+        return valid__isValid(this);
+    }
+
+    function parsingFlags () {
+        return extend({}, getParsingFlags(this));
+    }
+
+    function invalidAt () {
+        return getParsingFlags(this).overflow;
+    }
+
+    function creationData() {
+        return {
+            input: this._i,
+            format: this._f,
+            locale: this._locale,
+            isUTC: this._isUTC,
+            strict: this._strict
+        };
+    }
+
+    // FORMATTING
+
+    addFormatToken(0, ['gg', 2], 0, function () {
+        return this.weekYear() % 100;
+    });
+
+    addFormatToken(0, ['GG', 2], 0, function () {
+        return this.isoWeekYear() % 100;
+    });
+
+    function addWeekYearFormatToken (token, getter) {
+        addFormatToken(0, [token, token.length], 0, getter);
+    }
+
+    addWeekYearFormatToken('gggg',     'weekYear');
+    addWeekYearFormatToken('ggggg',    'weekYear');
+    addWeekYearFormatToken('GGGG',  'isoWeekYear');
+    addWeekYearFormatToken('GGGGG', 'isoWeekYear');
+
+    // ALIASES
+
+    addUnitAlias('weekYear', 'gg');
+    addUnitAlias('isoWeekYear', 'GG');
+
+    // PARSING
+
+    addRegexToken('G',      matchSigned);
+    addRegexToken('g',      matchSigned);
+    addRegexToken('GG',     match1to2, match2);
+    addRegexToken('gg',     match1to2, match2);
+    addRegexToken('GGGG',   match1to4, match4);
+    addRegexToken('gggg',   match1to4, match4);
+    addRegexToken('GGGGG',  match1to6, match6);
+    addRegexToken('ggggg',  match1to6, match6);
+
+    addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
+        week[token.substr(0, 2)] = toInt(input);
+    });
+
+    addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
+        week[token] = utils_hooks__hooks.parseTwoDigitYear(input);
+    });
+
+    // MOMENTS
+
+    function getSetWeekYear (input) {
+        return getSetWeekYearHelper.call(this,
+                input,
+                this.week(),
+                this.weekday(),
+                this.localeData()._week.dow,
+                this.localeData()._week.doy);
+    }
+
+    function getSetISOWeekYear (input) {
+        return getSetWeekYearHelper.call(this,
+                input, this.isoWeek(), this.isoWeekday(), 1, 4);
+    }
+
+    function getISOWeeksInYear () {
+        return weeksInYear(this.year(), 1, 4);
+    }
+
+    function getWeeksInYear () {
+        var weekInfo = this.localeData()._week;
+        return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
+    }
+
+    function getSetWeekYearHelper(input, week, weekday, dow, doy) {
+        var weeksTarget;
+        if (input == null) {
+            return weekOfYear(this, dow, doy).year;
+        } else {
+            weeksTarget = weeksInYear(input, dow, doy);
+            if (week > weeksTarget) {
+                week = weeksTarget;
+            }
+            return setWeekAll.call(this, input, week, weekday, dow, doy);
+        }
+    }
+
+    function setWeekAll(weekYear, week, weekday, dow, doy) {
+        var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
+            date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
+
+        this.year(date.getUTCFullYear());
+        this.month(date.getUTCMonth());
+        this.date(date.getUTCDate());
+        return this;
+    }
+
+    // FORMATTING
+
+    addFormatToken('Q', 0, 'Qo', 'quarter');
+
+    // ALIASES
+
+    addUnitAlias('quarter', 'Q');
+
+    // PARSING
+
+    addRegexToken('Q', match1);
+    addParseToken('Q', function (input, array) {
+        array[MONTH] = (toInt(input) - 1) * 3;
+    });
+
+    // MOMENTS
+
+    function getSetQuarter (input) {
+        return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
+    }
+
+    // FORMATTING
+
+    addFormatToken('w', ['ww', 2], 'wo', 'week');
+    addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
+
+    // ALIASES
+
+    addUnitAlias('week', 'w');
+    addUnitAlias('isoWeek', 'W');
+
+    // PARSING
+
+    addRegexToken('w',  match1to2);
+    addRegexToken('ww', match1to2, match2);
+    addRegexToken('W',  match1to2);
+    addRegexToken('WW', match1to2, match2);
+
+    addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
+        week[token.substr(0, 1)] = toInt(input);
+    });
+
+    // HELPERS
+
+    // LOCALES
+
+    function localeWeek (mom) {
+        return weekOfYear(mom, this._week.dow, this._week.doy).week;
+    }
+
+    var defaultLocaleWeek = {
+        dow : 0, // Sunday is the first day of the week.
+        doy : 6  // The week that contains Jan 1st is the first week of the year.
+    };
+
+    function localeFirstDayOfWeek () {
+        return this._week.dow;
+    }
+
+    function localeFirstDayOfYear () {
+        return this._week.doy;
+    }
+
+    // MOMENTS
+
+    function getSetWeek (input) {
+        var week = this.localeData().week(this);
+        return input == null ? week : this.add((input - week) * 7, 'd');
+    }
+
+    function getSetISOWeek (input) {
+        var week = weekOfYear(this, 1, 4).week;
+        return input == null ? week : this.add((input - week) * 7, 'd');
+    }
+
+    // FORMATTING
+
+    addFormatToken('D', ['DD', 2], 'Do', 'date');
+
+    // ALIASES
+
+    addUnitAlias('date', 'D');
+
+    // PARSING
+
+    addRegexToken('D',  match1to2);
+    addRegexToken('DD', match1to2, match2);
+    addRegexToken('Do', function (isStrict, locale) {
+        return isStrict ? locale._ordinalParse : locale._ordinalParseLenient;
+    });
+
+    addParseToken(['D', 'DD'], DATE);
+    addParseToken('Do', function (input, array) {
+        array[DATE] = toInt(input.match(match1to2)[0], 10);
+    });
+
+    // MOMENTS
+
+    var getSetDayOfMonth = makeGetSet('Date', true);
+
+    // FORMATTING
+
+    addFormatToken('d', 0, 'do', 'day');
+
+    addFormatToken('dd', 0, 0, function (format) {
+        return this.localeData().weekdaysMin(this, format);
+    });
+
+    addFormatToken('ddd', 0, 0, function (format) {
+        return this.localeData().weekdaysShort(this, format);
+    });
+
+    addFormatToken('dddd', 0, 0, function (format) {
+        return this.localeData().weekdays(this, format);
+    });
+
+    addFormatToken('e', 0, 0, 'weekday');
+    addFormatToken('E', 0, 0, 'isoWeekday');
+
+    // ALIASES
+
+    addUnitAlias('day', 'd');
+    addUnitAlias('weekday', 'e');
+    addUnitAlias('isoWeekday', 'E');
+
+    // PARSING
+
+    addRegexToken('d',    match1to2);
+    addRegexToken('e',    match1to2);
+    addRegexToken('E',    match1to2);
+    addRegexToken('dd',   function (isStrict, locale) {
+        return locale.weekdaysMinRegex(isStrict);
+    });
+    addRegexToken('ddd',   function (isStrict, locale) {
+        return locale.weekdaysShortRegex(isStrict);
+    });
+    addRegexToken('dddd',   function (isStrict, locale) {
+        return locale.weekdaysRegex(isStrict);
+    });
+
+    addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
+        var weekday = config._locale.weekdaysParse(input, token, config._strict);
+        // if we didn't get a weekday name, mark the date as invalid
+        if (weekday != null) {
+            week.d = weekday;
+        } else {
+            getParsingFlags(config).invalidWeekday = input;
+        }
+    });
+
+    addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
+        week[token] = toInt(input);
+    });
+
+    // HELPERS
+
+    function parseWeekday(input, locale) {
+        if (typeof input !== 'string') {
+            return input;
+        }
+
+        if (!isNaN(input)) {
+            return parseInt(input, 10);
+        }
+
+        input = locale.weekdaysParse(input);
+        if (typeof input === 'number') {
+            return input;
+        }
+
+        return null;
+    }
+
+    // LOCALES
+
+    var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
+    function localeWeekdays (m, format) {
+        return isArray(this._weekdays) ? this._weekdays[m.day()] :
+            this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
+    }
+
+    var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
+    function localeWeekdaysShort (m) {
+        return this._weekdaysShort[m.day()];
+    }
+
+    var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
+    function localeWeekdaysMin (m) {
+        return this._weekdaysMin[m.day()];
+    }
+
+    function day_of_week__handleStrictParse(weekdayName, format, strict) {
+        var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
+        if (!this._weekdaysParse) {
+            this._weekdaysParse = [];
+            this._shortWeekdaysParse = [];
+            this._minWeekdaysParse = [];
+
+            for (i = 0; i < 7; ++i) {
+                mom = create_utc__createUTC([2000, 1]).day(i);
+                this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
+                this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
+                this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
+            }
+        }
+
+        if (strict) {
+            if (format === 'dddd') {
+                ii = indexOf.call(this._weekdaysParse, llc);
+                return ii !== -1 ? ii : null;
+            } else if (format === 'ddd') {
+                ii = indexOf.call(this._shortWeekdaysParse, llc);
+                return ii !== -1 ? ii : null;
+            } else {
+                ii = indexOf.call(this._minWeekdaysParse, llc);
+                return ii !== -1 ? ii : null;
+            }
+        } else {
+            if (format === 'dddd') {
+                ii = indexOf.call(this._weekdaysParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._shortWeekdaysParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._minWeekdaysParse, llc);
+                return ii !== -1 ? ii : null;
+            } else if (format === 'ddd') {
+                ii = indexOf.call(this._shortWeekdaysParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._weekdaysParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._minWeekdaysParse, llc);
+                return ii !== -1 ? ii : null;
+            } else {
+                ii = indexOf.call(this._minWeekdaysParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._weekdaysParse, llc);
+                if (ii !== -1) {
+                    return ii;
+                }
+                ii = indexOf.call(this._shortWeekdaysParse, llc);
+                return ii !== -1 ? ii : null;
+            }
+        }
+    }
+
+    function localeWeekdaysParse (weekdayName, format, strict) {
+        var i, mom, regex;
+
+        if (this._weekdaysParseExact) {
+            return day_of_week__handleStrictParse.call(this, weekdayName, format, strict);
+        }
+
+        if (!this._weekdaysParse) {
+            this._weekdaysParse = [];
+            this._minWeekdaysParse = [];
+            this._shortWeekdaysParse = [];
+            this._fullWeekdaysParse = [];
+        }
+
+        for (i = 0; i < 7; i++) {
+            // make the regex if we don't have it already
+
+            mom = create_utc__createUTC([2000, 1]).day(i);
+            if (strict && !this._fullWeekdaysParse[i]) {
+                this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
+                this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
+                this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
+            }
+            if (!this._weekdaysParse[i]) {
+                regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
+                this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
+            }
+            // test the regex
+            if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
+                return i;
+            } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
+                return i;
+            } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
+                return i;
+            } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
+                return i;
+            }
+        }
+    }
+
+    // MOMENTS
+
+    function getSetDayOfWeek (input) {
+        if (!this.isValid()) {
+            return input != null ? this : NaN;
+        }
+        var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+        if (input != null) {
+            input = parseWeekday(input, this.localeData());
+            return this.add(input - day, 'd');
+        } else {
+            return day;
+        }
+    }
+
+    function getSetLocaleDayOfWeek (input) {
+        if (!this.isValid()) {
+            return input != null ? this : NaN;
+        }
+        var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
+        return input == null ? weekday : this.add(input - weekday, 'd');
+    }
+
+    function getSetISODayOfWeek (input) {
+        if (!this.isValid()) {
+            return input != null ? this : NaN;
+        }
+        // behaves the same as moment#day except
+        // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
+        // as a setter, sunday should belong to the previous week.
+        return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
+    }
+
+    var defaultWeekdaysRegex = matchWord;
+    function weekdaysRegex (isStrict) {
+        if (this._weekdaysParseExact) {
+            if (!hasOwnProp(this, '_weekdaysRegex')) {
+                computeWeekdaysParse.call(this);
+            }
+            if (isStrict) {
+                return this._weekdaysStrictRegex;
+            } else {
+                return this._weekdaysRegex;
+            }
+        } else {
+            return this._weekdaysStrictRegex && isStrict ?
+                this._weekdaysStrictRegex : this._weekdaysRegex;
+        }
+    }
+
+    var defaultWeekdaysShortRegex = matchWord;
+    function weekdaysShortRegex (isStrict) {
+        if (this._weekdaysParseExact) {
+            if (!hasOwnProp(this, '_weekdaysRegex')) {
+                computeWeekdaysParse.call(this);
+            }
+            if (isStrict) {
+                return this._weekdaysShortStrictRegex;
+            } else {
+                return this._weekdaysShortRegex;
+            }
+        } else {
+            return this._weekdaysShortStrictRegex && isStrict ?
+                this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
+        }
+    }
+
+    var defaultWeekdaysMinRegex = matchWord;
+    function weekdaysMinRegex (isStrict) {
+        if (this._weekdaysParseExact) {
+            if (!hasOwnProp(this, '_weekdaysRegex')) {
+                computeWeekdaysParse.call(this);
+            }
+            if (isStrict) {
+                return this._weekdaysMinStrictRegex;
+            } else {
+                return this._weekdaysMinRegex;
+            }
+        } else {
+            return this._weekdaysMinStrictRegex && isStrict ?
+                this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
+        }
+    }
+
+
+    function computeWeekdaysParse () {
+        function cmpLenRev(a, b) {
+            return b.length - a.length;
+        }
+
+        var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
+            i, mom, minp, shortp, longp;
+        for (i = 0; i < 7; i++) {
+            // make the regex if we don't have it already
+            mom = create_utc__createUTC([2000, 1]).day(i);
+            minp = this.weekdaysMin(mom, '');
+            shortp = this.weekdaysShort(mom, '');
+            longp = this.weekdays(mom, '');
+            minPieces.push(minp);
+            shortPieces.push(shortp);
+            longPieces.push(longp);
+            mixedPieces.push(minp);
+            mixedPieces.push(shortp);
+            mixedPieces.push(longp);
+        }
+        // Sorting makes sure if one weekday (or abbr) is a prefix of another it
+        // will match the longer piece.
+        minPieces.sort(cmpLenRev);
+        shortPieces.sort(cmpLenRev);
+        longPieces.sort(cmpLenRev);
+        mixedPieces.sort(cmpLenRev);
+        for (i = 0; i < 7; i++) {
+            shortPieces[i] = regexEscape(shortPieces[i]);
+            longPieces[i] = regexEscape(longPieces[i]);
+            mixedPieces[i] = regexEscape(mixedPieces[i]);
+        }
+
+        this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+        this._weekdaysShortRegex = this._weekdaysRegex;
+        this._weekdaysMinRegex = this._weekdaysRegex;
+
+        this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
+        this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
+        this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
+    }
+
+    // FORMATTING
+
+    addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
+
+    // ALIASES
+
+    addUnitAlias('dayOfYear', 'DDD');
+
+    // PARSING
+
+    addRegexToken('DDD',  match1to3);
+    addRegexToken('DDDD', match3);
+    addParseToken(['DDD', 'DDDD'], function (input, array, config) {
+        config._dayOfYear = toInt(input);
+    });
+
+    // HELPERS
+
+    // MOMENTS
+
+    function getSetDayOfYear (input) {
+        var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
+        return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
+    }
+
+    // FORMATTING
+
+    function hFormat() {
+        return this.hours() % 12 || 12;
+    }
+
+    function kFormat() {
+        return this.hours() || 24;
+    }
+
+    addFormatToken('H', ['HH', 2], 0, 'hour');
+    addFormatToken('h', ['hh', 2], 0, hFormat);
+    addFormatToken('k', ['kk', 2], 0, kFormat);
+
+    addFormatToken('hmm', 0, 0, function () {
+        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
+    });
+
+    addFormatToken('hmmss', 0, 0, function () {
+        return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
+            zeroFill(this.seconds(), 2);
+    });
+
+    addFormatToken('Hmm', 0, 0, function () {
+        return '' + this.hours() + zeroFill(this.minutes(), 2);
+    });
+
+    addFormatToken('Hmmss', 0, 0, function () {
+        return '' + this.hours() + zeroFill(this.minutes(), 2) +
+            zeroFill(this.seconds(), 2);
+    });
+
+    function meridiem (token, lowercase) {
+        addFormatToken(token, 0, 0, function () {
+            return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
+        });
+    }
+
+    meridiem('a', true);
+    meridiem('A', false);
+
+    // ALIASES
+
+    addUnitAlias('hour', 'h');
+
+    // PARSING
+
+    function matchMeridiem (isStrict, locale) {
+        return locale._meridiemParse;
+    }
+
+    addRegexToken('a',  matchMeridiem);
+    addRegexToken('A',  matchMeridiem);
+    addRegexToken('H',  match1to2);
+    addRegexToken('h',  match1to2);
+    addRegexToken('HH', match1to2, match2);
+    addRegexToken('hh', match1to2, match2);
+
+    addRegexToken('hmm', match3to4);
+    addRegexToken('hmmss', match5to6);
+    addRegexToken('Hmm', match3to4);
+    addRegexToken('Hmmss', match5to6);
+
+    addParseToken(['H', 'HH'], HOUR);
+    addParseToken(['a', 'A'], function (input, array, config) {
+        config._isPm = config._locale.isPM(input);
+        config._meridiem = input;
+    });
+    addParseToken(['h', 'hh'], function (input, array, config) {
+        array[HOUR] = toInt(input);
+        getParsingFlags(config).bigHour = true;
+    });
+    addParseToken('hmm', function (input, array, config) {
+        var pos = input.length - 2;
+        array[HOUR] = toInt(input.substr(0, pos));
+        array[MINUTE] = toInt(input.substr(pos));
+        getParsingFlags(config).bigHour = true;
+    });
+    addParseToken('hmmss', function (input, array, config) {
+        var pos1 = input.length - 4;
+        var pos2 = input.length - 2;
+        array[HOUR] = toInt(input.substr(0, pos1));
+        array[MINUTE] = toInt(input.substr(pos1, 2));
+        array[SECOND] = toInt(input.substr(pos2));
+        getParsingFlags(config).bigHour = true;
+    });
+    addParseToken('Hmm', function (input, array, config) {
+        var pos = input.length - 2;
+        array[HOUR] = toInt(input.substr(0, pos));
+        array[MINUTE] = toInt(input.substr(pos));
+    });
+    addParseToken('Hmmss', function (input, array, config) {
+        var pos1 = input.length - 4;
+        var pos2 = input.length - 2;
+        array[HOUR] = toInt(input.substr(0, pos1));
+        array[MINUTE] = toInt(input.substr(pos1, 2));
+        array[SECOND] = toInt(input.substr(pos2));
+    });
+
+    // LOCALES
+
+    function localeIsPM (input) {
+        // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+        // Using charAt should be more compatible.
+        return ((input + '').toLowerCase().charAt(0) === 'p');
+    }
+
+    var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
+    function localeMeridiem (hours, minutes, isLower) {
+        if (hours > 11) {
+            return isLower ? 'pm' : 'PM';
+        } else {
+            return isLower ? 'am' : 'AM';
+        }
+    }
+
+
+    // MOMENTS
+
+    // Setting the hour should keep the time, because the user explicitly
+    // specified which hour he wants. So trying to maintain the same hour (in
+    // a new timezone) makes sense. Adding/subtracting hours does not follow
+    // this rule.
+    var getSetHour = makeGetSet('Hours', true);
+
+    // FORMATTING
+
+    addFormatToken('m', ['mm', 2], 0, 'minute');
+
+    // ALIASES
+
+    addUnitAlias('minute', 'm');
+
+    // PARSING
+
+    addRegexToken('m',  match1to2);
+    addRegexToken('mm', match1to2, match2);
+    addParseToken(['m', 'mm'], MINUTE);
+
+    // MOMENTS
+
+    var getSetMinute = makeGetSet('Minutes', false);
+
+    // FORMATTING
+
+    addFormatToken('s', ['ss', 2], 0, 'second');
+
+    // ALIASES
+
+    addUnitAlias('second', 's');
+
+    // PARSING
+
+    addRegexToken('s',  match1to2);
+    addRegexToken('ss', match1to2, match2);
+    addParseToken(['s', 'ss'], SECOND);
+
+    // MOMENTS
+
+    var getSetSecond = makeGetSet('Seconds', false);
+
+    // FORMATTING
+
+    addFormatToken('S', 0, 0, function () {
+        return ~~(this.millisecond() / 100);
+    });
+
+    addFormatToken(0, ['SS', 2], 0, function () {
+        return ~~(this.millisecond() / 10);
+    });
+
+    addFormatToken(0, ['SSS', 3], 0, 'millisecond');
+    addFormatToken(0, ['SSSS', 4], 0, function () {
+        return this.millisecond() * 10;
+    });
+    addFormatToken(0, ['SSSSS', 5], 0, function () {
+        return this.millisecond() * 100;
+    });
+    addFormatToken(0, ['SSSSSS', 6], 0, function () {
+        return this.millisecond() * 1000;
+    });
+    addFormatToken(0, ['SSSSSSS', 7], 0, function () {
+        return this.millisecond() * 10000;
+    });
+    addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
+        return this.millisecond() * 100000;
+    });
+    addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
+        return this.millisecond() * 1000000;
+    });
+
+
+    // ALIASES
+
+    addUnitAlias('millisecond', 'ms');
+
+    // PARSING
+
+    addRegexToken('S',    match1to3, match1);
+    addRegexToken('SS',   match1to3, match2);
+    addRegexToken('SSS',  match1to3, match3);
+
+    var token;
+    for (token = 'SSSS'; token.length <= 9; token += 'S') {
+        addRegexToken(token, matchUnsigned);
+    }
+
+    function parseMs(input, array) {
+        array[MILLISECOND] = toInt(('0.' + input) * 1000);
+    }
+
+    for (token = 'S'; token.length <= 9; token += 'S') {
+        addParseToken(token, parseMs);
+    }
+    // MOMENTS
+
+    var getSetMillisecond = makeGetSet('Milliseconds', false);
+
+    // FORMATTING
+
+    addFormatToken('z',  0, 0, 'zoneAbbr');
+    addFormatToken('zz', 0, 0, 'zoneName');
+
+    // MOMENTS
+
+    function getZoneAbbr () {
+        return this._isUTC ? 'UTC' : '';
+    }
+
+    function getZoneName () {
+        return this._isUTC ? 'Coordinated Universal Time' : '';
+    }
+
+    var momentPrototype__proto = Moment.prototype;
+
+    momentPrototype__proto.add               = add_subtract__add;
+    momentPrototype__proto.calendar          = moment_calendar__calendar;
+    momentPrototype__proto.clone             = clone;
+    momentPrototype__proto.diff              = diff;
+    momentPrototype__proto.endOf             = endOf;
+    momentPrototype__proto.format            = moment_format__format;
+    momentPrototype__proto.from              = from;
+    momentPrototype__proto.fromNow           = fromNow;
+    momentPrototype__proto.to                = to;
+    momentPrototype__proto.toNow             = toNow;
+    momentPrototype__proto.get               = getSet;
+    momentPrototype__proto.invalidAt         = invalidAt;
+    momentPrototype__proto.isAfter           = isAfter;
+    momentPrototype__proto.isBefore          = isBefore;
+    momentPrototype__proto.isBetween         = isBetween;
+    momentPrototype__proto.isSame            = isSame;
+    momentPrototype__proto.isSameOrAfter     = isSameOrAfter;
+    momentPrototype__proto.isSameOrBefore    = isSameOrBefore;
+    momentPrototype__proto.isValid           = moment_valid__isValid;
+    momentPrototype__proto.lang              = lang;
+    momentPrototype__proto.locale            = locale;
+    momentPrototype__proto.localeData        = localeData;
+    momentPrototype__proto.max               = prototypeMax;
+    momentPrototype__proto.min               = prototypeMin;
+    momentPrototype__proto.parsingFlags      = parsingFlags;
+    momentPrototype__proto.set               = getSet;
+    momentPrototype__proto.startOf           = startOf;
+    momentPrototype__proto.subtract          = add_subtract__subtract;
+    momentPrototype__proto.toArray           = toArray;
+    momentPrototype__proto.toObject          = toObject;
+    momentPrototype__proto.toDate            = toDate;
+    momentPrototype__proto.toISOString       = moment_format__toISOString;
+    momentPrototype__proto.toJSON            = toJSON;
+    momentPrototype__proto.toString          = toString;
+    momentPrototype__proto.unix              = unix;
+    momentPrototype__proto.valueOf           = to_type__valueOf;
+    momentPrototype__proto.creationData      = creationData;
+
+    // Year
+    momentPrototype__proto.year       = getSetYear;
+    momentPrototype__proto.isLeapYear = getIsLeapYear;
+
+    // Week Year
+    momentPrototype__proto.weekYear    = getSetWeekYear;
+    momentPrototype__proto.isoWeekYear = getSetISOWeekYear;
+
+    // Quarter
+    momentPrototype__proto.quarter = momentPrototype__proto.quarters = getSetQuarter;
+
+    // Month
+    momentPrototype__proto.month       = getSetMonth;
+    momentPrototype__proto.daysInMonth = getDaysInMonth;
+
+    // Week
+    momentPrototype__proto.week           = momentPrototype__proto.weeks        = getSetWeek;
+    momentPrototype__proto.isoWeek        = momentPrototype__proto.isoWeeks     = getSetISOWeek;
+    momentPrototype__proto.weeksInYear    = getWeeksInYear;
+    momentPrototype__proto.isoWeeksInYear = getISOWeeksInYear;
+
+    // Day
+    momentPrototype__proto.date       = getSetDayOfMonth;
+    momentPrototype__proto.day        = momentPrototype__proto.days             = getSetDayOfWeek;
+    momentPrototype__proto.weekday    = getSetLocaleDayOfWeek;
+    momentPrototype__proto.isoWeekday = getSetISODayOfWeek;
+    momentPrototype__proto.dayOfYear  = getSetDayOfYear;
+
+    // Hour
+    momentPrototype__proto.hour = momentPrototype__proto.hours = getSetHour;
+
+    // Minute
+    momentPrototype__proto.minute = momentPrototype__proto.minutes = getSetMinute;
+
+    // Second
+    momentPrototype__proto.second = momentPrototype__proto.seconds = getSetSecond;
+
+    // Millisecond
+    momentPrototype__proto.millisecond = momentPrototype__proto.milliseconds = getSetMillisecond;
+
+    // Offset
+    momentPrototype__proto.utcOffset            = getSetOffset;
+    momentPrototype__proto.utc                  = setOffsetToUTC;
+    momentPrototype__proto.local                = setOffsetToLocal;
+    momentPrototype__proto.parseZone            = setOffsetToParsedOffset;
+    momentPrototype__proto.hasAlignedHourOffset = hasAlignedHourOffset;
+    momentPrototype__proto.isDST                = isDaylightSavingTime;
+    momentPrototype__proto.isDSTShifted         = isDaylightSavingTimeShifted;
+    momentPrototype__proto.isLocal              = isLocal;
+    momentPrototype__proto.isUtcOffset          = isUtcOffset;
+    momentPrototype__proto.isUtc                = isUtc;
+    momentPrototype__proto.isUTC                = isUtc;
+
+    // Timezone
+    momentPrototype__proto.zoneAbbr = getZoneAbbr;
+    momentPrototype__proto.zoneName = getZoneName;
+
+    // Deprecations
+    momentPrototype__proto.dates  = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
+    momentPrototype__proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
+    momentPrototype__proto.years  = deprecate('years accessor is deprecated. Use year instead', getSetYear);
+    momentPrototype__proto.zone   = deprecate('moment().zone is deprecated, use moment().utcOffset instead. https://github.com/moment/moment/issues/1779', getSetZone);
+
+    var momentPrototype = momentPrototype__proto;
+
+    function moment_moment__createUnix (input) {
+        return local__createLocal(input * 1000);
+    }
+
+    function moment_moment__createInZone () {
+        return local__createLocal.apply(null, arguments).parseZone();
+    }
+
+    var defaultCalendar = {
+        sameDay : '[Today at] LT',
+        nextDay : '[Tomorrow at] LT',
+        nextWeek : 'dddd [at] LT',
+        lastDay : '[Yesterday at] LT',
+        lastWeek : '[Last] dddd [at] LT',
+        sameElse : 'L'
+    };
+
+    function locale_calendar__calendar (key, mom, now) {
+        var output = this._calendar[key];
+        return isFunction(output) ? output.call(mom, now) : output;
+    }
+
+    var defaultLongDateFormat = {
+        LTS  : 'h:mm:ss A',
+        LT   : 'h:mm A',
+        L    : 'MM/DD/YYYY',
+        LL   : 'MMMM D, YYYY',
+        LLL  : 'MMMM D, YYYY h:mm A',
+        LLLL : 'dddd, MMMM D, YYYY h:mm A'
+    };
+
+    function longDateFormat (key) {
+        var format = this._longDateFormat[key],
+            formatUpper = this._longDateFormat[key.toUpperCase()];
+
+        if (format || !formatUpper) {
+            return format;
+        }
+
+        this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
+            return val.slice(1);
+        });
+
+        return this._longDateFormat[key];
+    }
+
+    var defaultInvalidDate = 'Invalid date';
+
+    function invalidDate () {
+        return this._invalidDate;
+    }
+
+    var defaultOrdinal = '%d';
+    var defaultOrdinalParse = /\d{1,2}/;
+
+    function ordinal (number) {
+        return this._ordinal.replace('%d', number);
+    }
+
+    function preParsePostFormat (string) {
+        return string;
+    }
+
+    var defaultRelativeTime = {
+        future : 'in %s',
+        past   : '%s ago',
+        s  : 'a few seconds',
+        m  : 'a minute',
+        mm : '%d minutes',
+        h  : 'an hour',
+        hh : '%d hours',
+        d  : 'a day',
+        dd : '%d days',
+        M  : 'a month',
+        MM : '%d months',
+        y  : 'a year',
+        yy : '%d years'
+    };
+
+    function relative__relativeTime (number, withoutSuffix, string, isFuture) {
+        var output = this._relativeTime[string];
+        return (isFunction(output)) ?
+            output(number, withoutSuffix, string, isFuture) :
+            output.replace(/%d/i, number);
+    }
+
+    function pastFuture (diff, output) {
+        var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+        return isFunction(format) ? format(output) : format.replace(/%s/i, output);
+    }
+
+    var prototype__proto = Locale.prototype;
+
+    prototype__proto._calendar       = defaultCalendar;
+    prototype__proto.calendar        = locale_calendar__calendar;
+    prototype__proto._longDateFormat = defaultLongDateFormat;
+    prototype__proto.longDateFormat  = longDateFormat;
+    prototype__proto._invalidDate    = defaultInvalidDate;
+    prototype__proto.invalidDate     = invalidDate;
+    prototype__proto._ordinal        = defaultOrdinal;
+    prototype__proto.ordinal         = ordinal;
+    prototype__proto._ordinalParse   = defaultOrdinalParse;
+    prototype__proto.preparse        = preParsePostFormat;
+    prototype__proto.postformat      = preParsePostFormat;
+    prototype__proto._relativeTime   = defaultRelativeTime;
+    prototype__proto.relativeTime    = relative__relativeTime;
+    prototype__proto.pastFuture      = pastFuture;
+    prototype__proto.set             = locale_set__set;
+
+    // Month
+    prototype__proto.months            =        localeMonths;
+    prototype__proto._months           = defaultLocaleMonths;
+    prototype__proto.monthsShort       =        localeMonthsShort;
+    prototype__proto._monthsShort      = defaultLocaleMonthsShort;
+    prototype__proto.monthsParse       =        localeMonthsParse;
+    prototype__proto._monthsRegex      = defaultMonthsRegex;
+    prototype__proto.monthsRegex       = monthsRegex;
+    prototype__proto._monthsShortRegex = defaultMonthsShortRegex;
+    prototype__proto.monthsShortRegex  = monthsShortRegex;
+
+    // Week
+    prototype__proto.week = localeWeek;
+    prototype__proto._week = defaultLocaleWeek;
+    prototype__proto.firstDayOfYear = localeFirstDayOfYear;
+    prototype__proto.firstDayOfWeek = localeFirstDayOfWeek;
+
+    // Day of Week
+    prototype__proto.weekdays       =        localeWeekdays;
+    prototype__proto._weekdays      = defaultLocaleWeekdays;
+    prototype__proto.weekdaysMin    =        localeWeekdaysMin;
+    prototype__proto._weekdaysMin   = defaultLocaleWeekdaysMin;
+    prototype__proto.weekdaysShort  =        localeWeekdaysShort;
+    prototype__proto._weekdaysShort = defaultLocaleWeekdaysShort;
+    prototype__proto.weekdaysParse  =        localeWeekdaysParse;
+
+    prototype__proto._weekdaysRegex      = defaultWeekdaysRegex;
+    prototype__proto.weekdaysRegex       =        weekdaysRegex;
+    prototype__proto._weekdaysShortRegex = defaultWeekdaysShortRegex;
+    prototype__proto.weekdaysShortRegex  =        weekdaysShortRegex;
+    prototype__proto._weekdaysMinRegex   = defaultWeekdaysMinRegex;
+    prototype__proto.weekdaysMinRegex    =        weekdaysMinRegex;
+
+    // Hours
+    prototype__proto.isPM = localeIsPM;
+    prototype__proto._meridiemParse = defaultLocaleMeridiemParse;
+    prototype__proto.meridiem = localeMeridiem;
+
+    function lists__get (format, index, field, setter) {
+        var locale = locale_locales__getLocale();
+        var utc = create_utc__createUTC().set(setter, index);
+        return locale[field](utc, format);
+    }
+
+    function listMonthsImpl (format, index, field) {
+        if (typeof format === 'number') {
+            index = format;
+            format = undefined;
+        }
+
+        format = format || '';
+
+        if (index != null) {
+            return lists__get(format, index, field, 'month');
+        }
+
+        var i;
+        var out = [];
+        for (i = 0; i < 12; i++) {
+            out[i] = lists__get(format, i, field, 'month');
+        }
+        return out;
+    }
+
+    // ()
+    // (5)
+    // (fmt, 5)
+    // (fmt)
+    // (true)
+    // (true, 5)
+    // (true, fmt, 5)
+    // (true, fmt)
+    function listWeekdaysImpl (localeSorted, format, index, field) {
+        if (typeof localeSorted === 'boolean') {
+            if (typeof format === 'number') {
+                index = format;
+                format = undefined;
+            }
+
+            format = format || '';
+        } else {
+            format = localeSorted;
+            index = format;
+            localeSorted = false;
+
+            if (typeof format === 'number') {
+                index = format;
+                format = undefined;
+            }
+
+            format = format || '';
+        }
+
+        var locale = locale_locales__getLocale(),
+            shift = localeSorted ? locale._week.dow : 0;
+
+        if (index != null) {
+            return lists__get(format, (index + shift) % 7, field, 'day');
+        }
+
+        var i;
+        var out = [];
+        for (i = 0; i < 7; i++) {
+            out[i] = lists__get(format, (i + shift) % 7, field, 'day');
+        }
+        return out;
+    }
+
+    function lists__listMonths (format, index) {
+        return listMonthsImpl(format, index, 'months');
+    }
+
+    function lists__listMonthsShort (format, index) {
+        return listMonthsImpl(format, index, 'monthsShort');
+    }
+
+    function lists__listWeekdays (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
+    }
+
+    function lists__listWeekdaysShort (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
+    }
+
+    function lists__listWeekdaysMin (localeSorted, format, index) {
+        return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
+    }
+
+    locale_locales__getSetGlobalLocale('en', {
+        ordinalParse: /\d{1,2}(th|st|nd|rd)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (toInt(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        }
+    });
+
+    // Side effect imports
+    utils_hooks__hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', locale_locales__getSetGlobalLocale);
+    utils_hooks__hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', locale_locales__getLocale);
+
+    var mathAbs = Math.abs;
+
+    function duration_abs__abs () {
+        var data           = this._data;
+
+        this._milliseconds = mathAbs(this._milliseconds);
+        this._days         = mathAbs(this._days);
+        this._months       = mathAbs(this._months);
+
+        data.milliseconds  = mathAbs(data.milliseconds);
+        data.seconds       = mathAbs(data.seconds);
+        data.minutes       = mathAbs(data.minutes);
+        data.hours         = mathAbs(data.hours);
+        data.months        = mathAbs(data.months);
+        data.years         = mathAbs(data.years);
+
+        return this;
+    }
+
+    function duration_add_subtract__addSubtract (duration, input, value, direction) {
+        var other = create__createDuration(input, value);
+
+        duration._milliseconds += direction * other._milliseconds;
+        duration._days         += direction * other._days;
+        duration._months       += direction * other._months;
+
+        return duration._bubble();
+    }
+
+    // supports only 2.0-style add(1, 's') or add(duration)
+    function duration_add_subtract__add (input, value) {
+        return duration_add_subtract__addSubtract(this, input, value, 1);
+    }
+
+    // supports only 2.0-style subtract(1, 's') or subtract(duration)
+    function duration_add_subtract__subtract (input, value) {
+        return duration_add_subtract__addSubtract(this, input, value, -1);
+    }
+
+    function absCeil (number) {
+        if (number < 0) {
+            return Math.floor(number);
+        } else {
+            return Math.ceil(number);
+        }
+    }
+
+    function bubble () {
+        var milliseconds = this._milliseconds;
+        var days         = this._days;
+        var months       = this._months;
+        var data         = this._data;
+        var seconds, minutes, hours, years, monthsFromDays;
+
+        // if we have a mix of positive and negative values, bubble down first
+        // check: https://github.com/moment/moment/issues/2166
+        if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
+                (milliseconds <= 0 && days <= 0 && months <= 0))) {
+            milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
+            days = 0;
+            months = 0;
+        }
+
+        // The following code bubbles up values, see the tests for
+        // examples of what that means.
+        data.milliseconds = milliseconds % 1000;
+
+        seconds           = absFloor(milliseconds / 1000);
+        data.seconds      = seconds % 60;
+
+        minutes           = absFloor(seconds / 60);
+        data.minutes      = minutes % 60;
+
+        hours             = absFloor(minutes / 60);
+        data.hours        = hours % 24;
+
+        days += absFloor(hours / 24);
+
+        // convert days to months
+        monthsFromDays = absFloor(daysToMonths(days));
+        months += monthsFromDays;
+        days -= absCeil(monthsToDays(monthsFromDays));
+
+        // 12 months -> 1 year
+        years = absFloor(months / 12);
+        months %= 12;
+
+        data.days   = days;
+        data.months = months;
+        data.years  = years;
+
+        return this;
+    }
+
+    function daysToMonths (days) {
+        // 400 years have 146097 days (taking into account leap year rules)
+        // 400 years have 12 months === 4800
+        return days * 4800 / 146097;
+    }
+
+    function monthsToDays (months) {
+        // the reverse of daysToMonths
+        return months * 146097 / 4800;
+    }
+
+    function as (units) {
+        var days;
+        var months;
+        var milliseconds = this._milliseconds;
+
+        units = normalizeUnits(units);
+
+        if (units === 'month' || units === 'year') {
+            days   = this._days   + milliseconds / 864e5;
+            months = this._months + daysToMonths(days);
+            return units === 'month' ? months : months / 12;
+        } else {
+            // handle milliseconds separately because of floating point math errors (issue #1867)
+            days = this._days + Math.round(monthsToDays(this._months));
+            switch (units) {
+                case 'week'   : return days / 7     + milliseconds / 6048e5;
+                case 'day'    : return days         + milliseconds / 864e5;
+                case 'hour'   : return days * 24    + milliseconds / 36e5;
+                case 'minute' : return days * 1440  + milliseconds / 6e4;
+                case 'second' : return days * 86400 + milliseconds / 1000;
+                // Math.floor prevents floating point math errors here
+                case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
+                default: throw new Error('Unknown unit ' + units);
+            }
+        }
+    }
+
+    // TODO: Use this.as('ms')?
+    function duration_as__valueOf () {
+        return (
+            this._milliseconds +
+            this._days * 864e5 +
+            (this._months % 12) * 2592e6 +
+            toInt(this._months / 12) * 31536e6
+        );
+    }
+
+    function makeAs (alias) {
+        return function () {
+            return this.as(alias);
+        };
+    }
+
+    var asMilliseconds = makeAs('ms');
+    var asSeconds      = makeAs('s');
+    var asMinutes      = makeAs('m');
+    var asHours        = makeAs('h');
+    var asDays         = makeAs('d');
+    var asWeeks        = makeAs('w');
+    var asMonths       = makeAs('M');
+    var asYears        = makeAs('y');
+
+    function duration_get__get (units) {
+        units = normalizeUnits(units);
+        return this[units + 's']();
+    }
+
+    function makeGetter(name) {
+        return function () {
+            return this._data[name];
+        };
+    }
+
+    var milliseconds = makeGetter('milliseconds');
+    var seconds      = makeGetter('seconds');
+    var minutes      = makeGetter('minutes');
+    var hours        = makeGetter('hours');
+    var days         = makeGetter('days');
+    var duration_get__months       = makeGetter('months');
+    var years        = makeGetter('years');
+
+    function weeks () {
+        return absFloor(this.days() / 7);
+    }
+
+    var round = Math.round;
+    var thresholds = {
+        s: 45,  // seconds to minute
+        m: 45,  // minutes to hour
+        h: 22,  // hours to day
+        d: 26,  // days to month
+        M: 11   // months to year
+    };
+
+    // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+    function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
+        return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+    }
+
+    function duration_humanize__relativeTime (posNegDuration, withoutSuffix, locale) {
+        var duration = create__createDuration(posNegDuration).abs();
+        var seconds  = round(duration.as('s'));
+        var minutes  = round(duration.as('m'));
+        var hours    = round(duration.as('h'));
+        var days     = round(duration.as('d'));
+        var months   = round(duration.as('M'));
+        var years    = round(duration.as('y'));
+
+        var a = seconds < thresholds.s && ['s', seconds]  ||
+                minutes <= 1           && ['m']           ||
+                minutes < thresholds.m && ['mm', minutes] ||
+                hours   <= 1           && ['h']           ||
+                hours   < thresholds.h && ['hh', hours]   ||
+                days    <= 1           && ['d']           ||
+                days    < thresholds.d && ['dd', days]    ||
+                months  <= 1           && ['M']           ||
+                months  < thresholds.M && ['MM', months]  ||
+                years   <= 1           && ['y']           || ['yy', years];
+
+        a[2] = withoutSuffix;
+        a[3] = +posNegDuration > 0;
+        a[4] = locale;
+        return substituteTimeAgo.apply(null, a);
+    }
+
+    // This function allows you to set a threshold for relative time strings
+    function duration_humanize__getSetRelativeTimeThreshold (threshold, limit) {
+        if (thresholds[threshold] === undefined) {
+            return false;
+        }
+        if (limit === undefined) {
+            return thresholds[threshold];
+        }
+        thresholds[threshold] = limit;
+        return true;
+    }
+
+    function humanize (withSuffix) {
+        var locale = this.localeData();
+        var output = duration_humanize__relativeTime(this, !withSuffix, locale);
+
+        if (withSuffix) {
+            output = locale.pastFuture(+this, output);
+        }
+
+        return locale.postformat(output);
+    }
+
+    var iso_string__abs = Math.abs;
+
+    function iso_string__toISOString() {
+        // for ISO strings we do not use the normal bubbling rules:
+        //  * milliseconds bubble up until they become hours
+        //  * days do not bubble at all
+        //  * months bubble up until they become years
+        // This is because there is no context-free conversion between hours and days
+        // (think of clock changes)
+        // and also not between days and months (28-31 days per month)
+        var seconds = iso_string__abs(this._milliseconds) / 1000;
+        var days         = iso_string__abs(this._days);
+        var months       = iso_string__abs(this._months);
+        var minutes, hours, years;
+
+        // 3600 seconds -> 60 minutes -> 1 hour
+        minutes           = absFloor(seconds / 60);
+        hours             = absFloor(minutes / 60);
+        seconds %= 60;
+        minutes %= 60;
+
+        // 12 months -> 1 year
+        years  = absFloor(months / 12);
+        months %= 12;
+
+
+        // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
+        var Y = years;
+        var M = months;
+        var D = days;
+        var h = hours;
+        var m = minutes;
+        var s = seconds;
+        var total = this.asSeconds();
+
+        if (!total) {
+            // this is the same as C#'s (Noda) and python (isodate)...
+            // but not other JS (goog.date)
+            return 'P0D';
+        }
+
+        return (total < 0 ? '-' : '') +
+            'P' +
+            (Y ? Y + 'Y' : '') +
+            (M ? M + 'M' : '') +
+            (D ? D + 'D' : '') +
+            ((h || m || s) ? 'T' : '') +
+            (h ? h + 'H' : '') +
+            (m ? m + 'M' : '') +
+            (s ? s + 'S' : '');
+    }
+
+    var duration_prototype__proto = Duration.prototype;
+
+    duration_prototype__proto.abs            = duration_abs__abs;
+    duration_prototype__proto.add            = duration_add_subtract__add;
+    duration_prototype__proto.subtract       = duration_add_subtract__subtract;
+    duration_prototype__proto.as             = as;
+    duration_prototype__proto.asMilliseconds = asMilliseconds;
+    duration_prototype__proto.asSeconds      = asSeconds;
+    duration_prototype__proto.asMinutes      = asMinutes;
+    duration_prototype__proto.asHours        = asHours;
+    duration_prototype__proto.asDays         = asDays;
+    duration_prototype__proto.asWeeks        = asWeeks;
+    duration_prototype__proto.asMonths       = asMonths;
+    duration_prototype__proto.asYears        = asYears;
+    duration_prototype__proto.valueOf        = duration_as__valueOf;
+    duration_prototype__proto._bubble        = bubble;
+    duration_prototype__proto.get            = duration_get__get;
+    duration_prototype__proto.milliseconds   = milliseconds;
+    duration_prototype__proto.seconds        = seconds;
+    duration_prototype__proto.minutes        = minutes;
+    duration_prototype__proto.hours          = hours;
+    duration_prototype__proto.days           = days;
+    duration_prototype__proto.weeks          = weeks;
+    duration_prototype__proto.months         = duration_get__months;
+    duration_prototype__proto.years          = years;
+    duration_prototype__proto.humanize       = humanize;
+    duration_prototype__proto.toISOString    = iso_string__toISOString;
+    duration_prototype__proto.toString       = iso_string__toISOString;
+    duration_prototype__proto.toJSON         = iso_string__toISOString;
+    duration_prototype__proto.locale         = locale;
+    duration_prototype__proto.localeData     = localeData;
+
+    // Deprecations
+    duration_prototype__proto.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', iso_string__toISOString);
+    duration_prototype__proto.lang = lang;
+
+    // Side effect imports
+
+    // FORMATTING
+
+    addFormatToken('X', 0, 0, 'unix');
+    addFormatToken('x', 0, 0, 'valueOf');
+
+    // PARSING
+
+    addRegexToken('x', matchSigned);
+    addRegexToken('X', matchTimestamp);
+    addParseToken('X', function (input, array, config) {
+        config._d = new Date(parseFloat(input, 10) * 1000);
+    });
+    addParseToken('x', function (input, array, config) {
+        config._d = new Date(toInt(input));
+    });
+
+    // Side effect imports
+
+    ;
+
+    //! moment.js
+    //! version : 2.13.0
+    //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+    //! license : MIT
+    //! momentjs.com
+
+    utils_hooks__hooks.version = '2.13.0';
+
+    setHookCallback(local__createLocal);
+
+    utils_hooks__hooks.fn                    = momentPrototype;
+    utils_hooks__hooks.min                   = min;
+    utils_hooks__hooks.max                   = max;
+    utils_hooks__hooks.now                   = now;
+    utils_hooks__hooks.utc                   = create_utc__createUTC;
+    utils_hooks__hooks.unix                  = moment_moment__createUnix;
+    utils_hooks__hooks.months                = lists__listMonths;
+    utils_hooks__hooks.isDate                = isDate;
+    utils_hooks__hooks.locale                = locale_locales__getSetGlobalLocale;
+    utils_hooks__hooks.invalid               = valid__createInvalid;
+    utils_hooks__hooks.duration              = create__createDuration;
+    utils_hooks__hooks.isMoment              = isMoment;
+    utils_hooks__hooks.weekdays              = lists__listWeekdays;
+    utils_hooks__hooks.parseZone             = moment_moment__createInZone;
+    utils_hooks__hooks.localeData            = locale_locales__getLocale;
+    utils_hooks__hooks.isDuration            = isDuration;
+    utils_hooks__hooks.monthsShort           = lists__listMonthsShort;
+    utils_hooks__hooks.weekdaysMin           = lists__listWeekdaysMin;
+    utils_hooks__hooks.defineLocale          = defineLocale;
+    utils_hooks__hooks.updateLocale          = updateLocale;
+    utils_hooks__hooks.locales               = locale_locales__listLocales;
+    utils_hooks__hooks.weekdaysShort         = lists__listWeekdaysShort;
+    utils_hooks__hooks.normalizeUnits        = normalizeUnits;
+    utils_hooks__hooks.relativeTimeThreshold = duration_humanize__getSetRelativeTimeThreshold;
+    utils_hooks__hooks.prototype             = momentPrototype;
+
+    var moment__default = utils_hooks__hooks;
+
+    //! moment.js locale configuration
+    //! locale : afrikaans (af)
+    //! author : Werner Mollentze : https://github.com/wernerm
+
+    var af = moment__default.defineLocale('af', {
+        months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
+        weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
+        weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
+        weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
+        meridiemParse: /vm|nm/i,
+        isPM : function (input) {
+            return /^nm$/i.test(input);
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 12) {
+                return isLower ? 'vm' : 'VM';
+            } else {
+                return isLower ? 'nm' : 'NM';
+            }
+        },
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[Vandag om] LT',
+            nextDay : '[Môre om] LT',
+            nextWeek : 'dddd [om] LT',
+            lastDay : '[Gister om] LT',
+            lastWeek : '[Laas] dddd [om] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'oor %s',
+            past : '%s gelede',
+            s : '\'n paar sekondes',
+            m : '\'n minuut',
+            mm : '%d minute',
+            h : '\'n uur',
+            hh : '%d ure',
+            d : '\'n dag',
+            dd : '%d dae',
+            M : '\'n maand',
+            MM : '%d maande',
+            y : '\'n jaar',
+            yy : '%d jaar'
+        },
+        ordinalParse: /\d{1,2}(ste|de)/,
+        ordinal : function (number) {
+            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
+        },
+        week : {
+            dow : 1, // Maandag is die eerste dag van die week.
+            doy : 4  // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Moroccan Arabic (ar-ma)
+    //! author : ElFadili Yassine : https://github.com/ElFadiliY
+    //! author : Abdel Said : https://github.com/abdelsaid
+
+    var ar_ma = moment__default.defineLocale('ar-ma', {
+        months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+        monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+        weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+        weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
+        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[اليوم على الساعة] LT',
+            nextDay: '[غدا على الساعة] LT',
+            nextWeek: 'dddd [على الساعة] LT',
+            lastDay: '[أمس على الساعة] LT',
+            lastWeek: 'dddd [على الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'في %s',
+            past : 'منذ %s',
+            s : 'ثوان',
+            m : 'دقيقة',
+            mm : '%d دقائق',
+            h : 'ساعة',
+            hh : '%d ساعات',
+            d : 'يوم',
+            dd : '%d أيام',
+            M : 'شهر',
+            MM : '%d أشهر',
+            y : 'سنة',
+            yy : '%d سنوات'
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Arabic Saudi Arabia (ar-sa)
+    //! author : Suhail Alkowaileet : https://github.com/xsoh
+
+    var ar_sa__symbolMap = {
+        '1': '١',
+        '2': '٢',
+        '3': '٣',
+        '4': '٤',
+        '5': '٥',
+        '6': '٦',
+        '7': '٧',
+        '8': '٨',
+        '9': '٩',
+        '0': '٠'
+    }, ar_sa__numberMap = {
+        '١': '1',
+        '٢': '2',
+        '٣': '3',
+        '٤': '4',
+        '٥': '5',
+        '٦': '6',
+        '٧': '7',
+        '٨': '8',
+        '٩': '9',
+        '٠': '0'
+    };
+
+    var ar_sa = moment__default.defineLocale('ar-sa', {
+        months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+        monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        meridiemParse: /ص|م/,
+        isPM : function (input) {
+            return 'م' === input;
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'ص';
+            } else {
+                return 'م';
+            }
+        },
+        calendar : {
+            sameDay: '[اليوم على الساعة] LT',
+            nextDay: '[غدا على الساعة] LT',
+            nextWeek: 'dddd [على الساعة] LT',
+            lastDay: '[أمس على الساعة] LT',
+            lastWeek: 'dddd [على الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'في %s',
+            past : 'منذ %s',
+            s : 'ثوان',
+            m : 'دقيقة',
+            mm : '%d دقائق',
+            h : 'ساعة',
+            hh : '%d ساعات',
+            d : 'يوم',
+            dd : '%d أيام',
+            M : 'شهر',
+            MM : '%d أشهر',
+            y : 'سنة',
+            yy : '%d سنوات'
+        },
+        preparse: function (string) {
+            return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+                return ar_sa__numberMap[match];
+            }).replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return ar_sa__symbolMap[match];
+            }).replace(/,/g, '،');
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale  : Tunisian Arabic (ar-tn)
+
+    var ar_tn = moment__default.defineLocale('ar-tn', {
+        months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+        monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+        weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+        weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+        weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat: {
+            LT: 'HH:mm',
+            LTS: 'HH:mm:ss',
+            L: 'DD/MM/YYYY',
+            LL: 'D MMMM YYYY',
+            LLL: 'D MMMM YYYY HH:mm',
+            LLLL: 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar: {
+            sameDay: '[اليوم على الساعة] LT',
+            nextDay: '[غدا على الساعة] LT',
+            nextWeek: 'dddd [على الساعة] LT',
+            lastDay: '[أمس على الساعة] LT',
+            lastWeek: 'dddd [على الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: 'في %s',
+            past: 'منذ %s',
+            s: 'ثوان',
+            m: 'دقيقة',
+            mm: '%d دقائق',
+            h: 'ساعة',
+            hh: '%d ساعات',
+            d: 'يوم',
+            dd: '%d أيام',
+            M: 'شهر',
+            MM: '%d أشهر',
+            y: 'سنة',
+            yy: '%d سنوات'
+        },
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4 // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! Locale: Arabic (ar)
+    //! Author: Abdel Said: https://github.com/abdelsaid
+    //! Changes in months, weekdays: Ahmed Elkhatib
+    //! Native plural forms: forabi https://github.com/forabi
+
+    var ar__symbolMap = {
+        '1': '١',
+        '2': '٢',
+        '3': '٣',
+        '4': '٤',
+        '5': '٥',
+        '6': '٦',
+        '7': '٧',
+        '8': '٨',
+        '9': '٩',
+        '0': '٠'
+    }, ar__numberMap = {
+        '١': '1',
+        '٢': '2',
+        '٣': '3',
+        '٤': '4',
+        '٥': '5',
+        '٦': '6',
+        '٧': '7',
+        '٨': '8',
+        '٩': '9',
+        '٠': '0'
+    }, pluralForm = function (n) {
+        return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
+    }, plurals = {
+        s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
+        m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
+        h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
+        d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
+        M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
+        y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
+    }, pluralize = function (u) {
+        return function (number, withoutSuffix, string, isFuture) {
+            var f = pluralForm(number),
+                str = plurals[u][pluralForm(number)];
+            if (f === 2) {
+                str = str[withoutSuffix ? 0 : 1];
+            }
+            return str.replace(/%d/i, number);
+        };
+    }, ar__months = [
+        'كانون الثاني يناير',
+        'شباط فبراير',
+        'آذار مارس',
+        'نيسان أبريل',
+        'أيار مايو',
+        'حزيران يونيو',
+        'تموز يوليو',
+        'آب أغسطس',
+        'أيلول سبتمبر',
+        'تشرين الأول أكتوبر',
+        'تشرين الثاني نوفمبر',
+        'كانون الأول ديسمبر'
+    ];
+
+    var ar = moment__default.defineLocale('ar', {
+        months : ar__months,
+        monthsShort : ar__months,
+        weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+        weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+        weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'D/\u200FM/\u200FYYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        meridiemParse: /ص|م/,
+        isPM : function (input) {
+            return 'م' === input;
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'ص';
+            } else {
+                return 'م';
+            }
+        },
+        calendar : {
+            sameDay: '[اليوم عند الساعة] LT',
+            nextDay: '[غدًا عند الساعة] LT',
+            nextWeek: 'dddd [عند الساعة] LT',
+            lastDay: '[أمس عند الساعة] LT',
+            lastWeek: 'dddd [عند الساعة] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'بعد %s',
+            past : 'منذ %s',
+            s : pluralize('s'),
+            m : pluralize('m'),
+            mm : pluralize('m'),
+            h : pluralize('h'),
+            hh : pluralize('h'),
+            d : pluralize('d'),
+            dd : pluralize('d'),
+            M : pluralize('M'),
+            MM : pluralize('M'),
+            y : pluralize('y'),
+            yy : pluralize('y')
+        },
+        preparse: function (string) {
+            return string.replace(/\u200f/g, '').replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+                return ar__numberMap[match];
+            }).replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return ar__symbolMap[match];
+            }).replace(/,/g, '،');
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : azerbaijani (az)
+    //! author : topchiyev : https://github.com/topchiyev
+
+    var az__suffixes = {
+        1: '-inci',
+        5: '-inci',
+        8: '-inci',
+        70: '-inci',
+        80: '-inci',
+        2: '-nci',
+        7: '-nci',
+        20: '-nci',
+        50: '-nci',
+        3: '-üncü',
+        4: '-üncü',
+        100: '-üncü',
+        6: '-ncı',
+        9: '-uncu',
+        10: '-uncu',
+        30: '-uncu',
+        60: '-ıncı',
+        90: '-ıncı'
+    };
+
+    var az = moment__default.defineLocale('az', {
+        months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
+        monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
+        weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
+        weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
+        weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[bugün saat] LT',
+            nextDay : '[sabah saat] LT',
+            nextWeek : '[gələn həftə] dddd [saat] LT',
+            lastDay : '[dünən] LT',
+            lastWeek : '[keçən həftə] dddd [saat] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s sonra',
+            past : '%s əvvəl',
+            s : 'birneçə saniyyə',
+            m : 'bir dəqiqə',
+            mm : '%d dəqiqə',
+            h : 'bir saat',
+            hh : '%d saat',
+            d : 'bir gün',
+            dd : '%d gün',
+            M : 'bir ay',
+            MM : '%d ay',
+            y : 'bir il',
+            yy : '%d il'
+        },
+        meridiemParse: /gecə|səhər|gündüz|axşam/,
+        isPM : function (input) {
+            return /^(gündüz|axşam)$/.test(input);
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'gecə';
+            } else if (hour < 12) {
+                return 'səhər';
+            } else if (hour < 17) {
+                return 'gündüz';
+            } else {
+                return 'axşam';
+            }
+        },
+        ordinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
+        ordinal : function (number) {
+            if (number === 0) {  // special case for zero
+                return number + '-ıncı';
+            }
+            var a = number % 10,
+                b = number % 100 - a,
+                c = number >= 100 ? 100 : null;
+            return number + (az__suffixes[a] || az__suffixes[b] || az__suffixes[c]);
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : belarusian (be)
+    //! author : Dmitry Demidov : https://github.com/demidov91
+    //! author: Praleska: http://praleska.pro/
+    //! Author : Menelion Elensúle : https://github.com/Oire
+
+    function be__plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+    function be__relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
+            'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
+            'dd': 'дзень_дні_дзён',
+            'MM': 'месяц_месяцы_месяцаў',
+            'yy': 'год_гады_гадоў'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'хвіліна' : 'хвіліну';
+        }
+        else if (key === 'h') {
+            return withoutSuffix ? 'гадзіна' : 'гадзіну';
+        }
+        else {
+            return number + ' ' + be__plural(format[key], +number);
+        }
+    }
+
+    var be = moment__default.defineLocale('be', {
+        months : {
+            format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
+            standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
+        },
+        monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
+        weekdays : {
+            format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
+            standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
+            isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
+        },
+        weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+        weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY г.',
+            LLL : 'D MMMM YYYY г., HH:mm',
+            LLLL : 'dddd, D MMMM YYYY г., HH:mm'
+        },
+        calendar : {
+            sameDay: '[Сёння ў] LT',
+            nextDay: '[Заўтра ў] LT',
+            lastDay: '[Учора ў] LT',
+            nextWeek: function () {
+                return '[У] dddd [ў] LT';
+            },
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 5:
+                case 6:
+                    return '[У мінулую] dddd [ў] LT';
+                case 1:
+                case 2:
+                case 4:
+                    return '[У мінулы] dddd [ў] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'праз %s',
+            past : '%s таму',
+            s : 'некалькі секунд',
+            m : be__relativeTimeWithPlural,
+            mm : be__relativeTimeWithPlural,
+            h : be__relativeTimeWithPlural,
+            hh : be__relativeTimeWithPlural,
+            d : 'дзень',
+            dd : be__relativeTimeWithPlural,
+            M : 'месяц',
+            MM : be__relativeTimeWithPlural,
+            y : 'год',
+            yy : be__relativeTimeWithPlural
+        },
+        meridiemParse: /ночы|раніцы|дня|вечара/,
+        isPM : function (input) {
+            return /^(дня|вечара)$/.test(input);
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'ночы';
+            } else if (hour < 12) {
+                return 'раніцы';
+            } else if (hour < 17) {
+                return 'дня';
+            } else {
+                return 'вечара';
+            }
+        },
+        ordinalParse: /\d{1,2}-(і|ы|га)/,
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+            case 'w':
+            case 'W':
+                return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
+            case 'D':
+                return number + '-га';
+            default:
+                return number;
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : bulgarian (bg)
+    //! author : Krasen Borisov : https://github.com/kraz
+
+    var bg = moment__default.defineLocale('bg', {
+        months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+        monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+        weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+        weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+        weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'D.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY H:mm',
+            LLLL : 'dddd, D MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay : '[Днес в] LT',
+            nextDay : '[Утре в] LT',
+            nextWeek : 'dddd [в] LT',
+            lastDay : '[Вчера в] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[В изминалата] dddd [в] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[В изминалия] dddd [в] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'след %s',
+            past : 'преди %s',
+            s : 'няколко секунди',
+            m : 'минута',
+            mm : '%d минути',
+            h : 'час',
+            hh : '%d часа',
+            d : 'ден',
+            dd : '%d дни',
+            M : 'месец',
+            MM : '%d месеца',
+            y : 'година',
+            yy : '%d години'
+        },
+        ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+        ordinal : function (number) {
+            var lastDigit = number % 10,
+                last2Digits = number % 100;
+            if (number === 0) {
+                return number + '-ев';
+            } else if (last2Digits === 0) {
+                return number + '-ен';
+            } else if (last2Digits > 10 && last2Digits < 20) {
+                return number + '-ти';
+            } else if (lastDigit === 1) {
+                return number + '-ви';
+            } else if (lastDigit === 2) {
+                return number + '-ри';
+            } else if (lastDigit === 7 || lastDigit === 8) {
+                return number + '-ми';
+            } else {
+                return number + '-ти';
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Bengali (bn)
+    //! author : Kaushik Gandhi : https://github.com/kaushikgandhi
+
+    var bn__symbolMap = {
+        '1': '১',
+        '2': '২',
+        '3': '৩',
+        '4': '৪',
+        '5': '৫',
+        '6': '৬',
+        '7': '৭',
+        '8': '৮',
+        '9': '৯',
+        '0': '০'
+    },
+    bn__numberMap = {
+        '১': '1',
+        '২': '2',
+        '৩': '3',
+        '৪': '4',
+        '৫': '5',
+        '৬': '6',
+        '৭': '7',
+        '৮': '8',
+        '৯': '9',
+        '০': '0'
+    };
+
+    var bn = moment__default.defineLocale('bn', {
+        months : 'জানুয়ারী_ফেবুয়ারী_মার্চ_এপ্রিল_মে_জুন_জুলাই_অগাস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
+        monthsShort : 'জানু_ফেব_মার্চ_এপর_মে_জুন_জুল_অগ_সেপ্ট_অক্টো_নভ_ডিসেম্'.split('_'),
+        weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পত্তিবার_শুক্রবার_শনিবার'.split('_'),
+        weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পত্তি_শুক্র_শনি'.split('_'),
+        weekdaysMin : 'রব_সম_মঙ্গ_বু_ব্রিহ_শু_শনি'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm সময়',
+            LTS : 'A h:mm:ss সময়',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, A h:mm সময়',
+            LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
+        },
+        calendar : {
+            sameDay : '[আজ] LT',
+            nextDay : '[আগামীকাল] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[গতকাল] LT',
+            lastWeek : '[গত] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s পরে',
+            past : '%s আগে',
+            s : 'কয়েক সেকেন্ড',
+            m : 'এক মিনিট',
+            mm : '%d মিনিট',
+            h : 'এক ঘন্টা',
+            hh : '%d ঘন্টা',
+            d : 'এক দিন',
+            dd : '%d দিন',
+            M : 'এক মাস',
+            MM : '%d মাস',
+            y : 'এক বছর',
+            yy : '%d বছর'
+        },
+        preparse: function (string) {
+            return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
+                return bn__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return bn__symbolMap[match];
+            });
+        },
+        meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if ((meridiem === 'রাত' && hour >= 4) ||
+                    (meridiem === 'দুপুর' && hour < 5) ||
+                    meridiem === 'বিকাল') {
+                return hour + 12;
+            } else {
+                return hour;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'রাত';
+            } else if (hour < 10) {
+                return 'সকাল';
+            } else if (hour < 17) {
+                return 'দুপুর';
+            } else if (hour < 20) {
+                return 'বিকাল';
+            } else {
+                return 'রাত';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : tibetan (bo)
+    //! author : Thupten N. Chakrishar : https://github.com/vajradog
+
+    var bo__symbolMap = {
+        '1': '༡',
+        '2': '༢',
+        '3': '༣',
+        '4': '༤',
+        '5': '༥',
+        '6': '༦',
+        '7': '༧',
+        '8': '༨',
+        '9': '༩',
+        '0': '༠'
+    },
+    bo__numberMap = {
+        '༡': '1',
+        '༢': '2',
+        '༣': '3',
+        '༤': '4',
+        '༥': '5',
+        '༦': '6',
+        '༧': '7',
+        '༨': '8',
+        '༩': '9',
+        '༠': '0'
+    };
+
+    var bo = moment__default.defineLocale('bo', {
+        months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+        monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+        weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
+        weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+        weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm',
+            LTS : 'A h:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, A h:mm',
+            LLLL : 'dddd, D MMMM YYYY, A h:mm'
+        },
+        calendar : {
+            sameDay : '[དི་རིང] LT',
+            nextDay : '[སང་ཉིན] LT',
+            nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
+            lastDay : '[ཁ་སང] LT',
+            lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s ལ་',
+            past : '%s སྔན་ལ',
+            s : 'ལམ་སང',
+            m : 'སྐར་མ་གཅིག',
+            mm : '%d སྐར་མ',
+            h : 'ཆུ་ཚོད་གཅིག',
+            hh : '%d ཆུ་ཚོད',
+            d : 'ཉིན་གཅིག',
+            dd : '%d ཉིན་',
+            M : 'ཟླ་བ་གཅིག',
+            MM : '%d ཟླ་བ',
+            y : 'ལོ་གཅིག',
+            yy : '%d ལོ'
+        },
+        preparse: function (string) {
+            return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
+                return bo__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return bo__symbolMap[match];
+            });
+        },
+        meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
+                    (meridiem === 'ཉིན་གུང' && hour < 5) ||
+                    meridiem === 'དགོང་དག') {
+                return hour + 12;
+            } else {
+                return hour;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'མཚན་མོ';
+            } else if (hour < 10) {
+                return 'ཞོགས་ཀས';
+            } else if (hour < 17) {
+                return 'ཉིན་གུང';
+            } else if (hour < 20) {
+                return 'དགོང་དག';
+            } else {
+                return 'མཚན་མོ';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : breton (br)
+    //! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
+
+    function relativeTimeWithMutation(number, withoutSuffix, key) {
+        var format = {
+            'mm': 'munutenn',
+            'MM': 'miz',
+            'dd': 'devezh'
+        };
+        return number + ' ' + mutation(format[key], number);
+    }
+    function specialMutationForYears(number) {
+        switch (lastNumber(number)) {
+        case 1:
+        case 3:
+        case 4:
+        case 5:
+        case 9:
+            return number + ' bloaz';
+        default:
+            return number + ' vloaz';
+        }
+    }
+    function lastNumber(number) {
+        if (number > 9) {
+            return lastNumber(number % 10);
+        }
+        return number;
+    }
+    function mutation(text, number) {
+        if (number === 2) {
+            return softMutation(text);
+        }
+        return text;
+    }
+    function softMutation(text) {
+        var mutationTable = {
+            'm': 'v',
+            'b': 'v',
+            'd': 'z'
+        };
+        if (mutationTable[text.charAt(0)] === undefined) {
+            return text;
+        }
+        return mutationTable[text.charAt(0)] + text.substring(1);
+    }
+
+    var br = moment__default.defineLocale('br', {
+        months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
+        monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
+        weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
+        weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
+        weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'h[e]mm A',
+            LTS : 'h[e]mm:ss A',
+            L : 'DD/MM/YYYY',
+            LL : 'D [a viz] MMMM YYYY',
+            LLL : 'D [a viz] MMMM YYYY h[e]mm A',
+            LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
+        },
+        calendar : {
+            sameDay : '[Hiziv da] LT',
+            nextDay : '[Warc\'hoazh da] LT',
+            nextWeek : 'dddd [da] LT',
+            lastDay : '[Dec\'h da] LT',
+            lastWeek : 'dddd [paset da] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'a-benn %s',
+            past : '%s \'zo',
+            s : 'un nebeud segondennoù',
+            m : 'ur vunutenn',
+            mm : relativeTimeWithMutation,
+            h : 'un eur',
+            hh : '%d eur',
+            d : 'un devezh',
+            dd : relativeTimeWithMutation,
+            M : 'ur miz',
+            MM : relativeTimeWithMutation,
+            y : 'ur bloaz',
+            yy : specialMutationForYears
+        },
+        ordinalParse: /\d{1,2}(añ|vet)/,
+        ordinal : function (number) {
+            var output = (number === 1) ? 'añ' : 'vet';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : bosnian (bs)
+    //! author : Nedim Cholich : https://github.com/frontyard
+    //! based on (hr) translation by Bojan Marković
+
+    function bs__translate(number, withoutSuffix, key) {
+        var result = number + ' ';
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mjesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'mjeseca';
+            } else {
+                result += 'mjeseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
+        }
+    }
+
+    var bs = moment__default.defineLocale('bs', {
+        months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
+        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
+        monthsParseExact: true,
+        weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+        weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+        weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD. MM. YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY H:mm',
+            LLLL : 'dddd, D. MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay  : '[danas u] LT',
+            nextDay  : '[sutra u] LT',
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[jučer u] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past   : 'prije %s',
+            s      : 'par sekundi',
+            m      : bs__translate,
+            mm     : bs__translate,
+            h      : bs__translate,
+            hh     : bs__translate,
+            d      : 'dan',
+            dd     : bs__translate,
+            M      : 'mjesec',
+            MM     : bs__translate,
+            y      : 'godinu',
+            yy     : bs__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : catalan (ca)
+    //! author : Juan G. Hurtado : https://github.com/juanghurtado
+
+    var ca = moment__default.defineLocale('ca', {
+        months : 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
+        monthsShort : 'gen._febr._mar._abr._mai._jun._jul._ag._set._oct._nov._des.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
+        weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
+        weekdaysMin : 'Dg_Dl_Dt_Dc_Dj_Dv_Ds'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY H:mm',
+            LLLL : 'dddd D MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay : function () {
+                return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            nextDay : function () {
+                return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            lastDay : function () {
+                return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            lastWeek : function () {
+                return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'en %s',
+            past : 'fa %s',
+            s : 'uns segons',
+            m : 'un minut',
+            mm : '%d minuts',
+            h : 'una hora',
+            hh : '%d hores',
+            d : 'un dia',
+            dd : '%d dies',
+            M : 'un mes',
+            MM : '%d mesos',
+            y : 'un any',
+            yy : '%d anys'
+        },
+        ordinalParse: /\d{1,2}(r|n|t|è|a)/,
+        ordinal : function (number, period) {
+            var output = (number === 1) ? 'r' :
+                (number === 2) ? 'n' :
+                (number === 3) ? 'r' :
+                (number === 4) ? 't' : 'è';
+            if (period === 'w' || period === 'W') {
+                output = 'a';
+            }
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : czech (cs)
+    //! author : petrbela : https://github.com/petrbela
+
+    var cs__months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_'),
+        cs__monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
+    function cs__plural(n) {
+        return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
+    }
+    function cs__translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        switch (key) {
+        case 's':  // a few seconds / in a few seconds / a few seconds ago
+            return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
+        case 'm':  // a minute / in a minute / a minute ago
+            return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
+        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+            if (withoutSuffix || isFuture) {
+                return result + (cs__plural(number) ? 'minuty' : 'minut');
+            } else {
+                return result + 'minutami';
+            }
+            break;
+        case 'h':  // an hour / in an hour / an hour ago
+            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+        case 'hh': // 9 hours / in 9 hours / 9 hours ago
+            if (withoutSuffix || isFuture) {
+                return result + (cs__plural(number) ? 'hodiny' : 'hodin');
+            } else {
+                return result + 'hodinami';
+            }
+            break;
+        case 'd':  // a day / in a day / a day ago
+            return (withoutSuffix || isFuture) ? 'den' : 'dnem';
+        case 'dd': // 9 days / in 9 days / 9 days ago
+            if (withoutSuffix || isFuture) {
+                return result + (cs__plural(number) ? 'dny' : 'dní');
+            } else {
+                return result + 'dny';
+            }
+            break;
+        case 'M':  // a month / in a month / a month ago
+            return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
+        case 'MM': // 9 months / in 9 months / 9 months ago
+            if (withoutSuffix || isFuture) {
+                return result + (cs__plural(number) ? 'měsíce' : 'měsíců');
+            } else {
+                return result + 'měsíci';
+            }
+            break;
+        case 'y':  // a year / in a year / a year ago
+            return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
+        case 'yy': // 9 years / in 9 years / 9 years ago
+            if (withoutSuffix || isFuture) {
+                return result + (cs__plural(number) ? 'roky' : 'let');
+            } else {
+                return result + 'lety';
+            }
+            break;
+        }
+    }
+
+    var cs = moment__default.defineLocale('cs', {
+        months : cs__months,
+        monthsShort : cs__monthsShort,
+        monthsParse : (function (months, monthsShort) {
+            var i, _monthsParse = [];
+            for (i = 0; i < 12; i++) {
+                // use custom parser to solve problem with July (červenec)
+                _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
+            }
+            return _monthsParse;
+        }(cs__months, cs__monthsShort)),
+        shortMonthsParse : (function (monthsShort) {
+            var i, _shortMonthsParse = [];
+            for (i = 0; i < 12; i++) {
+                _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i');
+            }
+            return _shortMonthsParse;
+        }(cs__monthsShort)),
+        longMonthsParse : (function (months) {
+            var i, _longMonthsParse = [];
+            for (i = 0; i < 12; i++) {
+                _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i');
+            }
+            return _longMonthsParse;
+        }(cs__months)),
+        weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
+        weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'),
+        weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
+        longDateFormat : {
+            LT: 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY H:mm',
+            LLLL : 'dddd D. MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay: '[dnes v] LT',
+            nextDay: '[zítra v] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v neděli v] LT';
+                case 1:
+                case 2:
+                    return '[v] dddd [v] LT';
+                case 3:
+                    return '[ve středu v] LT';
+                case 4:
+                    return '[ve čtvrtek v] LT';
+                case 5:
+                    return '[v pátek v] LT';
+                case 6:
+                    return '[v sobotu v] LT';
+                }
+            },
+            lastDay: '[včera v] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[minulou neděli v] LT';
+                case 1:
+                case 2:
+                    return '[minulé] dddd [v] LT';
+                case 3:
+                    return '[minulou středu v] LT';
+                case 4:
+                case 5:
+                    return '[minulý] dddd [v] LT';
+                case 6:
+                    return '[minulou sobotu v] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past : 'před %s',
+            s : cs__translate,
+            m : cs__translate,
+            mm : cs__translate,
+            h : cs__translate,
+            hh : cs__translate,
+            d : cs__translate,
+            dd : cs__translate,
+            M : cs__translate,
+            MM : cs__translate,
+            y : cs__translate,
+            yy : cs__translate
+        },
+        ordinalParse : /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : chuvash (cv)
+    //! author : Anatoly Mironov : https://github.com/mirontoli
+
+    var cv = moment__default.defineLocale('cv', {
+        months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'),
+        monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'),
+        weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'),
+        weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'),
+        weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD-MM-YYYY',
+            LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
+            LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
+            LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm'
+        },
+        calendar : {
+            sameDay: '[Паян] LT [сехетре]',
+            nextDay: '[Ыран] LT [сехетре]',
+            lastDay: '[Ӗнер] LT [сехетре]',
+            nextWeek: '[Ҫитес] dddd LT [сехетре]',
+            lastWeek: '[Иртнӗ] dddd LT [сехетре]',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : function (output) {
+                var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран';
+                return output + affix;
+            },
+            past : '%s каялла',
+            s : 'пӗр-ик ҫеккунт',
+            m : 'пӗр минут',
+            mm : '%d минут',
+            h : 'пӗр сехет',
+            hh : '%d сехет',
+            d : 'пӗр кун',
+            dd : '%d кун',
+            M : 'пӗр уйӑх',
+            MM : '%d уйӑх',
+            y : 'пӗр ҫул',
+            yy : '%d ҫул'
+        },
+        ordinalParse: /\d{1,2}-мӗш/,
+        ordinal : '%d-мӗш',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Welsh (cy)
+    //! author : Robert Allen
+
+    var cy = moment__default.defineLocale('cy', {
+        months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'),
+        monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'),
+        weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'),
+        weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
+        weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
+        weekdaysParseExact : true,
+        // time formats are the same as en-gb
+        longDateFormat: {
+            LT: 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L: 'DD/MM/YYYY',
+            LL: 'D MMMM YYYY',
+            LLL: 'D MMMM YYYY HH:mm',
+            LLLL: 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar: {
+            sameDay: '[Heddiw am] LT',
+            nextDay: '[Yfory am] LT',
+            nextWeek: 'dddd [am] LT',
+            lastDay: '[Ddoe am] LT',
+            lastWeek: 'dddd [diwethaf am] LT',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: 'mewn %s',
+            past: '%s yn ôl',
+            s: 'ychydig eiliadau',
+            m: 'munud',
+            mm: '%d munud',
+            h: 'awr',
+            hh: '%d awr',
+            d: 'diwrnod',
+            dd: '%d diwrnod',
+            M: 'mis',
+            MM: '%d mis',
+            y: 'blwyddyn',
+            yy: '%d flynedd'
+        },
+        ordinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
+        // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
+        ordinal: function (number) {
+            var b = number,
+                output = '',
+                lookup = [
+                    '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
+                    'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
+                ];
+            if (b > 20) {
+                if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
+                    output = 'fed'; // not 30ain, 70ain or 90ain
+                } else {
+                    output = 'ain';
+                }
+            } else if (b > 0) {
+                output = lookup[b];
+            }
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : danish (da)
+    //! author : Ulrik Nielsen : https://github.com/mrbase
+
+    var da = moment__default.defineLocale('da', {
+        months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+        weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+        weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'),
+        weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY HH:mm',
+            LLLL : 'dddd [d.] D. MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[I dag kl.] LT',
+            nextDay : '[I morgen kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[I går kl.] LT',
+            lastWeek : '[sidste] dddd [kl] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : '%s siden',
+            s : 'få sekunder',
+            m : 'et minut',
+            mm : '%d minutter',
+            h : 'en time',
+            hh : '%d timer',
+            d : 'en dag',
+            dd : '%d dage',
+            M : 'en måned',
+            MM : '%d måneder',
+            y : 'et år',
+            yy : '%d år'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : austrian german (de-at)
+    //! author : lluchs : https://github.com/lluchs
+    //! author: Menelion Elensúle: https://github.com/Oire
+    //! author : Martin Groller : https://github.com/MadMG
+    //! author : Mikolaj Dadela : https://github.com/mik01aj
+
+    function de_at__processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eine Minute', 'einer Minute'],
+            'h': ['eine Stunde', 'einer Stunde'],
+            'd': ['ein Tag', 'einem Tag'],
+            'dd': [number + ' Tage', number + ' Tagen'],
+            'M': ['ein Monat', 'einem Monat'],
+            'MM': [number + ' Monate', number + ' Monaten'],
+            'y': ['ein Jahr', 'einem Jahr'],
+            'yy': [number + ' Jahre', number + ' Jahren']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+
+    var de_at = moment__default.defineLocale('de-at', {
+        months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+        monthsShort : 'Jän._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+        weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+        weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT: 'HH:mm',
+            LTS: 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY HH:mm',
+            LLLL : 'dddd, D. MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[heute um] LT [Uhr]',
+            sameElse: 'L',
+            nextDay: '[morgen um] LT [Uhr]',
+            nextWeek: 'dddd [um] LT [Uhr]',
+            lastDay: '[gestern um] LT [Uhr]',
+            lastWeek: '[letzten] dddd [um] LT [Uhr]'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : 'vor %s',
+            s : 'ein paar Sekunden',
+            m : de_at__processRelativeTime,
+            mm : '%d Minuten',
+            h : de_at__processRelativeTime,
+            hh : '%d Stunden',
+            d : de_at__processRelativeTime,
+            dd : de_at__processRelativeTime,
+            M : de_at__processRelativeTime,
+            MM : de_at__processRelativeTime,
+            y : de_at__processRelativeTime,
+            yy : de_at__processRelativeTime
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : german (de)
+    //! author : lluchs : https://github.com/lluchs
+    //! author: Menelion Elensúle: https://github.com/Oire
+    //! author : Mikolaj Dadela : https://github.com/mik01aj
+
+    function de__processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eine Minute', 'einer Minute'],
+            'h': ['eine Stunde', 'einer Stunde'],
+            'd': ['ein Tag', 'einem Tag'],
+            'dd': [number + ' Tage', number + ' Tagen'],
+            'M': ['ein Monat', 'einem Monat'],
+            'MM': [number + ' Monate', number + ' Monaten'],
+            'y': ['ein Jahr', 'einem Jahr'],
+            'yy': [number + ' Jahre', number + ' Jahren']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+
+    var de = moment__default.defineLocale('de', {
+        months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+        monthsShort : 'Jan._Febr._Mrz._Apr._Mai_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+        weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+        weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT: 'HH:mm',
+            LTS: 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY HH:mm',
+            LLLL : 'dddd, D. MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[heute um] LT [Uhr]',
+            sameElse: 'L',
+            nextDay: '[morgen um] LT [Uhr]',
+            nextWeek: 'dddd [um] LT [Uhr]',
+            lastDay: '[gestern um] LT [Uhr]',
+            lastWeek: '[letzten] dddd [um] LT [Uhr]'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : 'vor %s',
+            s : 'ein paar Sekunden',
+            m : de__processRelativeTime,
+            mm : '%d Minuten',
+            h : de__processRelativeTime,
+            hh : '%d Stunden',
+            d : de__processRelativeTime,
+            dd : de__processRelativeTime,
+            M : de__processRelativeTime,
+            MM : de__processRelativeTime,
+            y : de__processRelativeTime,
+            yy : de__processRelativeTime
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : dhivehi (dv)
+    //! author : Jawish Hameed : https://github.com/jawish
+
+    var dv__months = [
+        'ޖެނުއަރީ',
+        'ފެބްރުއަރީ',
+        'މާރިޗު',
+        'އޭޕްރީލު',
+        'މޭ',
+        'ޖޫން',
+        'ޖުލައި',
+        'އޯގަސްޓު',
+        'ސެޕްޓެމްބަރު',
+        'އޮކްޓޯބަރު',
+        'ނޮވެމްބަރު',
+        'ޑިސެމްބަރު'
+    ], dv__weekdays = [
+        'އާދިއްތަ',
+        'ހޯމަ',
+        'އަންގާރަ',
+        'ބުދަ',
+        'ބުރާސްފަތި',
+        'ހުކުރު',
+        'ހޮނިހިރު'
+    ];
+
+    var dv = moment__default.defineLocale('dv', {
+        months : dv__months,
+        monthsShort : dv__months,
+        weekdays : dv__weekdays,
+        weekdaysShort : dv__weekdays,
+        weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'),
+        longDateFormat : {
+
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'D/M/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        meridiemParse: /މކ|މފ/,
+        isPM : function (input) {
+            return 'މފ' === input;
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'މކ';
+            } else {
+                return 'މފ';
+            }
+        },
+        calendar : {
+            sameDay : '[މިއަދު] LT',
+            nextDay : '[މާދަމާ] LT',
+            nextWeek : 'dddd LT',
+            lastDay : '[އިއްޔެ] LT',
+            lastWeek : '[ފާއިތުވި] dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'ތެރޭގައި %s',
+            past : 'ކުރިން %s',
+            s : 'ސިކުންތުކޮޅެއް',
+            m : 'މިނިޓެއް',
+            mm : 'މިނިޓު %d',
+            h : 'ގަޑިއިރެއް',
+            hh : 'ގަޑިއިރު %d',
+            d : 'ދުވަހެއް',
+            dd : 'ދުވަސް %d',
+            M : 'މަހެއް',
+            MM : 'މަސް %d',
+            y : 'އަހަރެއް',
+            yy : 'އަހަރު %d'
+        },
+        preparse: function (string) {
+            return string.replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/,/g, '،');
+        },
+        week : {
+            dow : 7,  // Sunday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : modern greek (el)
+    //! author : Aggelos Karalias : https://github.com/mehiel
+
+    var el = moment__default.defineLocale('el', {
+        monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'),
+        monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'),
+        months : function (momentToFormat, format) {
+            if (/D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM'
+                return this._monthsGenitiveEl[momentToFormat.month()];
+            } else {
+                return this._monthsNominativeEl[momentToFormat.month()];
+            }
+        },
+        monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'),
+        weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'),
+        weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'),
+        weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'),
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'μμ' : 'ΜΜ';
+            } else {
+                return isLower ? 'πμ' : 'ΠΜ';
+            }
+        },
+        isPM : function (input) {
+            return ((input + '').toLowerCase()[0] === 'μ');
+        },
+        meridiemParse : /[ΠΜ]\.?Μ?\.?/i,
+        longDateFormat : {
+            LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY h:mm A',
+            LLLL : 'dddd, D MMMM YYYY h:mm A'
+        },
+        calendarEl : {
+            sameDay : '[Σήμερα {}] LT',
+            nextDay : '[Αύριο {}] LT',
+            nextWeek : 'dddd [{}] LT',
+            lastDay : '[Χθες {}] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                    case 6:
+                        return '[το προηγούμενο] dddd [{}] LT';
+                    default:
+                        return '[την προηγούμενη] dddd [{}] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        calendar : function (key, mom) {
+            var output = this._calendarEl[key],
+                hours = mom && mom.hours();
+            if (isFunction(output)) {
+                output = output.apply(mom);
+            }
+            return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις'));
+        },
+        relativeTime : {
+            future : 'σε %s',
+            past : '%s πριν',
+            s : 'λίγα δευτερόλεπτα',
+            m : 'ένα λεπτό',
+            mm : '%d λεπτά',
+            h : 'μία ώρα',
+            hh : '%d ώρες',
+            d : 'μία μέρα',
+            dd : '%d μέρες',
+            M : 'ένας μήνας',
+            MM : '%d μήνες',
+            y : 'ένας χρόνος',
+            yy : '%d χρόνια'
+        },
+        ordinalParse: /\d{1,2}η/,
+        ordinal: '%dη',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : australian english (en-au)
+
+    var en_au = moment__default.defineLocale('en-au', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY h:mm A',
+            LLLL : 'dddd, D MMMM YYYY h:mm A'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : canadian english (en-ca)
+    //! author : Jonathan Abourbih : https://github.com/jonbca
+
+    var en_ca = moment__default.defineLocale('en-ca', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
+            L : 'YYYY-MM-DD',
+            LL : 'MMMM D, YYYY',
+            LLL : 'MMMM D, YYYY h:mm A',
+            LLLL : 'dddd, MMMM D, YYYY h:mm A'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : great britain english (en-gb)
+    //! author : Chris Gedrim : https://github.com/chrisgedrim
+
+    var en_gb = moment__default.defineLocale('en-gb', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Irish english (en-ie)
+    //! author : Chris Cartlidge : https://github.com/chriscartlidge
+
+    var en_ie = moment__default.defineLocale('en-ie', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD-MM-YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : New Zealand english (en-nz)
+
+    var en_nz = moment__default.defineLocale('en-nz', {
+        months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+        weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+        weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+        weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY h:mm A',
+            LLLL : 'dddd, D MMMM YYYY h:mm A'
+        },
+        calendar : {
+            sameDay : '[Today at] LT',
+            nextDay : '[Tomorrow at] LT',
+            nextWeek : 'dddd [at] LT',
+            lastDay : '[Yesterday at] LT',
+            lastWeek : '[Last] dddd [at] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'in %s',
+            past : '%s ago',
+            s : 'a few seconds',
+            m : 'a minute',
+            mm : '%d minutes',
+            h : 'an hour',
+            hh : '%d hours',
+            d : 'a day',
+            dd : '%d days',
+            M : 'a month',
+            MM : '%d months',
+            y : 'a year',
+            yy : '%d years'
+        },
+        ordinalParse: /\d{1,2}(st|nd|rd|th)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : esperanto (eo)
+    //! author : Colin Dean : https://github.com/colindean
+    //! komento: Mi estas malcerta se mi korekte traktis akuzativojn en tiu traduko.
+    //!          Se ne, bonvolu korekti kaj avizi min por ke mi povas lerni!
+
+    var eo = moment__default.defineLocale('eo', {
+        months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'),
+        weekdays : 'Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato'.split('_'),
+        weekdaysShort : 'Dim_Lun_Mard_Merk_Ĵaŭ_Ven_Sab'.split('_'),
+        weekdaysMin : 'Di_Lu_Ma_Me_Ĵa_Ve_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'YYYY-MM-DD',
+            LL : 'D[-an de] MMMM, YYYY',
+            LLL : 'D[-an de] MMMM, YYYY HH:mm',
+            LLLL : 'dddd, [la] D[-an de] MMMM, YYYY HH:mm'
+        },
+        meridiemParse: /[ap]\.t\.m/i,
+        isPM: function (input) {
+            return input.charAt(0).toLowerCase() === 'p';
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'p.t.m.' : 'P.T.M.';
+            } else {
+                return isLower ? 'a.t.m.' : 'A.T.M.';
+            }
+        },
+        calendar : {
+            sameDay : '[Hodiaŭ je] LT',
+            nextDay : '[Morgaŭ je] LT',
+            nextWeek : 'dddd [je] LT',
+            lastDay : '[Hieraŭ je] LT',
+            lastWeek : '[pasinta] dddd [je] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'je %s',
+            past : 'antaŭ %s',
+            s : 'sekundoj',
+            m : 'minuto',
+            mm : '%d minutoj',
+            h : 'horo',
+            hh : '%d horoj',
+            d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo
+            dd : '%d tagoj',
+            M : 'monato',
+            MM : '%d monatoj',
+            y : 'jaro',
+            yy : '%d jaroj'
+        },
+        ordinalParse: /\d{1,2}a/,
+        ordinal : '%da',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : spanish (es)
+    //! author : Julio Napurí : https://github.com/julionc
+
+    var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_'),
+        es__monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
+
+    var es = moment__default.defineLocale('es', {
+        months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
+        monthsShort : function (m, format) {
+            if (/-MMM-/.test(format)) {
+                return es__monthsShort[m.month()];
+            } else {
+                return monthsShortDot[m.month()];
+            }
+        },
+        monthsParseExact : true,
+        weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
+        weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
+        weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D [de] MMMM [de] YYYY',
+            LLL : 'D [de] MMMM [de] YYYY H:mm',
+            LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
+        },
+        calendar : {
+            sameDay : function () {
+                return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            nextDay : function () {
+                return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            lastDay : function () {
+                return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            lastWeek : function () {
+                return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'en %s',
+            past : 'hace %s',
+            s : 'unos segundos',
+            m : 'un minuto',
+            mm : '%d minutos',
+            h : 'una hora',
+            hh : '%d horas',
+            d : 'un día',
+            dd : '%d días',
+            M : 'un mes',
+            MM : '%d meses',
+            y : 'un año',
+            yy : '%d años'
+        },
+        ordinalParse : /\d{1,2}º/,
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : estonian (et)
+    //! author : Henry Kehlmann : https://github.com/madhenry
+    //! improvements : Illimar Tambek : https://github.com/ragulka
+
+    function et__processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
+            'm' : ['ühe minuti', 'üks minut'],
+            'mm': [number + ' minuti', number + ' minutit'],
+            'h' : ['ühe tunni', 'tund aega', 'üks tund'],
+            'hh': [number + ' tunni', number + ' tundi'],
+            'd' : ['ühe päeva', 'üks päev'],
+            'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
+            'MM': [number + ' kuu', number + ' kuud'],
+            'y' : ['ühe aasta', 'aasta', 'üks aasta'],
+            'yy': [number + ' aasta', number + ' aastat']
+        };
+        if (withoutSuffix) {
+            return format[key][2] ? format[key][2] : format[key][1];
+        }
+        return isFuture ? format[key][0] : format[key][1];
+    }
+
+    var et = moment__default.defineLocale('et', {
+        months        : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'),
+        monthsShort   : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'),
+        weekdays      : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'),
+        weekdaysShort : 'P_E_T_K_N_R_L'.split('_'),
+        weekdaysMin   : 'P_E_T_K_N_R_L'.split('_'),
+        longDateFormat : {
+            LT   : 'H:mm',
+            LTS : 'H:mm:ss',
+            L    : 'DD.MM.YYYY',
+            LL   : 'D. MMMM YYYY',
+            LLL  : 'D. MMMM YYYY H:mm',
+            LLLL : 'dddd, D. MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay  : '[Täna,] LT',
+            nextDay  : '[Homme,] LT',
+            nextWeek : '[Järgmine] dddd LT',
+            lastDay  : '[Eile,] LT',
+            lastWeek : '[Eelmine] dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s pärast',
+            past   : '%s tagasi',
+            s      : et__processRelativeTime,
+            m      : et__processRelativeTime,
+            mm     : et__processRelativeTime,
+            h      : et__processRelativeTime,
+            hh     : et__processRelativeTime,
+            d      : et__processRelativeTime,
+            dd     : '%d päeva',
+            M      : et__processRelativeTime,
+            MM     : et__processRelativeTime,
+            y      : et__processRelativeTime,
+            yy     : et__processRelativeTime
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : euskara (eu)
+    //! author : Eneko Illarramendi : https://github.com/eillarra
+
+    var eu = moment__default.defineLocale('eu', {
+        months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
+        monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
+        weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'),
+        weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'YYYY-MM-DD',
+            LL : 'YYYY[ko] MMMM[ren] D[a]',
+            LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm',
+            LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
+            l : 'YYYY-M-D',
+            ll : 'YYYY[ko] MMM D[a]',
+            lll : 'YYYY[ko] MMM D[a] HH:mm',
+            llll : 'ddd, YYYY[ko] MMM D[a] HH:mm'
+        },
+        calendar : {
+            sameDay : '[gaur] LT[etan]',
+            nextDay : '[bihar] LT[etan]',
+            nextWeek : 'dddd LT[etan]',
+            lastDay : '[atzo] LT[etan]',
+            lastWeek : '[aurreko] dddd LT[etan]',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s barru',
+            past : 'duela %s',
+            s : 'segundo batzuk',
+            m : 'minutu bat',
+            mm : '%d minutu',
+            h : 'ordu bat',
+            hh : '%d ordu',
+            d : 'egun bat',
+            dd : '%d egun',
+            M : 'hilabete bat',
+            MM : '%d hilabete',
+            y : 'urte bat',
+            yy : '%d urte'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Persian (fa)
+    //! author : Ebrahim Byagowi : https://github.com/ebraminio
+
+    var fa__symbolMap = {
+        '1': '۱',
+        '2': '۲',
+        '3': '۳',
+        '4': '۴',
+        '5': '۵',
+        '6': '۶',
+        '7': '۷',
+        '8': '۸',
+        '9': '۹',
+        '0': '۰'
+    }, fa__numberMap = {
+        '۱': '1',
+        '۲': '2',
+        '۳': '3',
+        '۴': '4',
+        '۵': '5',
+        '۶': '6',
+        '۷': '7',
+        '۸': '8',
+        '۹': '9',
+        '۰': '0'
+    };
+
+    var fa = moment__default.defineLocale('fa', {
+        months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+        monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+        weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+        weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+        weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        meridiemParse: /قبل از ظهر|بعد از ظهر/,
+        isPM: function (input) {
+            return /بعد از ظهر/.test(input);
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'قبل از ظهر';
+            } else {
+                return 'بعد از ظهر';
+            }
+        },
+        calendar : {
+            sameDay : '[امروز ساعت] LT',
+            nextDay : '[فردا ساعت] LT',
+            nextWeek : 'dddd [ساعت] LT',
+            lastDay : '[دیروز ساعت] LT',
+            lastWeek : 'dddd [پیش] [ساعت] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'در %s',
+            past : '%s پیش',
+            s : 'چندین ثانیه',
+            m : 'یک دقیقه',
+            mm : '%d دقیقه',
+            h : 'یک ساعت',
+            hh : '%d ساعت',
+            d : 'یک روز',
+            dd : '%d روز',
+            M : 'یک ماه',
+            MM : '%d ماه',
+            y : 'یک سال',
+            yy : '%d سال'
+        },
+        preparse: function (string) {
+            return string.replace(/[۰-۹]/g, function (match) {
+                return fa__numberMap[match];
+            }).replace(/،/g, ',');
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return fa__symbolMap[match];
+            }).replace(/,/g, '،');
+        },
+        ordinalParse: /\d{1,2}م/,
+        ordinal : '%dم',
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12 // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : finnish (fi)
+    //! author : Tarmo Aidantausta : https://github.com/bleadof
+
+    var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' '),
+        numbersFuture = [
+            'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
+            numbersPast[7], numbersPast[8], numbersPast[9]
+        ];
+    function fi__translate(number, withoutSuffix, key, isFuture) {
+        var result = '';
+        switch (key) {
+        case 's':
+            return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
+        case 'm':
+            return isFuture ? 'minuutin' : 'minuutti';
+        case 'mm':
+            result = isFuture ? 'minuutin' : 'minuuttia';
+            break;
+        case 'h':
+            return isFuture ? 'tunnin' : 'tunti';
+        case 'hh':
+            result = isFuture ? 'tunnin' : 'tuntia';
+            break;
+        case 'd':
+            return isFuture ? 'päivän' : 'päivä';
+        case 'dd':
+            result = isFuture ? 'päivän' : 'päivää';
+            break;
+        case 'M':
+            return isFuture ? 'kuukauden' : 'kuukausi';
+        case 'MM':
+            result = isFuture ? 'kuukauden' : 'kuukautta';
+            break;
+        case 'y':
+            return isFuture ? 'vuoden' : 'vuosi';
+        case 'yy':
+            result = isFuture ? 'vuoden' : 'vuotta';
+            break;
+        }
+        result = verbalNumber(number, isFuture) + ' ' + result;
+        return result;
+    }
+    function verbalNumber(number, isFuture) {
+        return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
+    }
+
+    var fi = moment__default.defineLocale('fi', {
+        months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'),
+        monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
+        weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
+        weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'),
+        weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            LTS : 'HH.mm.ss',
+            L : 'DD.MM.YYYY',
+            LL : 'Do MMMM[ta] YYYY',
+            LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm',
+            LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm',
+            l : 'D.M.YYYY',
+            ll : 'Do MMM YYYY',
+            lll : 'Do MMM YYYY, [klo] HH.mm',
+            llll : 'ddd, Do MMM YYYY, [klo] HH.mm'
+        },
+        calendar : {
+            sameDay : '[tänään] [klo] LT',
+            nextDay : '[huomenna] [klo] LT',
+            nextWeek : 'dddd [klo] LT',
+            lastDay : '[eilen] [klo] LT',
+            lastWeek : '[viime] dddd[na] [klo] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s päästä',
+            past : '%s sitten',
+            s : fi__translate,
+            m : fi__translate,
+            mm : fi__translate,
+            h : fi__translate,
+            hh : fi__translate,
+            d : fi__translate,
+            dd : fi__translate,
+            M : fi__translate,
+            MM : fi__translate,
+            y : fi__translate,
+            yy : fi__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : faroese (fo)
+    //! author : Ragnar Johannesen : https://github.com/ragnar123
+
+    var fo = moment__default.defineLocale('fo', {
+        months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+        weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'),
+        weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'),
+        weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D. MMMM, YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[Í dag kl.] LT',
+            nextDay : '[Í morgin kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[Í gjár kl.] LT',
+            lastWeek : '[síðstu] dddd [kl] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'um %s',
+            past : '%s síðani',
+            s : 'fá sekund',
+            m : 'ein minutt',
+            mm : '%d minuttir',
+            h : 'ein tími',
+            hh : '%d tímar',
+            d : 'ein dagur',
+            dd : '%d dagar',
+            M : 'ein mánaði',
+            MM : '%d mánaðir',
+            y : 'eitt ár',
+            yy : '%d ár'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : canadian french (fr-ca)
+    //! author : Jonathan Abourbih : https://github.com/jonbca
+
+    var fr_ca = moment__default.defineLocale('fr-ca', {
+        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'YYYY-MM-DD',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Aujourd\'hui à] LT',
+            nextDay: '[Demain à] LT',
+            nextWeek: 'dddd [à] LT',
+            lastDay: '[Hier à] LT',
+            lastWeek: 'dddd [dernier à] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'dans %s',
+            past : 'il y a %s',
+            s : 'quelques secondes',
+            m : 'une minute',
+            mm : '%d minutes',
+            h : 'une heure',
+            hh : '%d heures',
+            d : 'un jour',
+            dd : '%d jours',
+            M : 'un mois',
+            MM : '%d mois',
+            y : 'un an',
+            yy : '%d ans'
+        },
+        ordinalParse: /\d{1,2}(er|e)/,
+        ordinal : function (number) {
+            return number + (number === 1 ? 'er' : 'e');
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : swiss french (fr)
+    //! author : Gaspard Bucher : https://github.com/gaspard
+
+    var fr_ch = moment__default.defineLocale('fr-ch', {
+        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Aujourd\'hui à] LT',
+            nextDay: '[Demain à] LT',
+            nextWeek: 'dddd [à] LT',
+            lastDay: '[Hier à] LT',
+            lastWeek: 'dddd [dernier à] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'dans %s',
+            past : 'il y a %s',
+            s : 'quelques secondes',
+            m : 'une minute',
+            mm : '%d minutes',
+            h : 'une heure',
+            hh : '%d heures',
+            d : 'un jour',
+            dd : '%d jours',
+            M : 'un mois',
+            MM : '%d mois',
+            y : 'un an',
+            yy : '%d ans'
+        },
+        ordinalParse: /\d{1,2}(er|e)/,
+        ordinal : function (number) {
+            return number + (number === 1 ? 'er' : 'e');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : french (fr)
+    //! author : John Fischer : https://github.com/jfroffice
+
+    var fr = moment__default.defineLocale('fr', {
+        months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+        monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+        weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+        weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Aujourd\'hui à] LT',
+            nextDay: '[Demain à] LT',
+            nextWeek: 'dddd [à] LT',
+            lastDay: '[Hier à] LT',
+            lastWeek: 'dddd [dernier à] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'dans %s',
+            past : 'il y a %s',
+            s : 'quelques secondes',
+            m : 'une minute',
+            mm : '%d minutes',
+            h : 'une heure',
+            hh : '%d heures',
+            d : 'un jour',
+            dd : '%d jours',
+            M : 'un mois',
+            MM : '%d mois',
+            y : 'un an',
+            yy : '%d ans'
+        },
+        ordinalParse: /\d{1,2}(er|)/,
+        ordinal : function (number) {
+            return number + (number === 1 ? 'er' : '');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : frisian (fy)
+    //! author : Robin van der Vliet : https://github.com/robin0van0der0v
+
+    var fy__monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_'),
+        fy__monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_');
+
+    var fy = moment__default.defineLocale('fy', {
+        months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'),
+        monthsShort : function (m, format) {
+            if (/-MMM-/.test(format)) {
+                return fy__monthsShortWithoutDots[m.month()];
+            } else {
+                return fy__monthsShortWithDots[m.month()];
+            }
+        },
+        monthsParseExact : true,
+        weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'),
+        weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'),
+        weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD-MM-YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[hjoed om] LT',
+            nextDay: '[moarn om] LT',
+            nextWeek: 'dddd [om] LT',
+            lastDay: '[juster om] LT',
+            lastWeek: '[ôfrûne] dddd [om] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'oer %s',
+            past : '%s lyn',
+            s : 'in pear sekonden',
+            m : 'ien minút',
+            mm : '%d minuten',
+            h : 'ien oere',
+            hh : '%d oeren',
+            d : 'ien dei',
+            dd : '%d dagen',
+            M : 'ien moanne',
+            MM : '%d moannen',
+            y : 'ien jier',
+            yy : '%d jierren'
+        },
+        ordinalParse: /\d{1,2}(ste|de)/,
+        ordinal : function (number) {
+            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : great britain scottish gealic (gd)
+    //! author : Jon Ashdown : https://github.com/jonashdown
+
+    var gd__months = [
+        'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'
+    ];
+
+    var gd__monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'];
+
+    var gd__weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'];
+
+    var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'];
+
+    var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];
+
+    var gd = moment__default.defineLocale('gd', {
+        months : gd__months,
+        monthsShort : gd__monthsShort,
+        monthsParseExact : true,
+        weekdays : gd__weekdays,
+        weekdaysShort : weekdaysShort,
+        weekdaysMin : weekdaysMin,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[An-diugh aig] LT',
+            nextDay : '[A-màireach aig] LT',
+            nextWeek : 'dddd [aig] LT',
+            lastDay : '[An-dè aig] LT',
+            lastWeek : 'dddd [seo chaidh] [aig] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'ann an %s',
+            past : 'bho chionn %s',
+            s : 'beagan diogan',
+            m : 'mionaid',
+            mm : '%d mionaidean',
+            h : 'uair',
+            hh : '%d uairean',
+            d : 'latha',
+            dd : '%d latha',
+            M : 'mìos',
+            MM : '%d mìosan',
+            y : 'bliadhna',
+            yy : '%d bliadhna'
+        },
+        ordinalParse : /\d{1,2}(d|na|mh)/,
+        ordinal : function (number) {
+            var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : galician (gl)
+    //! author : Juan G. Hurtado : https://github.com/juanghurtado
+
+    var gl = moment__default.defineLocale('gl', {
+        months : 'Xaneiro_Febreiro_Marzo_Abril_Maio_Xuño_Xullo_Agosto_Setembro_Outubro_Novembro_Decembro'.split('_'),
+        monthsShort : 'Xan._Feb._Mar._Abr._Mai._Xuñ._Xul._Ago._Set._Out._Nov._Dec.'.split('_'),
+        monthsParseExact: true,
+        weekdays : 'Domingo_Luns_Martes_Mércores_Xoves_Venres_Sábado'.split('_'),
+        weekdaysShort : 'Dom._Lun._Mar._Mér._Xov._Ven._Sáb.'.split('_'),
+        weekdaysMin : 'Do_Lu_Ma_Mé_Xo_Ve_Sá'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY H:mm',
+            LLLL : 'dddd D MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay : function () {
+                return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+            },
+            nextDay : function () {
+                return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+            },
+            nextWeek : function () {
+                return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+            },
+            lastDay : function () {
+                return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
+            },
+            lastWeek : function () {
+                return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : function (str) {
+                if (str === 'uns segundos') {
+                    return 'nuns segundos';
+                }
+                return 'en ' + str;
+            },
+            past : 'hai %s',
+            s : 'uns segundos',
+            m : 'un minuto',
+            mm : '%d minutos',
+            h : 'unha hora',
+            hh : '%d horas',
+            d : 'un día',
+            dd : '%d días',
+            M : 'un mes',
+            MM : '%d meses',
+            y : 'un ano',
+            yy : '%d anos'
+        },
+        ordinalParse : /\d{1,2}º/,
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Hebrew (he)
+    //! author : Tomer Cohen : https://github.com/tomer
+    //! author : Moshe Simantov : https://github.com/DevelopmentIL
+    //! author : Tal Ater : https://github.com/TalAter
+
+    var he = moment__default.defineLocale('he', {
+        months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'),
+        monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'),
+        weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
+        weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
+        weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D [ב]MMMM YYYY',
+            LLL : 'D [ב]MMMM YYYY HH:mm',
+            LLLL : 'dddd, D [ב]MMMM YYYY HH:mm',
+            l : 'D/M/YYYY',
+            ll : 'D MMM YYYY',
+            lll : 'D MMM YYYY HH:mm',
+            llll : 'ddd, D MMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[היום ב־]LT',
+            nextDay : '[מחר ב־]LT',
+            nextWeek : 'dddd [בשעה] LT',
+            lastDay : '[אתמול ב־]LT',
+            lastWeek : '[ביום] dddd [האחרון בשעה] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'בעוד %s',
+            past : 'לפני %s',
+            s : 'מספר שניות',
+            m : 'דקה',
+            mm : '%d דקות',
+            h : 'שעה',
+            hh : function (number) {
+                if (number === 2) {
+                    return 'שעתיים';
+                }
+                return number + ' שעות';
+            },
+            d : 'יום',
+            dd : function (number) {
+                if (number === 2) {
+                    return 'יומיים';
+                }
+                return number + ' ימים';
+            },
+            M : 'חודש',
+            MM : function (number) {
+                if (number === 2) {
+                    return 'חודשיים';
+                }
+                return number + ' חודשים';
+            },
+            y : 'שנה',
+            yy : function (number) {
+                if (number === 2) {
+                    return 'שנתיים';
+                } else if (number % 10 === 0 && number !== 10) {
+                    return number + ' שנה';
+                }
+                return number + ' שנים';
+            }
+        },
+        meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,
+        isPM : function (input) {
+            return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input);
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 5) {
+                return 'לפנות בוקר';
+            } else if (hour < 10) {
+                return 'בבוקר';
+            } else if (hour < 12) {
+                return isLower ? 'לפנה"צ' : 'לפני הצהריים';
+            } else if (hour < 18) {
+                return isLower ? 'אחה"צ' : 'אחרי הצהריים';
+            } else {
+                return 'בערב';
+            }
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : hindi (hi)
+    //! author : Mayank Singhal : https://github.com/mayanksinghal
+
+    var hi__symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    hi__numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    var hi = moment__default.defineLocale('hi', {
+        months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'),
+        monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'),
+        monthsParseExact: true,
+        weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+        weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'),
+        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm बजे',
+            LTS : 'A h:mm:ss बजे',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, A h:mm बजे',
+            LLLL : 'dddd, D MMMM YYYY, A h:mm बजे'
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[कल] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[कल] LT',
+            lastWeek : '[पिछले] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s में',
+            past : '%s पहले',
+            s : 'कुछ ही क्षण',
+            m : 'एक मिनट',
+            mm : '%d मिनट',
+            h : 'एक घंटा',
+            hh : '%d घंटे',
+            d : 'एक दिन',
+            dd : '%d दिन',
+            M : 'एक महीने',
+            MM : '%d महीने',
+            y : 'एक वर्ष',
+            yy : '%d वर्ष'
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return hi__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return hi__symbolMap[match];
+            });
+        },
+        // Hindi notation for meridiems are quite fuzzy in practice. While there exists
+        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
+        meridiemParse: /रात|सुबह|दोपहर|शाम/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'रात') {
+                return hour < 4 ? hour : hour + 12;
+            } else if (meridiem === 'सुबह') {
+                return hour;
+            } else if (meridiem === 'दोपहर') {
+                return hour >= 10 ? hour : hour + 12;
+            } else if (meridiem === 'शाम') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'रात';
+            } else if (hour < 10) {
+                return 'सुबह';
+            } else if (hour < 17) {
+                return 'दोपहर';
+            } else if (hour < 20) {
+                return 'शाम';
+            } else {
+                return 'रात';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : hrvatski (hr)
+    //! author : Bojan Marković : https://github.com/bmarkovic
+
+    function hr__translate(number, withoutSuffix, key) {
+        var result = number + ' ';
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+        case 'mm':
+            if (number === 1) {
+                result += 'minuta';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'minute';
+            } else {
+                result += 'minuta';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'jedan sat' : 'jednog sata';
+        case 'hh':
+            if (number === 1) {
+                result += 'sat';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'sata';
+            } else {
+                result += 'sati';
+            }
+            return result;
+        case 'dd':
+            if (number === 1) {
+                result += 'dan';
+            } else {
+                result += 'dana';
+            }
+            return result;
+        case 'MM':
+            if (number === 1) {
+                result += 'mjesec';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'mjeseca';
+            } else {
+                result += 'mjeseci';
+            }
+            return result;
+        case 'yy':
+            if (number === 1) {
+                result += 'godina';
+            } else if (number === 2 || number === 3 || number === 4) {
+                result += 'godine';
+            } else {
+                result += 'godina';
+            }
+            return result;
+        }
+    }
+
+    var hr = moment__default.defineLocale('hr', {
+        months : {
+            format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'),
+            standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_')
+        },
+        monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'),
+        monthsParseExact: true,
+        weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+        weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+        weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD. MM. YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY H:mm',
+            LLLL : 'dddd, D. MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay  : '[danas u] LT',
+            nextDay  : '[sutra u] LT',
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[jučer u] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                    return '[prošlu] dddd [u] LT';
+                case 6:
+                    return '[prošle] [subote] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prošli] dddd [u] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past   : 'prije %s',
+            s      : 'par sekundi',
+            m      : hr__translate,
+            mm     : hr__translate,
+            h      : hr__translate,
+            hh     : hr__translate,
+            d      : 'dan',
+            dd     : hr__translate,
+            M      : 'mjesec',
+            MM     : hr__translate,
+            y      : 'godinu',
+            yy     : hr__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : hungarian (hu)
+    //! author : Adam Brunner : https://github.com/adambrunner
+
+    var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
+    function hu__translate(number, withoutSuffix, key, isFuture) {
+        var num = number,
+            suffix;
+        switch (key) {
+        case 's':
+            return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
+        case 'm':
+            return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
+        case 'mm':
+            return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
+        case 'h':
+            return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
+        case 'hh':
+            return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
+        case 'd':
+            return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
+        case 'dd':
+            return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
+        case 'M':
+            return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+        case 'MM':
+            return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+        case 'y':
+            return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
+        case 'yy':
+            return num + (isFuture || withoutSuffix ? ' év' : ' éve');
+        }
+        return '';
+    }
+    function week(isFuture) {
+        return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
+    }
+
+    var hu = moment__default.defineLocale('hu', {
+        months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'),
+        monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'),
+        weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
+        weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
+        weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'YYYY.MM.DD.',
+            LL : 'YYYY. MMMM D.',
+            LLL : 'YYYY. MMMM D. H:mm',
+            LLLL : 'YYYY. MMMM D., dddd H:mm'
+        },
+        meridiemParse: /de|du/i,
+        isPM: function (input) {
+            return input.charAt(1).toLowerCase() === 'u';
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 12) {
+                return isLower === true ? 'de' : 'DE';
+            } else {
+                return isLower === true ? 'du' : 'DU';
+            }
+        },
+        calendar : {
+            sameDay : '[ma] LT[-kor]',
+            nextDay : '[holnap] LT[-kor]',
+            nextWeek : function () {
+                return week.call(this, true);
+            },
+            lastDay : '[tegnap] LT[-kor]',
+            lastWeek : function () {
+                return week.call(this, false);
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s múlva',
+            past : '%s',
+            s : hu__translate,
+            m : hu__translate,
+            mm : hu__translate,
+            h : hu__translate,
+            hh : hu__translate,
+            d : hu__translate,
+            dd : hu__translate,
+            M : hu__translate,
+            MM : hu__translate,
+            y : hu__translate,
+            yy : hu__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Armenian (hy-am)
+    //! author : Armendarabyan : https://github.com/armendarabyan
+
+    var hy_am = moment__default.defineLocale('hy-am', {
+        months : {
+            format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'),
+            standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_')
+        },
+        monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'),
+        weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'),
+        weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+        weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY թ.',
+            LLL : 'D MMMM YYYY թ., HH:mm',
+            LLLL : 'dddd, D MMMM YYYY թ., HH:mm'
+        },
+        calendar : {
+            sameDay: '[այսօր] LT',
+            nextDay: '[վաղը] LT',
+            lastDay: '[երեկ] LT',
+            nextWeek: function () {
+                return 'dddd [օրը ժամը] LT';
+            },
+            lastWeek: function () {
+                return '[անցած] dddd [օրը ժամը] LT';
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : '%s հետո',
+            past : '%s առաջ',
+            s : 'մի քանի վայրկյան',
+            m : 'րոպե',
+            mm : '%d րոպե',
+            h : 'ժամ',
+            hh : '%d ժամ',
+            d : 'օր',
+            dd : '%d օր',
+            M : 'ամիս',
+            MM : '%d ամիս',
+            y : 'տարի',
+            yy : '%d տարի'
+        },
+        meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,
+        isPM: function (input) {
+            return /^(ցերեկվա|երեկոյան)$/.test(input);
+        },
+        meridiem : function (hour) {
+            if (hour < 4) {
+                return 'գիշերվա';
+            } else if (hour < 12) {
+                return 'առավոտվա';
+            } else if (hour < 17) {
+                return 'ցերեկվա';
+            } else {
+                return 'երեկոյան';
+            }
+        },
+        ordinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/,
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'DDD':
+            case 'w':
+            case 'W':
+            case 'DDDo':
+                if (number === 1) {
+                    return number + '-ին';
+                }
+                return number + '-րդ';
+            default:
+                return number;
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Bahasa Indonesia (id)
+    //! author : Mohammad Satrio Utomo : https://github.com/tyok
+    //! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
+
+    var id = moment__default.defineLocale('id', {
+        months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'),
+        weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
+        weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
+        weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            LTS : 'HH.mm.ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY [pukul] HH.mm',
+            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+        },
+        meridiemParse: /pagi|siang|sore|malam/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'pagi') {
+                return hour;
+            } else if (meridiem === 'siang') {
+                return hour >= 11 ? hour : hour + 12;
+            } else if (meridiem === 'sore' || meridiem === 'malam') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'pagi';
+            } else if (hours < 15) {
+                return 'siang';
+            } else if (hours < 19) {
+                return 'sore';
+            } else {
+                return 'malam';
+            }
+        },
+        calendar : {
+            sameDay : '[Hari ini pukul] LT',
+            nextDay : '[Besok pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kemarin pukul] LT',
+            lastWeek : 'dddd [lalu pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'dalam %s',
+            past : '%s yang lalu',
+            s : 'beberapa detik',
+            m : 'semenit',
+            mm : '%d menit',
+            h : 'sejam',
+            hh : '%d jam',
+            d : 'sehari',
+            dd : '%d hari',
+            M : 'sebulan',
+            MM : '%d bulan',
+            y : 'setahun',
+            yy : '%d tahun'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : icelandic (is)
+    //! author : Hinrik Örn Sigurðsson : https://github.com/hinrik
+
+    function is__plural(n) {
+        if (n % 100 === 11) {
+            return true;
+        } else if (n % 10 === 1) {
+            return false;
+        }
+        return true;
+    }
+    function is__translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        switch (key) {
+        case 's':
+            return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
+        case 'm':
+            return withoutSuffix ? 'mínúta' : 'mínútu';
+        case 'mm':
+            if (is__plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
+            } else if (withoutSuffix) {
+                return result + 'mínúta';
+            }
+            return result + 'mínútu';
+        case 'hh':
+            if (is__plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
+            }
+            return result + 'klukkustund';
+        case 'd':
+            if (withoutSuffix) {
+                return 'dagur';
+            }
+            return isFuture ? 'dag' : 'degi';
+        case 'dd':
+            if (is__plural(number)) {
+                if (withoutSuffix) {
+                    return result + 'dagar';
+                }
+                return result + (isFuture ? 'daga' : 'dögum');
+            } else if (withoutSuffix) {
+                return result + 'dagur';
+            }
+            return result + (isFuture ? 'dag' : 'degi');
+        case 'M':
+            if (withoutSuffix) {
+                return 'mánuður';
+            }
+            return isFuture ? 'mánuð' : 'mánuði';
+        case 'MM':
+            if (is__plural(number)) {
+                if (withoutSuffix) {
+                    return result + 'mánuðir';
+                }
+                return result + (isFuture ? 'mánuði' : 'mánuðum');
+            } else if (withoutSuffix) {
+                return result + 'mánuður';
+            }
+            return result + (isFuture ? 'mánuð' : 'mánuði');
+        case 'y':
+            return withoutSuffix || isFuture ? 'ár' : 'ári';
+        case 'yy':
+            if (is__plural(number)) {
+                return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
+            }
+            return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
+        }
+    }
+
+    var is = moment__default.defineLocale('is', {
+        months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'),
+        weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'),
+        weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'),
+        weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY [kl.] H:mm',
+            LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm'
+        },
+        calendar : {
+            sameDay : '[í dag kl.] LT',
+            nextDay : '[á morgun kl.] LT',
+            nextWeek : 'dddd [kl.] LT',
+            lastDay : '[í gær kl.] LT',
+            lastWeek : '[síðasta] dddd [kl.] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'eftir %s',
+            past : 'fyrir %s síðan',
+            s : is__translate,
+            m : is__translate,
+            mm : is__translate,
+            h : 'klukkustund',
+            hh : is__translate,
+            d : is__translate,
+            dd : is__translate,
+            M : is__translate,
+            MM : is__translate,
+            y : is__translate,
+            yy : is__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : italian (it)
+    //! author : Lorenzo : https://github.com/aliem
+    //! author: Mattia Larentis: https://github.com/nostalgiaz
+
+    var it = moment__default.defineLocale('it', {
+        months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'),
+        monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
+        weekdays : 'Domenica_Lunedì_Martedì_Mercoledì_Giovedì_Venerdì_Sabato'.split('_'),
+        weekdaysShort : 'Dom_Lun_Mar_Mer_Gio_Ven_Sab'.split('_'),
+        weekdaysMin : 'Do_Lu_Ma_Me_Gi_Ve_Sa'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Oggi alle] LT',
+            nextDay: '[Domani alle] LT',
+            nextWeek: 'dddd [alle] LT',
+            lastDay: '[Ieri alle] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                    case 0:
+                        return '[la scorsa] dddd [alle] LT';
+                    default:
+                        return '[lo scorso] dddd [alle] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : function (s) {
+                return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s;
+            },
+            past : '%s fa',
+            s : 'alcuni secondi',
+            m : 'un minuto',
+            mm : '%d minuti',
+            h : 'un\'ora',
+            hh : '%d ore',
+            d : 'un giorno',
+            dd : '%d giorni',
+            M : 'un mese',
+            MM : '%d mesi',
+            y : 'un anno',
+            yy : '%d anni'
+        },
+        ordinalParse : /\d{1,2}º/,
+        ordinal: '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : japanese (ja)
+    //! author : LI Long : https://github.com/baryon
+
+    var ja = moment__default.defineLocale('ja', {
+        months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
+        weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
+        weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
+        longDateFormat : {
+            LT : 'Ah時m分',
+            LTS : 'Ah時m分s秒',
+            L : 'YYYY/MM/DD',
+            LL : 'YYYY年M月D日',
+            LLL : 'YYYY年M月D日Ah時m分',
+            LLLL : 'YYYY年M月D日Ah時m分 dddd'
+        },
+        meridiemParse: /午前|午後/i,
+        isPM : function (input) {
+            return input === '午後';
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return '午前';
+            } else {
+                return '午後';
+            }
+        },
+        calendar : {
+            sameDay : '[今日] LT',
+            nextDay : '[明日] LT',
+            nextWeek : '[来週]dddd LT',
+            lastDay : '[昨日] LT',
+            lastWeek : '[前週]dddd LT',
+            sameElse : 'L'
+        },
+        ordinalParse : /\d{1,2}日/,
+        ordinal : function (number, period) {
+            switch (period) {
+            case 'd':
+            case 'D':
+            case 'DDD':
+                return number + '日';
+            default:
+                return number;
+            }
+        },
+        relativeTime : {
+            future : '%s後',
+            past : '%s前',
+            s : '数秒',
+            m : '1分',
+            mm : '%d分',
+            h : '1時間',
+            hh : '%d時間',
+            d : '1日',
+            dd : '%d日',
+            M : '1ヶ月',
+            MM : '%dヶ月',
+            y : '1年',
+            yy : '%d年'
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Boso Jowo (jv)
+    //! author : Rony Lantip : https://github.com/lantip
+    //! reference: http://jv.wikipedia.org/wiki/Basa_Jawa
+
+    var jv = moment__default.defineLocale('jv', {
+        months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'),
+        monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'),
+        weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'),
+        weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'),
+        weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            LTS : 'HH.mm.ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY [pukul] HH.mm',
+            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+        },
+        meridiemParse: /enjing|siyang|sonten|ndalu/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'enjing') {
+                return hour;
+            } else if (meridiem === 'siyang') {
+                return hour >= 11 ? hour : hour + 12;
+            } else if (meridiem === 'sonten' || meridiem === 'ndalu') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'enjing';
+            } else if (hours < 15) {
+                return 'siyang';
+            } else if (hours < 19) {
+                return 'sonten';
+            } else {
+                return 'ndalu';
+            }
+        },
+        calendar : {
+            sameDay : '[Dinten puniko pukul] LT',
+            nextDay : '[Mbenjang pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kala wingi pukul] LT',
+            lastWeek : 'dddd [kepengker pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'wonten ing %s',
+            past : '%s ingkang kepengker',
+            s : 'sawetawis detik',
+            m : 'setunggal menit',
+            mm : '%d menit',
+            h : 'setunggal jam',
+            hh : '%d jam',
+            d : 'sedinten',
+            dd : '%d dinten',
+            M : 'sewulan',
+            MM : '%d wulan',
+            y : 'setaun',
+            yy : '%d taun'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Georgian (ka)
+    //! author : Irakli Janiashvili : https://github.com/irakli-janiashvili
+
+    var ka = moment__default.defineLocale('ka', {
+        months : {
+            standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
+            format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
+        },
+        monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
+        weekdays : {
+            standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
+            format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'),
+            isFormat: /(წინა|შემდეგ)/
+        },
+        weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
+        weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
+        longDateFormat : {
+            LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY h:mm A',
+            LLLL : 'dddd, D MMMM YYYY h:mm A'
+        },
+        calendar : {
+            sameDay : '[დღეს] LT[-ზე]',
+            nextDay : '[ხვალ] LT[-ზე]',
+            lastDay : '[გუშინ] LT[-ზე]',
+            nextWeek : '[შემდეგ] dddd LT[-ზე]',
+            lastWeek : '[წინა] dddd LT-ზე',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : function (s) {
+                return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
+                    s.replace(/ი$/, 'ში') :
+                    s + 'ში';
+            },
+            past : function (s) {
+                if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
+                    return s.replace(/(ი|ე)$/, 'ის წინ');
+                }
+                if ((/წელი/).test(s)) {
+                    return s.replace(/წელი$/, 'წლის წინ');
+                }
+            },
+            s : 'რამდენიმე წამი',
+            m : 'წუთი',
+            mm : '%d წუთი',
+            h : 'საათი',
+            hh : '%d საათი',
+            d : 'დღე',
+            dd : '%d დღე',
+            M : 'თვე',
+            MM : '%d თვე',
+            y : 'წელი',
+            yy : '%d წელი'
+        },
+        ordinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,
+        ordinal : function (number) {
+            if (number === 0) {
+                return number;
+            }
+            if (number === 1) {
+                return number + '-ლი';
+            }
+            if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
+                return 'მე-' + number;
+            }
+            return number + '-ე';
+        },
+        week : {
+            dow : 1,
+            doy : 7
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : kazakh (kk)
+    //! authors : Nurlan Rakhimzhanov : https://github.com/nurlan
+
+    var kk__suffixes = {
+        0: '-ші',
+        1: '-ші',
+        2: '-ші',
+        3: '-ші',
+        4: '-ші',
+        5: '-ші',
+        6: '-шы',
+        7: '-ші',
+        8: '-ші',
+        9: '-шы',
+        10: '-шы',
+        20: '-шы',
+        30: '-шы',
+        40: '-шы',
+        50: '-ші',
+        60: '-шы',
+        70: '-ші',
+        80: '-ші',
+        90: '-шы',
+        100: '-ші'
+    };
+
+    var kk = moment__default.defineLocale('kk', {
+        months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'),
+        monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'),
+        weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'),
+        weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'),
+        weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[Бүгін сағат] LT',
+            nextDay : '[Ертең сағат] LT',
+            nextWeek : 'dddd [сағат] LT',
+            lastDay : '[Кеше сағат] LT',
+            lastWeek : '[Өткен аптаның] dddd [сағат] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s ішінде',
+            past : '%s бұрын',
+            s : 'бірнеше секунд',
+            m : 'бір минут',
+            mm : '%d минут',
+            h : 'бір сағат',
+            hh : '%d сағат',
+            d : 'бір күн',
+            dd : '%d күн',
+            M : 'бір ай',
+            MM : '%d ай',
+            y : 'бір жыл',
+            yy : '%d жыл'
+        },
+        ordinalParse: /\d{1,2}-(ші|шы)/,
+        ordinal : function (number) {
+            var a = number % 10,
+                b = number >= 100 ? 100 : null;
+            return number + (kk__suffixes[number] || kk__suffixes[a] || kk__suffixes[b]);
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : khmer (km)
+    //! author : Kruy Vanna : https://github.com/kruyvanna
+
+    var km = moment__default.defineLocale('km', {
+        months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+        monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+        weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+        weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+        weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+        longDateFormat: {
+            LT: 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L: 'DD/MM/YYYY',
+            LL: 'D MMMM YYYY',
+            LLL: 'D MMMM YYYY HH:mm',
+            LLLL: 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar: {
+            sameDay: '[ថ្ងៃនេះ ម៉ោង] LT',
+            nextDay: '[ស្អែក ម៉ោង] LT',
+            nextWeek: 'dddd [ម៉ោង] LT',
+            lastDay: '[ម្សិលមិញ ម៉ោង] LT',
+            lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: '%sទៀត',
+            past: '%sមុន',
+            s: 'ប៉ុន្មានវិនាទី',
+            m: 'មួយនាទី',
+            mm: '%d នាទី',
+            h: 'មួយម៉ោង',
+            hh: '%d ម៉ោង',
+            d: 'មួយថ្ងៃ',
+            dd: '%d ថ្ងៃ',
+            M: 'មួយខែ',
+            MM: '%d ខែ',
+            y: 'មួយឆ្នាំ',
+            yy: '%d ឆ្នាំ'
+        },
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4 // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : korean (ko)
+    //!
+    //! authors
+    //!
+    //! - Kyungwook, Park : https://github.com/kyungw00k
+    //! - Jeeeyul Lee <je...@gmail.com>
+
+    var ko = moment__default.defineLocale('ko', {
+        months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+        monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+        weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
+        weekdaysShort : '일_월_화_수_목_금_토'.split('_'),
+        weekdaysMin : '일_월_화_수_목_금_토'.split('_'),
+        longDateFormat : {
+            LT : 'A h시 m분',
+            LTS : 'A h시 m분 s초',
+            L : 'YYYY.MM.DD',
+            LL : 'YYYY년 MMMM D일',
+            LLL : 'YYYY년 MMMM D일 A h시 m분',
+            LLLL : 'YYYY년 MMMM D일 dddd A h시 m분'
+        },
+        calendar : {
+            sameDay : '오늘 LT',
+            nextDay : '내일 LT',
+            nextWeek : 'dddd LT',
+            lastDay : '어제 LT',
+            lastWeek : '지난주 dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s 후',
+            past : '%s 전',
+            s : '몇 초',
+            ss : '%d초',
+            m : '일분',
+            mm : '%d분',
+            h : '한 시간',
+            hh : '%d시간',
+            d : '하루',
+            dd : '%d일',
+            M : '한 달',
+            MM : '%d달',
+            y : '일 년',
+            yy : '%d년'
+        },
+        ordinalParse : /\d{1,2}일/,
+        ordinal : '%d일',
+        meridiemParse : /오전|오후/,
+        isPM : function (token) {
+            return token === '오후';
+        },
+        meridiem : function (hour, minute, isUpper) {
+            return hour < 12 ? '오전' : '오후';
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : kyrgyz (ky)
+    //! author : Chyngyz Arystan uulu : https://github.com/chyngyz
+
+
+    var ky__suffixes = {
+        0: '-чү',
+        1: '-чи',
+        2: '-чи',
+        3: '-чү',
+        4: '-чү',
+        5: '-чи',
+        6: '-чы',
+        7: '-чи',
+        8: '-чи',
+        9: '-чу',
+        10: '-чу',
+        20: '-чы',
+        30: '-чу',
+        40: '-чы',
+        50: '-чү',
+        60: '-чы',
+        70: '-чи',
+        80: '-чи',
+        90: '-чу',
+        100: '-чү'
+    };
+
+    var ky = moment__default.defineLocale('ky', {
+        months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
+        monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
+        weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'),
+        weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'),
+        weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[Бүгүн саат] LT',
+            nextDay : '[Эртең саат] LT',
+            nextWeek : 'dddd [саат] LT',
+            lastDay : '[Кече саат] LT',
+            lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s ичинде',
+            past : '%s мурун',
+            s : 'бирнече секунд',
+            m : 'бир мүнөт',
+            mm : '%d мүнөт',
+            h : 'бир саат',
+            hh : '%d саат',
+            d : 'бир күн',
+            dd : '%d күн',
+            M : 'бир ай',
+            MM : '%d ай',
+            y : 'бир жыл',
+            yy : '%d жыл'
+        },
+        ordinalParse: /\d{1,2}-(чи|чы|чү|чу)/,
+        ordinal : function (number) {
+            var a = number % 10,
+                b = number >= 100 ? 100 : null;
+            return number + (ky__suffixes[number] || ky__suffixes[a] || ky__suffixes[b]);
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Luxembourgish (lb)
+    //! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz
+
+    function lb__processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            'm': ['eng Minutt', 'enger Minutt'],
+            'h': ['eng Stonn', 'enger Stonn'],
+            'd': ['een Dag', 'engem Dag'],
+            'M': ['ee Mount', 'engem Mount'],
+            'y': ['ee Joer', 'engem Joer']
+        };
+        return withoutSuffix ? format[key][0] : format[key][1];
+    }
+    function processFutureTime(string) {
+        var number = string.substr(0, string.indexOf(' '));
+        if (eifelerRegelAppliesToNumber(number)) {
+            return 'a ' + string;
+        }
+        return 'an ' + string;
+    }
+    function processPastTime(string) {
+        var number = string.substr(0, string.indexOf(' '));
+        if (eifelerRegelAppliesToNumber(number)) {
+            return 'viru ' + string;
+        }
+        return 'virun ' + string;
+    }
+    /**
+     * Returns true if the word before the given number loses the '-n' ending.
+     * e.g. 'an 10 Deeg' but 'a 5 Deeg'
+     *
+     * @param number {integer}
+     * @returns {boolean}
+     */
+    function eifelerRegelAppliesToNumber(number) {
+        number = parseInt(number, 10);
+        if (isNaN(number)) {
+            return false;
+        }
+        if (number < 0) {
+            // Negative Number --> always true
+            return true;
+        } else if (number < 10) {
+            // Only 1 digit
+            if (4 <= number && number <= 7) {
+                return true;
+            }
+            return false;
+        } else if (number < 100) {
+            // 2 digits
+            var lastDigit = number % 10, firstDigit = number / 10;
+            if (lastDigit === 0) {
+                return eifelerRegelAppliesToNumber(firstDigit);
+            }
+            return eifelerRegelAppliesToNumber(lastDigit);
+        } else if (number < 10000) {
+            // 3 or 4 digits --> recursively check first digit
+            while (number >= 10) {
+                number = number / 10;
+            }
+            return eifelerRegelAppliesToNumber(number);
+        } else {
+            // Anything larger than 4 digits: recursively check first n-3 digits
+            number = number / 1000;
+            return eifelerRegelAppliesToNumber(number);
+        }
+    }
+
+    var lb = moment__default.defineLocale('lb', {
+        months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+        monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+        monthsParseExact : true,
+        weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
+        weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
+        weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat: {
+            LT: 'H:mm [Auer]',
+            LTS: 'H:mm:ss [Auer]',
+            L: 'DD.MM.YYYY',
+            LL: 'D. MMMM YYYY',
+            LLL: 'D. MMMM YYYY H:mm [Auer]',
+            LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]'
+        },
+        calendar: {
+            sameDay: '[Haut um] LT',
+            sameElse: 'L',
+            nextDay: '[Muer um] LT',
+            nextWeek: 'dddd [um] LT',
+            lastDay: '[Gëschter um] LT',
+            lastWeek: function () {
+                // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
+                switch (this.day()) {
+                    case 2:
+                    case 4:
+                        return '[Leschten] dddd [um] LT';
+                    default:
+                        return '[Leschte] dddd [um] LT';
+                }
+            }
+        },
+        relativeTime : {
+            future : processFutureTime,
+            past : processPastTime,
+            s : 'e puer Sekonnen',
+            m : lb__processRelativeTime,
+            mm : '%d Minutten',
+            h : lb__processRelativeTime,
+            hh : '%d Stonnen',
+            d : lb__processRelativeTime,
+            dd : '%d Deeg',
+            M : lb__processRelativeTime,
+            MM : '%d Méint',
+            y : lb__processRelativeTime,
+            yy : '%d Joer'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal: '%d.',
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : lao (lo)
+    //! author : Ryan Hart : https://github.com/ryanhart2
+
+    var lo = moment__default.defineLocale('lo', {
+        months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
+        monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
+        weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
+        weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
+        weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'ວັນdddd D MMMM YYYY HH:mm'
+        },
+        meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/,
+        isPM: function (input) {
+            return input === 'ຕອນແລງ';
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'ຕອນເຊົ້າ';
+            } else {
+                return 'ຕອນແລງ';
+            }
+        },
+        calendar : {
+            sameDay : '[ມື້ນີ້ເວລາ] LT',
+            nextDay : '[ມື້ອື່ນເວລາ] LT',
+            nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT',
+            lastDay : '[ມື້ວານນີ້ເວລາ] LT',
+            lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'ອີກ %s',
+            past : '%sຜ່ານມາ',
+            s : 'ບໍ່ເທົ່າໃດວິນາທີ',
+            m : '1 ນາທີ',
+            mm : '%d ນາທີ',
+            h : '1 ຊົ່ວໂມງ',
+            hh : '%d ຊົ່ວໂມງ',
+            d : '1 ມື້',
+            dd : '%d ມື້',
+            M : '1 ເດືອນ',
+            MM : '%d ເດືອນ',
+            y : '1 ປີ',
+            yy : '%d ປີ'
+        },
+        ordinalParse: /(ທີ່)\d{1,2}/,
+        ordinal : function (number) {
+            return 'ທີ່' + number;
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Lithuanian (lt)
+    //! author : Mindaugas Mozūras : https://github.com/mmozuras
+
+    var lt__units = {
+        'm' : 'minutė_minutės_minutę',
+        'mm': 'minutės_minučių_minutes',
+        'h' : 'valanda_valandos_valandą',
+        'hh': 'valandos_valandų_valandas',
+        'd' : 'diena_dienos_dieną',
+        'dd': 'dienos_dienų_dienas',
+        'M' : 'mėnuo_mėnesio_mėnesį',
+        'MM': 'mėnesiai_mėnesių_mėnesius',
+        'y' : 'metai_metų_metus',
+        'yy': 'metai_metų_metus'
+    };
+    function translateSeconds(number, withoutSuffix, key, isFuture) {
+        if (withoutSuffix) {
+            return 'kelios sekundės';
+        } else {
+            return isFuture ? 'kelių sekundžių' : 'kelias sekundes';
+        }
+    }
+    function translateSingular(number, withoutSuffix, key, isFuture) {
+        return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
+    }
+    function special(number) {
+        return number % 10 === 0 || (number > 10 && number < 20);
+    }
+    function forms(key) {
+        return lt__units[key].split('_');
+    }
+    function lt__translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        if (number === 1) {
+            return result + translateSingular(number, withoutSuffix, key[0], isFuture);
+        } else if (withoutSuffix) {
+            return result + (special(number) ? forms(key)[1] : forms(key)[0]);
+        } else {
+            if (isFuture) {
+                return result + forms(key)[1];
+            } else {
+                return result + (special(number) ? forms(key)[1] : forms(key)[2]);
+            }
+        }
+    }
+    var lt = moment__default.defineLocale('lt', {
+        months : {
+            format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'),
+            standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_')
+        },
+        monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'),
+        weekdays : {
+            format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'),
+            standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'),
+            isFormat: /dddd HH:mm/
+        },
+        weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'),
+        weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'YYYY-MM-DD',
+            LL : 'YYYY [m.] MMMM D [d.]',
+            LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
+            LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]',
+            l : 'YYYY-MM-DD',
+            ll : 'YYYY [m.] MMMM D [d.]',
+            lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
+            llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]'
+        },
+        calendar : {
+            sameDay : '[Šiandien] LT',
+            nextDay : '[Rytoj] LT',
+            nextWeek : 'dddd LT',
+            lastDay : '[Vakar] LT',
+            lastWeek : '[Praėjusį] dddd LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'po %s',
+            past : 'prieš %s',
+            s : translateSeconds,
+            m : translateSingular,
+            mm : lt__translate,
+            h : translateSingular,
+            hh : lt__translate,
+            d : translateSingular,
+            dd : lt__translate,
+            M : translateSingular,
+            MM : lt__translate,
+            y : translateSingular,
+            yy : lt__translate
+        },
+        ordinalParse: /\d{1,2}-oji/,
+        ordinal : function (number) {
+            return number + '-oji';
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : latvian (lv)
+    //! author : Kristaps Karlsons : https://github.com/skakri
+    //! author : Jānis Elmeris : https://github.com/JanisE
+
+    var lv__units = {
+        'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
+        'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
+        'h': 'stundas_stundām_stunda_stundas'.split('_'),
+        'hh': 'stundas_stundām_stunda_stundas'.split('_'),
+        'd': 'dienas_dienām_diena_dienas'.split('_'),
+        'dd': 'dienas_dienām_diena_dienas'.split('_'),
+        'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
+        'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
+        'y': 'gada_gadiem_gads_gadi'.split('_'),
+        'yy': 'gada_gadiem_gads_gadi'.split('_')
+    };
+    /**
+     * @param withoutSuffix boolean true = a length of time; false = before/after a period of time.
+     */
+    function lv__format(forms, number, withoutSuffix) {
+        if (withoutSuffix) {
+            // E.g. "21 minūte", "3 minūtes".
+            return number % 10 === 1 && number !== 11 ? forms[2] : forms[3];
+        } else {
+            // E.g. "21 minūtes" as in "pēc 21 minūtes".
+            // E.g. "3 minūtēm" as in "pēc 3 minūtēm".
+            return number % 10 === 1 && number !== 11 ? forms[0] : forms[1];
+        }
+    }
+    function lv__relativeTimeWithPlural(number, withoutSuffix, key) {
+        return number + ' ' + lv__format(lv__units[key], number, withoutSuffix);
+    }
+    function relativeTimeWithSingular(number, withoutSuffix, key) {
+        return lv__format(lv__units[key], number, withoutSuffix);
+    }
+    function relativeSeconds(number, withoutSuffix) {
+        return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm';
+    }
+
+    var lv = moment__default.defineLocale('lv', {
+        months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'),
+        weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'),
+        weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'),
+        weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY.',
+            LL : 'YYYY. [gada] D. MMMM',
+            LLL : 'YYYY. [gada] D. MMMM, HH:mm',
+            LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm'
+        },
+        calendar : {
+            sameDay : '[Šodien pulksten] LT',
+            nextDay : '[Rīt pulksten] LT',
+            nextWeek : 'dddd [pulksten] LT',
+            lastDay : '[Vakar pulksten] LT',
+            lastWeek : '[Pagājušā] dddd [pulksten] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'pēc %s',
+            past : 'pirms %s',
+            s : relativeSeconds,
+            m : relativeTimeWithSingular,
+            mm : lv__relativeTimeWithPlural,
+            h : relativeTimeWithSingular,
+            hh : lv__relativeTimeWithPlural,
+            d : relativeTimeWithSingular,
+            dd : lv__relativeTimeWithPlural,
+            M : relativeTimeWithSingular,
+            MM : lv__relativeTimeWithPlural,
+            y : relativeTimeWithSingular,
+            yy : lv__relativeTimeWithPlural
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Montenegrin (me)
+    //! author : Miodrag Nikač <mi...@restartit.me> : https://github.com/miodragnikac
+
+    var me__translator = {
+        words: { //Different grammatical cases
+            m: ['jedan minut', 'jednog minuta'],
+            mm: ['minut', 'minuta', 'minuta'],
+            h: ['jedan sat', 'jednog sata'],
+            hh: ['sat', 'sata', 'sati'],
+            dd: ['dan', 'dana', 'dana'],
+            MM: ['mjesec', 'mjeseca', 'mjeseci'],
+            yy: ['godina', 'godine', 'godina']
+        },
+        correctGrammaticalCase: function (number, wordKey) {
+            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+        },
+        translate: function (number, withoutSuffix, key) {
+            var wordKey = me__translator.words[key];
+            if (key.length === 1) {
+                return withoutSuffix ? wordKey[0] : wordKey[1];
+            } else {
+                return number + ' ' + me__translator.correctGrammaticalCase(number, wordKey);
+            }
+        }
+    };
+
+    var me = moment__default.defineLocale('me', {
+        months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
+        monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
+        monthsParseExact : true,
+        weekdays: 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+        weekdaysShort: 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+        weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat: {
+            LT: 'H:mm',
+            LTS : 'H:mm:ss',
+            L: 'DD. MM. YYYY',
+            LL: 'D. MMMM YYYY',
+            LLL: 'D. MMMM YYYY H:mm',
+            LLLL: 'dddd, D. MMMM YYYY H:mm'
+        },
+        calendar: {
+            sameDay: '[danas u] LT',
+            nextDay: '[sjutra u] LT',
+
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedjelju] [u] LT';
+                case 3:
+                    return '[u] [srijedu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[juče u] LT',
+            lastWeek : function () {
+                var lastWeekDays = [
+                    '[prošle] [nedjelje] [u] LT',
+                    '[prošlog] [ponedjeljka] [u] LT',
+                    '[prošlog] [utorka] [u] LT',
+                    '[prošle] [srijede] [u] LT',
+                    '[prošlog] [četvrtka] [u] LT',
+                    '[prošlog] [petka] [u] LT',
+                    '[prošle] [subote] [u] LT'
+                ];
+                return lastWeekDays[this.day()];
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past   : 'prije %s',
+            s      : 'nekoliko sekundi',
+            m      : me__translator.translate,
+            mm     : me__translator.translate,
+            h      : me__translator.translate,
+            hh     : me__translator.translate,
+            d      : 'dan',
+            dd     : me__translator.translate,
+            M      : 'mjesec',
+            MM     : me__translator.translate,
+            y      : 'godinu',
+            yy     : me__translator.translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : macedonian (mk)
+    //! author : Borislav Mickov : https://github.com/B0k0
+
+    var mk = moment__default.defineLocale('mk', {
+        months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'),
+        monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'),
+        weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'),
+        weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'),
+        weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'D.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY H:mm',
+            LLLL : 'dddd, D MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay : '[Денес во] LT',
+            nextDay : '[Утре во] LT',
+            nextWeek : '[Во] dddd [во] LT',
+            lastDay : '[Вчера во] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 6:
+                    return '[Изминатата] dddd [во] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[Изминатиот] dddd [во] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'после %s',
+            past : 'пред %s',
+            s : 'неколку секунди',
+            m : 'минута',
+            mm : '%d минути',
+            h : 'час',
+            hh : '%d часа',
+            d : 'ден',
+            dd : '%d дена',
+            M : 'месец',
+            MM : '%d месеци',
+            y : 'година',
+            yy : '%d години'
+        },
+        ordinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+        ordinal : function (number) {
+            var lastDigit = number % 10,
+                last2Digits = number % 100;
+            if (number === 0) {
+                return number + '-ев';
+            } else if (last2Digits === 0) {
+                return number + '-ен';
+            } else if (last2Digits > 10 && last2Digits < 20) {
+                return number + '-ти';
+            } else if (lastDigit === 1) {
+                return number + '-ви';
+            } else if (lastDigit === 2) {
+                return number + '-ри';
+            } else if (lastDigit === 7 || lastDigit === 8) {
+                return number + '-ми';
+            } else {
+                return number + '-ти';
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : malayalam (ml)
+    //! author : Floyd Pink : https://github.com/floydpink
+
+    var ml = moment__default.defineLocale('ml', {
+        months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'),
+        monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'),
+        weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
+        weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm -നു',
+            LTS : 'A h:mm:ss -നു',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, A h:mm -നു',
+            LLLL : 'dddd, D MMMM YYYY, A h:mm -നു'
+        },
+        calendar : {
+            sameDay : '[ഇന്ന്] LT',
+            nextDay : '[നാളെ] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[ഇന്നലെ] LT',
+            lastWeek : '[കഴിഞ്ഞ] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s കഴിഞ്ഞ്',
+            past : '%s മുൻപ്',
+            s : 'അൽപ നിമിഷങ്ങൾ',
+            m : 'ഒരു മിനിറ്റ്',
+            mm : '%d മിനിറ്റ്',
+            h : 'ഒരു മണിക്കൂർ',
+            hh : '%d മണിക്കൂർ',
+            d : 'ഒരു ദിവസം',
+            dd : '%d ദിവസം',
+            M : 'ഒരു മാസം',
+            MM : '%d മാസം',
+            y : 'ഒരു വർഷം',
+            yy : '%d വർഷം'
+        },
+        meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if ((meridiem === 'രാത്രി' && hour >= 4) ||
+                    meridiem === 'ഉച്ച കഴിഞ്ഞ്' ||
+                    meridiem === 'വൈകുന്നേരം') {
+                return hour + 12;
+            } else {
+                return hour;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'രാത്രി';
+            } else if (hour < 12) {
+                return 'രാവിലെ';
+            } else if (hour < 17) {
+                return 'ഉച്ച കഴിഞ്ഞ്';
+            } else if (hour < 20) {
+                return 'വൈകുന്നേരം';
+            } else {
+                return 'രാത്രി';
+            }
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Marathi (mr)
+    //! author : Harshad Kale : https://github.com/kalehv
+    //! author : Vivek Athalye : https://github.com/vnathalye
+
+    var mr__symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    mr__numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    function relativeTimeMr(number, withoutSuffix, string, isFuture)
+    {
+        var output = '';
+        if (withoutSuffix) {
+            switch (string) {
+                case 's': output = 'काही सेकंद'; break;
+                case 'm': output = 'एक मिनिट'; break;
+                case 'mm': output = '%d मिनिटे'; break;
+                case 'h': output = 'एक तास'; break;
+                case 'hh': output = '%d तास'; break;
+                case 'd': output = 'एक दिवस'; break;
+                case 'dd': output = '%d दिवस'; break;
+                case 'M': output = 'एक महिना'; break;
+                case 'MM': output = '%d महिने'; break;
+                case 'y': output = 'एक वर्ष'; break;
+                case 'yy': output = '%d वर्षे'; break;
+            }
+        }
+        else {
+            switch (string) {
+                case 's': output = 'काही सेकंदां'; break;
+                case 'm': output = 'एका मिनिटा'; break;
+                case 'mm': output = '%d मिनिटां'; break;
+                case 'h': output = 'एका तासा'; break;
+                case 'hh': output = '%d तासां'; break;
+                case 'd': output = 'एका दिवसा'; break;
+                case 'dd': output = '%d दिवसां'; break;
+                case 'M': output = 'एका महिन्या'; break;
+                case 'MM': output = '%d महिन्यां'; break;
+                case 'y': output = 'एका वर्षा'; break;
+                case 'yy': output = '%d वर्षां'; break;
+            }
+        }
+        return output.replace(/%d/i, number);
+    }
+
+    var mr = moment__default.defineLocale('mr', {
+        months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'),
+        monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+        weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'),
+        weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm वाजता',
+            LTS : 'A h:mm:ss वाजता',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, A h:mm वाजता',
+            LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता'
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[उद्या] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[काल] LT',
+            lastWeek: '[मागील] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future: '%sमध्ये',
+            past: '%sपूर्वी',
+            s: relativeTimeMr,
+            m: relativeTimeMr,
+            mm: relativeTimeMr,
+            h: relativeTimeMr,
+            hh: relativeTimeMr,
+            d: relativeTimeMr,
+            dd: relativeTimeMr,
+            M: relativeTimeMr,
+            MM: relativeTimeMr,
+            y: relativeTimeMr,
+            yy: relativeTimeMr
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return mr__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return mr__symbolMap[match];
+            });
+        },
+        meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'रात्री') {
+                return hour < 4 ? hour : hour + 12;
+            } else if (meridiem === 'सकाळी') {
+                return hour;
+            } else if (meridiem === 'दुपारी') {
+                return hour >= 10 ? hour : hour + 12;
+            } else if (meridiem === 'सायंकाळी') {
+                return hour + 12;
+            }
+        },
+        meridiem: function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'रात्री';
+            } else if (hour < 10) {
+                return 'सकाळी';
+            } else if (hour < 17) {
+                return 'दुपारी';
+            } else if (hour < 20) {
+                return 'सायंकाळी';
+            } else {
+                return 'रात्री';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Bahasa Malaysia (ms-MY)
+    //! author : Weldan Jamili : https://github.com/weldan
+
+    var ms_my = moment__default.defineLocale('ms-my', {
+        months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+        monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
+        weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+        weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+        weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            LTS : 'HH.mm.ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY [pukul] HH.mm',
+            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+        },
+        meridiemParse: /pagi|tengahari|petang|malam/,
+        meridiemHour: function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'pagi') {
+                return hour;
+            } else if (meridiem === 'tengahari') {
+                return hour >= 11 ? hour : hour + 12;
+            } else if (meridiem === 'petang' || meridiem === 'malam') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'pagi';
+            } else if (hours < 15) {
+                return 'tengahari';
+            } else if (hours < 19) {
+                return 'petang';
+            } else {
+                return 'malam';
+            }
+        },
+        calendar : {
+            sameDay : '[Hari ini pukul] LT',
+            nextDay : '[Esok pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kelmarin pukul] LT',
+            lastWeek : 'dddd [lepas pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'dalam %s',
+            past : '%s yang lepas',
+            s : 'beberapa saat',
+            m : 'seminit',
+            mm : '%d minit',
+            h : 'sejam',
+            hh : '%d jam',
+            d : 'sehari',
+            dd : '%d hari',
+            M : 'sebulan',
+            MM : '%d bulan',
+            y : 'setahun',
+            yy : '%d tahun'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Bahasa Malaysia (ms-MY)
+    //! author : Weldan Jamili : https://github.com/weldan
+
+    var locale_ms = moment__default.defineLocale('ms', {
+        months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+        monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
+        weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+        weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+        weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            LTS : 'HH.mm.ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY [pukul] HH.mm',
+            LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+        },
+        meridiemParse: /pagi|tengahari|petang|malam/,
+        meridiemHour: function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'pagi') {
+                return hour;
+            } else if (meridiem === 'tengahari') {
+                return hour >= 11 ? hour : hour + 12;
+            } else if (meridiem === 'petang' || meridiem === 'malam') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'pagi';
+            } else if (hours < 15) {
+                return 'tengahari';
+            } else if (hours < 19) {
+                return 'petang';
+            } else {
+                return 'malam';
+            }
+        },
+        calendar : {
+            sameDay : '[Hari ini pukul] LT',
+            nextDay : '[Esok pukul] LT',
+            nextWeek : 'dddd [pukul] LT',
+            lastDay : '[Kelmarin pukul] LT',
+            lastWeek : 'dddd [lepas pukul] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'dalam %s',
+            past : '%s yang lepas',
+            s : 'beberapa saat',
+            m : 'seminit',
+            mm : '%d minit',
+            h : 'sejam',
+            hh : '%d jam',
+            d : 'sehari',
+            dd : '%d hari',
+            M : 'sebulan',
+            MM : '%d bulan',
+            y : 'setahun',
+            yy : '%d tahun'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Burmese (my)
+    //! author : Squar team, mysquar.com
+
+    var my__symbolMap = {
+        '1': '၁',
+        '2': '၂',
+        '3': '၃',
+        '4': '၄',
+        '5': '၅',
+        '6': '၆',
+        '7': '၇',
+        '8': '၈',
+        '9': '၉',
+        '0': '၀'
+    }, my__numberMap = {
+        '၁': '1',
+        '၂': '2',
+        '၃': '3',
+        '၄': '4',
+        '၅': '5',
+        '၆': '6',
+        '၇': '7',
+        '၈': '8',
+        '၉': '9',
+        '၀': '0'
+    };
+
+    var my = moment__default.defineLocale('my', {
+        months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
+        monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'),
+        weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
+        weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+        weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+
+        longDateFormat: {
+            LT: 'HH:mm',
+            LTS: 'HH:mm:ss',
+            L: 'DD/MM/YYYY',
+            LL: 'D MMMM YYYY',
+            LLL: 'D MMMM YYYY HH:mm',
+            LLLL: 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar: {
+            sameDay: '[ယနေ.] LT [မှာ]',
+            nextDay: '[မနက်ဖြန်] LT [မှာ]',
+            nextWeek: 'dddd LT [မှာ]',
+            lastDay: '[မနေ.က] LT [မှာ]',
+            lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]',
+            sameElse: 'L'
+        },
+        relativeTime: {
+            future: 'လာမည့် %s မှာ',
+            past: 'လွန်ခဲ့သော %s က',
+            s: 'စက္ကန်.အနည်းငယ်',
+            m: 'တစ်မိနစ်',
+            mm: '%d မိနစ်',
+            h: 'တစ်နာရီ',
+            hh: '%d နာရီ',
+            d: 'တစ်ရက်',
+            dd: '%d ရက်',
+            M: 'တစ်လ',
+            MM: '%d လ',
+            y: 'တစ်နှစ်',
+            yy: '%d နှစ်'
+        },
+        preparse: function (string) {
+            return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) {
+                return my__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return my__symbolMap[match];
+            });
+        },
+        week: {
+            dow: 1, // Monday is the first day of the week.
+            doy: 4 // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : norwegian bokmål (nb)
+    //! authors : Espen Hovlandsdal : https://github.com/rexxars
+    //!           Sigurd Gartmann : https://github.com/sigurdga
+
+    var nb = moment__default.defineLocale('nb', {
+        months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+        monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+        weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
+        weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY [kl.] HH:mm',
+            LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
+        },
+        calendar : {
+            sameDay: '[i dag kl.] LT',
+            nextDay: '[i morgen kl.] LT',
+            nextWeek: 'dddd [kl.] LT',
+            lastDay: '[i går kl.] LT',
+            lastWeek: '[forrige] dddd [kl.] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : '%s siden',
+            s : 'noen sekunder',
+            m : 'ett minutt',
+            mm : '%d minutter',
+            h : 'en time',
+            hh : '%d timer',
+            d : 'en dag',
+            dd : '%d dager',
+            M : 'en måned',
+            MM : '%d måneder',
+            y : 'ett år',
+            yy : '%d år'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : nepali/nepalese
+    //! author : suvash : https://github.com/suvash
+
+    var ne__symbolMap = {
+        '1': '१',
+        '2': '२',
+        '3': '३',
+        '4': '४',
+        '5': '५',
+        '6': '६',
+        '7': '७',
+        '8': '८',
+        '9': '९',
+        '0': '०'
+    },
+    ne__numberMap = {
+        '१': '1',
+        '२': '2',
+        '३': '3',
+        '४': '4',
+        '५': '5',
+        '६': '6',
+        '७': '7',
+        '८': '8',
+        '९': '9',
+        '०': '0'
+    };
+
+    var ne = moment__default.defineLocale('ne', {
+        months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'),
+        monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'),
+        weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'),
+        weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'Aको h:mm बजे',
+            LTS : 'Aको h:mm:ss बजे',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, Aको h:mm बजे',
+            LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे'
+        },
+        preparse: function (string) {
+            return string.replace(/[१२३४५६७८९०]/g, function (match) {
+                return ne__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return ne__symbolMap[match];
+            });
+        },
+        meridiemParse: /राति|बिहान|दिउँसो|साँझ/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'राति') {
+                return hour < 4 ? hour : hour + 12;
+            } else if (meridiem === 'बिहान') {
+                return hour;
+            } else if (meridiem === 'दिउँसो') {
+                return hour >= 10 ? hour : hour + 12;
+            } else if (meridiem === 'साँझ') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 3) {
+                return 'राति';
+            } else if (hour < 12) {
+                return 'बिहान';
+            } else if (hour < 16) {
+                return 'दिउँसो';
+            } else if (hour < 20) {
+                return 'साँझ';
+            } else {
+                return 'राति';
+            }
+        },
+        calendar : {
+            sameDay : '[आज] LT',
+            nextDay : '[भोलि] LT',
+            nextWeek : '[आउँदो] dddd[,] LT',
+            lastDay : '[हिजो] LT',
+            lastWeek : '[गएको] dddd[,] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%sमा',
+            past : '%s अगाडि',
+            s : 'केही क्षण',
+            m : 'एक मिनेट',
+            mm : '%d मिनेट',
+            h : 'एक घण्टा',
+            hh : '%d घण्टा',
+            d : 'एक दिन',
+            dd : '%d दिन',
+            M : 'एक महिना',
+            MM : '%d महिना',
+            y : 'एक बर्ष',
+            yy : '%d बर्ष'
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : dutch (nl)
+    //! author : Joris Röling : https://github.com/jjupiter
+
+    var nl__monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_'),
+        nl__monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
+
+    var nl = moment__default.defineLocale('nl', {
+        months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
+        monthsShort : function (m, format) {
+            if (/-MMM-/.test(format)) {
+                return nl__monthsShortWithoutDots[m.month()];
+            } else {
+                return nl__monthsShortWithDots[m.month()];
+            }
+        },
+        monthsParseExact : true,
+        weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
+        weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
+        weekdaysMin : 'Zo_Ma_Di_Wo_Do_Vr_Za'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD-MM-YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[vandaag om] LT',
+            nextDay: '[morgen om] LT',
+            nextWeek: 'dddd [om] LT',
+            lastDay: '[gisteren om] LT',
+            lastWeek: '[afgelopen] dddd [om] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'over %s',
+            past : '%s geleden',
+            s : 'een paar seconden',
+            m : 'één minuut',
+            mm : '%d minuten',
+            h : 'één uur',
+            hh : '%d uur',
+            d : 'één dag',
+            dd : '%d dagen',
+            M : 'één maand',
+            MM : '%d maanden',
+            y : 'één jaar',
+            yy : '%d jaar'
+        },
+        ordinalParse: /\d{1,2}(ste|de)/,
+        ordinal : function (number) {
+            return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : norwegian nynorsk (nn)
+    //! author : https://github.com/mechuwind
+
+    var nn = moment__default.defineLocale('nn', {
+        months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+        weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
+        weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'),
+        weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY [kl.] H:mm',
+            LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
+        },
+        calendar : {
+            sameDay: '[I dag klokka] LT',
+            nextDay: '[I morgon klokka] LT',
+            nextWeek: 'dddd [klokka] LT',
+            lastDay: '[I går klokka] LT',
+            lastWeek: '[Føregåande] dddd [klokka] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : '%s sidan',
+            s : 'nokre sekund',
+            m : 'eit minutt',
+            mm : '%d minutt',
+            h : 'ein time',
+            hh : '%d timar',
+            d : 'ein dag',
+            dd : '%d dagar',
+            M : 'ein månad',
+            MM : '%d månader',
+            y : 'eit år',
+            yy : '%d år'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : punjabi india (pa-in)
+    //! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit
+
+    var pa_in__symbolMap = {
+        '1': '੧',
+        '2': '੨',
+        '3': '੩',
+        '4': '੪',
+        '5': '੫',
+        '6': '੬',
+        '7': '੭',
+        '8': '੮',
+        '9': '੯',
+        '0': '੦'
+    },
+    pa_in__numberMap = {
+        '੧': '1',
+        '੨': '2',
+        '੩': '3',
+        '੪': '4',
+        '੫': '5',
+        '੬': '6',
+        '੭': '7',
+        '੮': '8',
+        '੯': '9',
+        '੦': '0'
+    };
+
+    var pa_in = moment__default.defineLocale('pa-in', {
+        // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi.
+        months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
+        monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
+        weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'),
+        weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
+        weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm ਵਜੇ',
+            LTS : 'A h:mm:ss ਵਜੇ',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, A h:mm ਵਜੇ',
+            LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ'
+        },
+        calendar : {
+            sameDay : '[ਅਜ] LT',
+            nextDay : '[ਕਲ] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[ਕਲ] LT',
+            lastWeek : '[ਪਿਛਲੇ] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s ਵਿੱਚ',
+            past : '%s ਪਿਛਲੇ',
+            s : 'ਕੁਝ ਸਕਿੰਟ',
+            m : 'ਇਕ ਮਿੰਟ',
+            mm : '%d ਮਿੰਟ',
+            h : 'ਇੱਕ ਘੰਟਾ',
+            hh : '%d ਘੰਟੇ',
+            d : 'ਇੱਕ ਦਿਨ',
+            dd : '%d ਦਿਨ',
+            M : 'ਇੱਕ ਮਹੀਨਾ',
+            MM : '%d ਮਹੀਨੇ',
+            y : 'ਇੱਕ ਸਾਲ',
+            yy : '%d ਸਾਲ'
+        },
+        preparse: function (string) {
+            return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) {
+                return pa_in__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return pa_in__symbolMap[match];
+            });
+        },
+        // Punjabi notation for meridiems are quite fuzzy in practice. While there exists
+        // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi.
+        meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'ਰਾਤ') {
+                return hour < 4 ? hour : hour + 12;
+            } else if (meridiem === 'ਸਵੇਰ') {
+                return hour;
+            } else if (meridiem === 'ਦੁਪਹਿਰ') {
+                return hour >= 10 ? hour : hour + 12;
+            } else if (meridiem === 'ਸ਼ਾਮ') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'ਰਾਤ';
+            } else if (hour < 10) {
+                return 'ਸਵੇਰ';
+            } else if (hour < 17) {
+                return 'ਦੁਪਹਿਰ';
+            } else if (hour < 20) {
+                return 'ਸ਼ਾਮ';
+            } else {
+                return 'ਰਾਤ';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : polish (pl)
+    //! author : Rafal Hirsz : https://github.com/evoL
+
+    var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_'),
+        monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_');
+    function pl__plural(n) {
+        return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
+    }
+    function pl__translate(number, withoutSuffix, key) {
+        var result = number + ' ';
+        switch (key) {
+        case 'm':
+            return withoutSuffix ? 'minuta' : 'minutę';
+        case 'mm':
+            return result + (pl__plural(number) ? 'minuty' : 'minut');
+        case 'h':
+            return withoutSuffix  ? 'godzina'  : 'godzinę';
+        case 'hh':
+            return result + (pl__plural(number) ? 'godziny' : 'godzin');
+        case 'MM':
+            return result + (pl__plural(number) ? 'miesiące' : 'miesięcy');
+        case 'yy':
+            return result + (pl__plural(number) ? 'lata' : 'lat');
+        }
+    }
+
+    var pl = moment__default.defineLocale('pl', {
+        months : function (momentToFormat, format) {
+            if (format === '') {
+                // Hack: if format empty we know this is used to generate
+                // RegExp by moment. Give then back both valid forms of months
+                // in RegExp ready format.
+                return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')';
+            } else if (/D MMMM/.test(format)) {
+                return monthsSubjective[momentToFormat.month()];
+            } else {
+                return monthsNominative[momentToFormat.month()];
+            }
+        },
+        monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
+        weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'),
+        weekdaysShort : 'nie_pon_wt_śr_czw_pt_sb'.split('_'),
+        weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Dziś o] LT',
+            nextDay: '[Jutro o] LT',
+            nextWeek: '[W] dddd [o] LT',
+            lastDay: '[Wczoraj o] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[W zeszłą niedzielę o] LT';
+                case 3:
+                    return '[W zeszłą środę o] LT';
+                case 6:
+                    return '[W zeszłą sobotę o] LT';
+                default:
+                    return '[W zeszły] dddd [o] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past : '%s temu',
+            s : 'kilka sekund',
+            m : pl__translate,
+            mm : pl__translate,
+            h : pl__translate,
+            hh : pl__translate,
+            d : '1 dzień',
+            dd : '%d dni',
+            M : 'miesiąc',
+            MM : pl__translate,
+            y : 'rok',
+            yy : pl__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : brazilian portuguese (pt-br)
+    //! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
+
+    var pt_br = moment__default.defineLocale('pt-br', {
+        months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'),
+        monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'),
+        weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
+        weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
+        weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D [de] MMMM [de] YYYY',
+            LLL : 'D [de] MMMM [de] YYYY [às] HH:mm',
+            LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm'
+        },
+        calendar : {
+            sameDay: '[Hoje às] LT',
+            nextDay: '[Amanhã às] LT',
+            nextWeek: 'dddd [às] LT',
+            lastDay: '[Ontem às] LT',
+            lastWeek: function () {
+                return (this.day() === 0 || this.day() === 6) ?
+                    '[Último] dddd [às] LT' : // Saturday + Sunday
+                    '[Última] dddd [às] LT'; // Monday - Friday
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'em %s',
+            past : '%s atrás',
+            s : 'poucos segundos',
+            m : 'um minuto',
+            mm : '%d minutos',
+            h : 'uma hora',
+            hh : '%d horas',
+            d : 'um dia',
+            dd : '%d dias',
+            M : 'um mês',
+            MM : '%d meses',
+            y : 'um ano',
+            yy : '%d anos'
+        },
+        ordinalParse: /\d{1,2}º/,
+        ordinal : '%dº'
+    });
+
+    //! moment.js locale configuration
+    //! locale : portuguese (pt)
+    //! author : Jefferson : https://github.com/jalex79
+
+    var pt = moment__default.defineLocale('pt', {
+        months : 'Janeiro_Fevereiro_Março_Abril_Maio_Junho_Julho_Agosto_Setembro_Outubro_Novembro_Dezembro'.split('_'),
+        monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Ago_Set_Out_Nov_Dez'.split('_'),
+        weekdays : 'Domingo_Segunda-Feira_Terça-Feira_Quarta-Feira_Quinta-Feira_Sexta-Feira_Sábado'.split('_'),
+        weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
+        weekdaysMin : 'Dom_2ª_3ª_4ª_5ª_6ª_Sáb'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D [de] MMMM [de] YYYY',
+            LLL : 'D [de] MMMM [de] YYYY HH:mm',
+            LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Hoje às] LT',
+            nextDay: '[Amanhã às] LT',
+            nextWeek: 'dddd [às] LT',
+            lastDay: '[Ontem às] LT',
+            lastWeek: function () {
+                return (this.day() === 0 || this.day() === 6) ?
+                    '[Último] dddd [às] LT' : // Saturday + Sunday
+                    '[Última] dddd [às] LT'; // Monday - Friday
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'em %s',
+            past : 'há %s',
+            s : 'segundos',
+            m : 'um minuto',
+            mm : '%d minutos',
+            h : 'uma hora',
+            hh : '%d horas',
+            d : 'um dia',
+            dd : '%d dias',
+            M : 'um mês',
+            MM : '%d meses',
+            y : 'um ano',
+            yy : '%d anos'
+        },
+        ordinalParse: /\d{1,2}º/,
+        ordinal : '%dº',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : romanian (ro)
+    //! author : Vlad Gurdiga : https://github.com/gurdiga
+    //! author : Valentin Agachi : https://github.com/avaly
+
+    function ro__relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+                'mm': 'minute',
+                'hh': 'ore',
+                'dd': 'zile',
+                'MM': 'luni',
+                'yy': 'ani'
+            },
+            separator = ' ';
+        if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
+            separator = ' de ';
+        }
+        return number + separator + format[key];
+    }
+
+    var ro = moment__default.defineLocale('ro', {
+        months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'),
+        monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'),
+        monthsParseExact: true,
+        weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'),
+        weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'),
+        weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY H:mm',
+            LLLL : 'dddd, D MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay: '[azi la] LT',
+            nextDay: '[mâine la] LT',
+            nextWeek: 'dddd [la] LT',
+            lastDay: '[ieri la] LT',
+            lastWeek: '[fosta] dddd [la] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'peste %s',
+            past : '%s în urmă',
+            s : 'câteva secunde',
+            m : 'un minut',
+            mm : ro__relativeTimeWithPlural,
+            h : 'o oră',
+            hh : ro__relativeTimeWithPlural,
+            d : 'o zi',
+            dd : ro__relativeTimeWithPlural,
+            M : 'o lună',
+            MM : ro__relativeTimeWithPlural,
+            y : 'un an',
+            yy : ro__relativeTimeWithPlural
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : russian (ru)
+    //! author : Viktorminator : https://github.com/Viktorminator
+    //! Author : Menelion Elensúle : https://github.com/Oire
+    //! author : Коренберг Марк : https://github.com/socketpair
+
+    function ru__plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+    function ru__relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
+            'hh': 'час_часа_часов',
+            'dd': 'день_дня_дней',
+            'MM': 'месяц_месяца_месяцев',
+            'yy': 'год_года_лет'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'минута' : 'минуту';
+        }
+        else {
+            return number + ' ' + ru__plural(format[key], +number);
+        }
+    }
+    var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i];
+
+    // http://new.gramota.ru/spravka/rules/139-prop : § 103
+    // Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637
+    // CLDR data:          http://www.unicode.org/cldr/charts/28/summary/ru.html#1753
+    var ru = moment__default.defineLocale('ru', {
+        months : {
+            format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'),
+            standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_')
+        },
+        monthsShort : {
+            // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ?
+            format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'),
+            standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_')
+        },
+        weekdays : {
+            standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
+            format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'),
+            isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/
+        },
+        weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+        weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+        monthsParse : monthsParse,
+        longMonthsParse : monthsParse,
+        shortMonthsParse : monthsParse,
+        monthsRegex: /^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,
+        monthsShortRegex: /^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|сент\.|февр\.|нояб\.|июнь|янв.|июль|дек.|авг.|апр.|марта|мар[.т]|окт.|июн[яь]|июл[яь]|ма[яй])/i,
+        monthsStrictRegex: /^(сентябр[яь]|октябр[яь]|декабр[яь]|феврал[яь]|январ[яь]|апрел[яь]|августа?|ноябр[яь]|марта?|июн[яь]|июл[яь]|ма[яй])/i,
+        monthsShortStrictRegex: /^(нояб\.|февр\.|сент\.|июль|янв\.|июн[яь]|мар[.т]|авг\.|апр\.|окт\.|дек\.|ма[яй])/i,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY г.',
+            LLL : 'D MMMM YYYY г., HH:mm',
+            LLLL : 'dddd, D MMMM YYYY г., HH:mm'
+        },
+        calendar : {
+            sameDay: '[Сегодня в] LT',
+            nextDay: '[Завтра в] LT',
+            lastDay: '[Вчера в] LT',
+            nextWeek: function (now) {
+                if (now.week() !== this.week()) {
+                    switch (this.day()) {
+                    case 0:
+                        return '[В следующее] dddd [в] LT';
+                    case 1:
+                    case 2:
+                    case 4:
+                        return '[В следующий] dddd [в] LT';
+                    case 3:
+                    case 5:
+                    case 6:
+                        return '[В следующую] dddd [в] LT';
+                    }
+                } else {
+                    if (this.day() === 2) {
+                        return '[Во] dddd [в] LT';
+                    } else {
+                        return '[В] dddd [в] LT';
+                    }
+                }
+            },
+            lastWeek: function (now) {
+                if (now.week() !== this.week()) {
+                    switch (this.day()) {
+                    case 0:
+                        return '[В прошлое] dddd [в] LT';
+                    case 1:
+                    case 2:
+                    case 4:
+                        return '[В прошлый] dddd [в] LT';
+                    case 3:
+                    case 5:
+                    case 6:
+                        return '[В прошлую] dddd [в] LT';
+                    }
+                } else {
+                    if (this.day() === 2) {
+                        return '[Во] dddd [в] LT';
+                    } else {
+                        return '[В] dddd [в] LT';
+                    }
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'через %s',
+            past : '%s назад',
+            s : 'несколько секунд',
+            m : ru__relativeTimeWithPlural,
+            mm : ru__relativeTimeWithPlural,
+            h : 'час',
+            hh : ru__relativeTimeWithPlural,
+            d : 'день',
+            dd : ru__relativeTimeWithPlural,
+            M : 'месяц',
+            MM : ru__relativeTimeWithPlural,
+            y : 'год',
+            yy : ru__relativeTimeWithPlural
+        },
+        meridiemParse: /ночи|утра|дня|вечера/i,
+        isPM : function (input) {
+            return /^(дня|вечера)$/.test(input);
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'ночи';
+            } else if (hour < 12) {
+                return 'утра';
+            } else if (hour < 17) {
+                return 'дня';
+            } else {
+                return 'вечера';
+            }
+        },
+        ordinalParse: /\d{1,2}-(й|го|я)/,
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+                return number + '-й';
+            case 'D':
+                return number + '-го';
+            case 'w':
+            case 'W':
+                return number + '-я';
+            default:
+                return number;
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Northern Sami (se)
+    //! authors : Bård Rolstad Henriksen : https://github.com/karamell
+
+
+    var se = moment__default.defineLocale('se', {
+        months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'),
+        monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'),
+        weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'),
+        weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'),
+        weekdaysMin : 's_v_m_g_d_b_L'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'MMMM D. [b.] YYYY',
+            LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm',
+            LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm'
+        },
+        calendar : {
+            sameDay: '[otne ti] LT',
+            nextDay: '[ihttin ti] LT',
+            nextWeek: 'dddd [ti] LT',
+            lastDay: '[ikte ti] LT',
+            lastWeek: '[ovddit] dddd [ti] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : '%s geažes',
+            past : 'maŋit %s',
+            s : 'moadde sekunddat',
+            m : 'okta minuhta',
+            mm : '%d minuhtat',
+            h : 'okta diimmu',
+            hh : '%d diimmut',
+            d : 'okta beaivi',
+            dd : '%d beaivvit',
+            M : 'okta mánnu',
+            MM : '%d mánut',
+            y : 'okta jahki',
+            yy : '%d jagit'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Sinhalese (si)
+    //! author : Sampath Sitinamaluwa : https://github.com/sampathsris
+
+    /*jshint -W100*/
+    var si = moment__default.defineLocale('si', {
+        months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'),
+        monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'),
+        weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'),
+        weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන'.split('_'),
+        weekdaysMin : 'ඉ_ස_අ_බ_බ්‍ර_සි_සෙ'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'a h:mm',
+            LTS : 'a h:mm:ss',
+            L : 'YYYY/MM/DD',
+            LL : 'YYYY MMMM D',
+            LLL : 'YYYY MMMM D, a h:mm',
+            LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss'
+        },
+        calendar : {
+            sameDay : '[අද] LT[ට]',
+            nextDay : '[හෙට] LT[ට]',
+            nextWeek : 'dddd LT[ට]',
+            lastDay : '[ඊයේ] LT[ට]',
+            lastWeek : '[පසුගිය] dddd LT[ට]',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%sකින්',
+            past : '%sකට පෙර',
+            s : 'තත්පර කිහිපය',
+            m : 'මිනිත්තුව',
+            mm : 'මිනිත්තු %d',
+            h : 'පැය',
+            hh : 'පැය %d',
+            d : 'දිනය',
+            dd : 'දින %d',
+            M : 'මාසය',
+            MM : 'මාස %d',
+            y : 'වසර',
+            yy : 'වසර %d'
+        },
+        ordinalParse: /\d{1,2} වැනි/,
+        ordinal : function (number) {
+            return number + ' වැනි';
+        },
+        meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,
+        isPM : function (input) {
+            return input === 'ප.ව.' || input === 'පස් වරු';
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'ප.ව.' : 'පස් වරු';
+            } else {
+                return isLower ? 'පෙ.ව.' : 'පෙර වරු';
+            }
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : slovak (sk)
+    //! author : Martin Minka : https://github.com/k2s
+    //! based on work of petrbela : https://github.com/petrbela
+
+    var sk__months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_'),
+        sk__monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_');
+    function sk__plural(n) {
+        return (n > 1) && (n < 5);
+    }
+    function sk__translate(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        switch (key) {
+        case 's':  // a few seconds / in a few seconds / a few seconds ago
+            return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
+        case 'm':  // a minute / in a minute / a minute ago
+            return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
+        case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+            if (withoutSuffix || isFuture) {
+                return result + (sk__plural(number) ? 'minúty' : 'minút');
+            } else {
+                return result + 'minútami';
+            }
+            break;
+        case 'h':  // an hour / in an hour / an hour ago
+            return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+        case 'hh': // 9 hours / in 9 hours / 9 hours ago
+            if (withoutSuffix || isFuture) {
+                return result + (sk__plural(number) ? 'hodiny' : 'hodín');
+            } else {
+                return result + 'hodinami';
+            }
+            break;
+        case 'd':  // a day / in a day / a day ago
+            return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
+        case 'dd': // 9 days / in 9 days / 9 days ago
+            if (withoutSuffix || isFuture) {
+                return result + (sk__plural(number) ? 'dni' : 'dní');
+            } else {
+                return result + 'dňami';
+            }
+            break;
+        case 'M':  // a month / in a month / a month ago
+            return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
+        case 'MM': // 9 months / in 9 months / 9 months ago
+            if (withoutSuffix || isFuture) {
+                return result + (sk__plural(number) ? 'mesiace' : 'mesiacov');
+            } else {
+                return result + 'mesiacmi';
+            }
+            break;
+        case 'y':  // a year / in a year / a year ago
+            return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
+        case 'yy': // 9 years / in 9 years / 9 years ago
+            if (withoutSuffix || isFuture) {
+                return result + (sk__plural(number) ? 'roky' : 'rokov');
+            } else {
+                return result + 'rokmi';
+            }
+            break;
+        }
+    }
+
+    var sk = moment__default.defineLocale('sk', {
+        months : sk__months,
+        monthsShort : sk__monthsShort,
+        weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'),
+        weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'),
+        weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'),
+        longDateFormat : {
+            LT: 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY H:mm',
+            LLLL : 'dddd D. MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay: '[dnes o] LT',
+            nextDay: '[zajtra o] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v nedeľu o] LT';
+                case 1:
+                case 2:
+                    return '[v] dddd [o] LT';
+                case 3:
+                    return '[v stredu o] LT';
+                case 4:
+                    return '[vo štvrtok o] LT';
+                case 5:
+                    return '[v piatok o] LT';
+                case 6:
+                    return '[v sobotu o] LT';
+                }
+            },
+            lastDay: '[včera o] LT',
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[minulú nedeľu o] LT';
+                case 1:
+                case 2:
+                    return '[minulý] dddd [o] LT';
+                case 3:
+                    return '[minulú stredu o] LT';
+                case 4:
+                case 5:
+                    return '[minulý] dddd [o] LT';
+                case 6:
+                    return '[minulú sobotu o] LT';
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past : 'pred %s',
+            s : sk__translate,
+            m : sk__translate,
+            mm : sk__translate,
+            h : sk__translate,
+            hh : sk__translate,
+            d : sk__translate,
+            dd : sk__translate,
+            M : sk__translate,
+            MM : sk__translate,
+            y : sk__translate,
+            yy : sk__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : slovenian (sl)
+    //! author : Robert Sedovšek : https://github.com/sedovsek
+
+    function sl__processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var result = number + ' ';
+        switch (key) {
+        case 's':
+            return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami';
+        case 'm':
+            return withoutSuffix ? 'ena minuta' : 'eno minuto';
+        case 'mm':
+            if (number === 1) {
+                result += withoutSuffix ? 'minuta' : 'minuto';
+            } else if (number === 2) {
+                result += withoutSuffix || isFuture ? 'minuti' : 'minutama';
+            } else if (number < 5) {
+                result += withoutSuffix || isFuture ? 'minute' : 'minutami';
+            } else {
+                result += withoutSuffix || isFuture ? 'minut' : 'minutami';
+            }
+            return result;
+        case 'h':
+            return withoutSuffix ? 'ena ura' : 'eno uro';
+        case 'hh':
+            if (number === 1) {
+                result += withoutSuffix ? 'ura' : 'uro';
+            } else if (number === 2) {
+                result += withoutSuffix || isFuture ? 'uri' : 'urama';
+            } else if (number < 5) {
+                result += withoutSuffix || isFuture ? 'ure' : 'urami';
+            } else {
+                result += withoutSuffix || isFuture ? 'ur' : 'urami';
+            }
+            return result;
+        case 'd':
+            return withoutSuffix || isFuture ? 'en dan' : 'enim dnem';
+        case 'dd':
+            if (number === 1) {
+                result += withoutSuffix || isFuture ? 'dan' : 'dnem';
+            } else if (number === 2) {
+                result += withoutSuffix || isFuture ? 'dni' : 'dnevoma';
+            } else {
+                result += withoutSuffix || isFuture ? 'dni' : 'dnevi';
+            }
+            return result;
+        case 'M':
+            return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem';
+        case 'MM':
+            if (number === 1) {
+                result += withoutSuffix || isFuture ? 'mesec' : 'mesecem';
+            } else if (number === 2) {
+                result += withoutSuffix || isFuture ? 'meseca' : 'mesecema';
+            } else if (number < 5) {
+                result += withoutSuffix || isFuture ? 'mesece' : 'meseci';
+            } else {
+                result += withoutSuffix || isFuture ? 'mesecev' : 'meseci';
+            }
+            return result;
+        case 'y':
+            return withoutSuffix || isFuture ? 'eno leto' : 'enim letom';
+        case 'yy':
+            if (number === 1) {
+                result += withoutSuffix || isFuture ? 'leto' : 'letom';
+            } else if (number === 2) {
+                result += withoutSuffix || isFuture ? 'leti' : 'letoma';
+            } else if (number < 5) {
+                result += withoutSuffix || isFuture ? 'leta' : 'leti';
+            } else {
+                result += withoutSuffix || isFuture ? 'let' : 'leti';
+            }
+            return result;
+        }
+    }
+
+    var sl = moment__default.defineLocale('sl', {
+        months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'),
+        monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
+        monthsParseExact: true,
+        weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'),
+        weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'),
+        weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'H:mm',
+            LTS : 'H:mm:ss',
+            L : 'DD. MM. YYYY',
+            LL : 'D. MMMM YYYY',
+            LLL : 'D. MMMM YYYY H:mm',
+            LLLL : 'dddd, D. MMMM YYYY H:mm'
+        },
+        calendar : {
+            sameDay  : '[danes ob] LT',
+            nextDay  : '[jutri ob] LT',
+
+            nextWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[v] [nedeljo] [ob] LT';
+                case 3:
+                    return '[v] [sredo] [ob] LT';
+                case 6:
+                    return '[v] [soboto] [ob] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[v] dddd [ob] LT';
+                }
+            },
+            lastDay  : '[včeraj ob] LT',
+            lastWeek : function () {
+                switch (this.day()) {
+                case 0:
+                    return '[prejšnjo] [nedeljo] [ob] LT';
+                case 3:
+                    return '[prejšnjo] [sredo] [ob] LT';
+                case 6:
+                    return '[prejšnjo] [soboto] [ob] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[prejšnji] dddd [ob] LT';
+                }
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'čez %s',
+            past   : 'pred %s',
+            s      : sl__processRelativeTime,
+            m      : sl__processRelativeTime,
+            mm     : sl__processRelativeTime,
+            h      : sl__processRelativeTime,
+            hh     : sl__processRelativeTime,
+            d      : sl__processRelativeTime,
+            dd     : sl__processRelativeTime,
+            M      : sl__processRelativeTime,
+            MM     : sl__processRelativeTime,
+            y      : sl__processRelativeTime,
+            yy     : sl__processRelativeTime
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Albanian (sq)
+    //! author : Flakërim Ismani : https://github.com/flakerimi
+    //! author: Menelion Elensúle: https://github.com/Oire (tests)
+    //! author : Oerd Cukalla : https://github.com/oerd (fixes)
+
+    var sq = moment__default.defineLocale('sq', {
+        months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'),
+        monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'),
+        weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'),
+        weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'),
+        weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'),
+        weekdaysParseExact : true,
+        meridiemParse: /PD|MD/,
+        isPM: function (input) {
+            return input.charAt(0) === 'M';
+        },
+        meridiem : function (hours, minutes, isLower) {
+            return hours < 12 ? 'PD' : 'MD';
+        },
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[Sot në] LT',
+            nextDay : '[Nesër në] LT',
+            nextWeek : 'dddd [në] LT',
+            lastDay : '[Dje në] LT',
+            lastWeek : 'dddd [e kaluar në] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'në %s',
+            past : '%s më parë',
+            s : 'disa sekonda',
+            m : 'një minutë',
+            mm : '%d minuta',
+            h : 'një orë',
+            hh : '%d orë',
+            d : 'një ditë',
+            dd : '%d ditë',
+            M : 'një muaj',
+            MM : '%d muaj',
+            y : 'një vit',
+            yy : '%d vite'
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Serbian-cyrillic (sr-cyrl)
+    //! author : Milan Janačković<mi...@gmail.com> : https://github.com/milan-j
+
+    var sr_cyrl__translator = {
+        words: { //Different grammatical cases
+            m: ['један минут', 'једне минуте'],
+            mm: ['минут', 'минуте', 'минута'],
+            h: ['један сат', 'једног сата'],
+            hh: ['сат', 'сата', 'сати'],
+            dd: ['дан', 'дана', 'дана'],
+            MM: ['месец', 'месеца', 'месеци'],
+            yy: ['година', 'године', 'година']
+        },
+        correctGrammaticalCase: function (number, wordKey) {
+            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+        },
+        translate: function (number, withoutSuffix, key) {
+            var wordKey = sr_cyrl__translator.words[key];
+            if (key.length === 1) {
+                return withoutSuffix ? wordKey[0] : wordKey[1];
+            } else {
+                return number + ' ' + sr_cyrl__translator.correctGrammaticalCase(number, wordKey);
+            }
+        }
+    };
+
+    var sr_cyrl = moment__default.defineLocale('sr-cyrl', {
+        months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'),
+        monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'),
+        monthsParseExact: true,
+        weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'),
+        weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'),
+        weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat: {
+            LT: 'H:mm',
+            LTS : 'H:mm:ss',
+            L: 'DD. MM. YYYY',
+            LL: 'D. MMMM YYYY',
+            LLL: 'D. MMMM YYYY H:mm',
+            LLLL: 'dddd, D. MMMM YYYY H:mm'
+        },
+        calendar: {
+            sameDay: '[данас у] LT',
+            nextDay: '[сутра у] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[у] [недељу] [у] LT';
+                case 3:
+                    return '[у] [среду] [у] LT';
+                case 6:
+                    return '[у] [суботу] [у] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[у] dddd [у] LT';
+                }
+            },
+            lastDay  : '[јуче у] LT',
+            lastWeek : function () {
+                var lastWeekDays = [
+                    '[прошле] [недеље] [у] LT',
+                    '[прошлог] [понедељка] [у] LT',
+                    '[прошлог] [уторка] [у] LT',
+                    '[прошле] [среде] [у] LT',
+                    '[прошлог] [четвртка] [у] LT',
+                    '[прошлог] [петка] [у] LT',
+                    '[прошле] [суботе] [у] LT'
+                ];
+                return lastWeekDays[this.day()];
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'за %s',
+            past   : 'пре %s',
+            s      : 'неколико секунди',
+            m      : sr_cyrl__translator.translate,
+            mm     : sr_cyrl__translator.translate,
+            h      : sr_cyrl__translator.translate,
+            hh     : sr_cyrl__translator.translate,
+            d      : 'дан',
+            dd     : sr_cyrl__translator.translate,
+            M      : 'месец',
+            MM     : sr_cyrl__translator.translate,
+            y      : 'годину',
+            yy     : sr_cyrl__translator.translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Serbian-latin (sr)
+    //! author : Milan Janačković<mi...@gmail.com> : https://github.com/milan-j
+
+    var sr__translator = {
+        words: { //Different grammatical cases
+            m: ['jedan minut', 'jedne minute'],
+            mm: ['minut', 'minute', 'minuta'],
+            h: ['jedan sat', 'jednog sata'],
+            hh: ['sat', 'sata', 'sati'],
+            dd: ['dan', 'dana', 'dana'],
+            MM: ['mesec', 'meseca', 'meseci'],
+            yy: ['godina', 'godine', 'godina']
+        },
+        correctGrammaticalCase: function (number, wordKey) {
+            return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+        },
+        translate: function (number, withoutSuffix, key) {
+            var wordKey = sr__translator.words[key];
+            if (key.length === 1) {
+                return withoutSuffix ? wordKey[0] : wordKey[1];
+            } else {
+                return number + ' ' + sr__translator.correctGrammaticalCase(number, wordKey);
+            }
+        }
+    };
+
+    var sr = moment__default.defineLocale('sr', {
+        months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
+        monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
+        monthsParseExact: true,
+        weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'),
+        weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'),
+        weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat: {
+            LT: 'H:mm',
+            LTS : 'H:mm:ss',
+            L: 'DD. MM. YYYY',
+            LL: 'D. MMMM YYYY',
+            LLL: 'D. MMMM YYYY H:mm',
+            LLLL: 'dddd, D. MMMM YYYY H:mm'
+        },
+        calendar: {
+            sameDay: '[danas u] LT',
+            nextDay: '[sutra u] LT',
+            nextWeek: function () {
+                switch (this.day()) {
+                case 0:
+                    return '[u] [nedelju] [u] LT';
+                case 3:
+                    return '[u] [sredu] [u] LT';
+                case 6:
+                    return '[u] [subotu] [u] LT';
+                case 1:
+                case 2:
+                case 4:
+                case 5:
+                    return '[u] dddd [u] LT';
+                }
+            },
+            lastDay  : '[juče u] LT',
+            lastWeek : function () {
+                var lastWeekDays = [
+                    '[prošle] [nedelje] [u] LT',
+                    '[prošlog] [ponedeljka] [u] LT',
+                    '[prošlog] [utorka] [u] LT',
+                    '[prošle] [srede] [u] LT',
+                    '[prošlog] [četvrtka] [u] LT',
+                    '[prošlog] [petka] [u] LT',
+                    '[prošle] [subote] [u] LT'
+                ];
+                return lastWeekDays[this.day()];
+            },
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'za %s',
+            past   : 'pre %s',
+            s      : 'nekoliko sekundi',
+            m      : sr__translator.translate,
+            mm     : sr__translator.translate,
+            h      : sr__translator.translate,
+            hh     : sr__translator.translate,
+            d      : 'dan',
+            dd     : sr__translator.translate,
+            M      : 'mesec',
+            MM     : sr__translator.translate,
+            y      : 'godinu',
+            yy     : sr__translator.translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : siSwati (ss)
+    //! author : Nicolai Davies<ma...@nicolai.io> : https://github.com/nicolaidavies
+
+
+    var ss = moment__default.defineLocale('ss', {
+        months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'),
+        monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'),
+        weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'),
+        weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'),
+        weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'h:mm A',
+            LTS : 'h:mm:ss A',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY h:mm A',
+            LLLL : 'dddd, D MMMM YYYY h:mm A'
+        },
+        calendar : {
+            sameDay : '[Namuhla nga] LT',
+            nextDay : '[Kusasa nga] LT',
+            nextWeek : 'dddd [nga] LT',
+            lastDay : '[Itolo nga] LT',
+            lastWeek : 'dddd [leliphelile] [nga] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'nga %s',
+            past : 'wenteka nga %s',
+            s : 'emizuzwana lomcane',
+            m : 'umzuzu',
+            mm : '%d emizuzu',
+            h : 'lihora',
+            hh : '%d emahora',
+            d : 'lilanga',
+            dd : '%d emalanga',
+            M : 'inyanga',
+            MM : '%d tinyanga',
+            y : 'umnyaka',
+            yy : '%d iminyaka'
+        },
+        meridiemParse: /ekuseni|emini|entsambama|ebusuku/,
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 11) {
+                return 'ekuseni';
+            } else if (hours < 15) {
+                return 'emini';
+            } else if (hours < 19) {
+                return 'entsambama';
+            } else {
+                return 'ebusuku';
+            }
+        },
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'ekuseni') {
+                return hour;
+            } else if (meridiem === 'emini') {
+                return hour >= 11 ? hour : hour + 12;
+            } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') {
+                if (hour === 0) {
+                    return 0;
+                }
+                return hour + 12;
+            }
+        },
+        ordinalParse: /\d{1,2}/,
+        ordinal : '%d',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : swedish (sv)
+    //! author : Jens Alm : https://github.com/ulmus
+
+    var sv = moment__default.defineLocale('sv', {
+        months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'),
+        monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+        weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
+        weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
+        weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'YYYY-MM-DD',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY [kl.] HH:mm',
+            LLLL : 'dddd D MMMM YYYY [kl.] HH:mm',
+            lll : 'D MMM YYYY HH:mm',
+            llll : 'ddd D MMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Idag] LT',
+            nextDay: '[Imorgon] LT',
+            lastDay: '[Igår] LT',
+            nextWeek: '[På] dddd LT',
+            lastWeek: '[I] dddd[s] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'om %s',
+            past : 'för %s sedan',
+            s : 'några sekunder',
+            m : 'en minut',
+            mm : '%d minuter',
+            h : 'en timme',
+            hh : '%d timmar',
+            d : 'en dag',
+            dd : '%d dagar',
+            M : 'en månad',
+            MM : '%d månader',
+            y : 'ett år',
+            yy : '%d år'
+        },
+        ordinalParse: /\d{1,2}(e|a)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'e' :
+                (b === 1) ? 'a' :
+                (b === 2) ? 'a' :
+                (b === 3) ? 'e' : 'e';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : swahili (sw)
+    //! author : Fahad Kassim : https://github.com/fadsel
+
+    var sw = moment__default.defineLocale('sw', {
+        months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'),
+        monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'),
+        weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'),
+        weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'),
+        weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[leo saa] LT',
+            nextDay : '[kesho saa] LT',
+            nextWeek : '[wiki ijayo] dddd [saat] LT',
+            lastDay : '[jana] LT',
+            lastWeek : '[wiki iliyopita] dddd [saat] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s baadaye',
+            past : 'tokea %s',
+            s : 'hivi punde',
+            m : 'dakika moja',
+            mm : 'dakika %d',
+            h : 'saa limoja',
+            hh : 'masaa %d',
+            d : 'siku moja',
+            dd : 'masiku %d',
+            M : 'mwezi mmoja',
+            MM : 'miezi %d',
+            y : 'mwaka mmoja',
+            yy : 'miaka %d'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : tamil (ta)
+    //! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
+
+    var ta__symbolMap = {
+        '1': '௧',
+        '2': '௨',
+        '3': '௩',
+        '4': '௪',
+        '5': '௫',
+        '6': '௬',
+        '7': '௭',
+        '8': '௮',
+        '9': '௯',
+        '0': '௦'
+    }, ta__numberMap = {
+        '௧': '1',
+        '௨': '2',
+        '௩': '3',
+        '௪': '4',
+        '௫': '5',
+        '௬': '6',
+        '௭': '7',
+        '௮': '8',
+        '௯': '9',
+        '௦': '0'
+    };
+
+    var ta = moment__default.defineLocale('ta', {
+        months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+        monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+        weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'),
+        weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'),
+        weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, HH:mm',
+            LLLL : 'dddd, D MMMM YYYY, HH:mm'
+        },
+        calendar : {
+            sameDay : '[இன்று] LT',
+            nextDay : '[நாளை] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[நேற்று] LT',
+            lastWeek : '[கடந்த வாரம்] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s இல்',
+            past : '%s முன்',
+            s : 'ஒரு சில விநாடிகள்',
+            m : 'ஒரு நிமிடம்',
+            mm : '%d நிமிடங்கள்',
+            h : 'ஒரு மணி நேரம்',
+            hh : '%d மணி நேரம்',
+            d : 'ஒரு நாள்',
+            dd : '%d நாட்கள்',
+            M : 'ஒரு மாதம்',
+            MM : '%d மாதங்கள்',
+            y : 'ஒரு வருடம்',
+            yy : '%d ஆண்டுகள்'
+        },
+        ordinalParse: /\d{1,2}வது/,
+        ordinal : function (number) {
+            return number + 'வது';
+        },
+        preparse: function (string) {
+            return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
+                return ta__numberMap[match];
+            });
+        },
+        postformat: function (string) {
+            return string.replace(/\d/g, function (match) {
+                return ta__symbolMap[match];
+            });
+        },
+        // refer http://ta.wikipedia.org/s/1er1
+        meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 2) {
+                return ' யாமம்';
+            } else if (hour < 6) {
+                return ' வைகறை';  // வைகறை
+            } else if (hour < 10) {
+                return ' காலை'; // காலை
+            } else if (hour < 14) {
+                return ' நண்பகல்'; // நண்பகல்
+            } else if (hour < 18) {
+                return ' எற்பாடு'; // எற்பாடு
+            } else if (hour < 22) {
+                return ' மாலை'; // மாலை
+            } else {
+                return ' யாமம்';
+            }
+        },
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'யாமம்') {
+                return hour < 2 ? hour : hour + 12;
+            } else if (meridiem === 'வைகறை' || meridiem === 'காலை') {
+                return hour;
+            } else if (meridiem === 'நண்பகல்') {
+                return hour >= 10 ? hour : hour + 12;
+            } else {
+                return hour + 12;
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : telugu (te)
+    //! author : Krishna Chaitanya Thota : https://github.com/kcthota
+
+    var te = moment__default.defineLocale('te', {
+        months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'),
+        monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'),
+        weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'),
+        weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'),
+        longDateFormat : {
+            LT : 'A h:mm',
+            LTS : 'A h:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY, A h:mm',
+            LLLL : 'dddd, D MMMM YYYY, A h:mm'
+        },
+        calendar : {
+            sameDay : '[నేడు] LT',
+            nextDay : '[రేపు] LT',
+            nextWeek : 'dddd, LT',
+            lastDay : '[నిన్న] LT',
+            lastWeek : '[గత] dddd, LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s లో',
+            past : '%s క్రితం',
+            s : 'కొన్ని క్షణాలు',
+            m : 'ఒక నిమిషం',
+            mm : '%d నిమిషాలు',
+            h : 'ఒక గంట',
+            hh : '%d గంటలు',
+            d : 'ఒక రోజు',
+            dd : '%d రోజులు',
+            M : 'ఒక నెల',
+            MM : '%d నెలలు',
+            y : 'ఒక సంవత్సరం',
+            yy : '%d సంవత్సరాలు'
+        },
+        ordinalParse : /\d{1,2}వ/,
+        ordinal : '%dవ',
+        meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === 'రాత్రి') {
+                return hour < 4 ? hour : hour + 12;
+            } else if (meridiem === 'ఉదయం') {
+                return hour;
+            } else if (meridiem === 'మధ్యాహ్నం') {
+                return hour >= 10 ? hour : hour + 12;
+            } else if (meridiem === 'సాయంత్రం') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'రాత్రి';
+            } else if (hour < 10) {
+                return 'ఉదయం';
+            } else if (hour < 17) {
+                return 'మధ్యాహ్నం';
+            } else if (hour < 20) {
+                return 'సాయంత్రం';
+            } else {
+                return 'రాత్రి';
+            }
+        },
+        week : {
+            dow : 0, // Sunday is the first day of the week.
+            doy : 6  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : thai (th)
+    //! author : Kridsada Thanabulpong : https://github.com/sirn
+
+    var th = moment__default.defineLocale('th', {
+        months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'),
+        monthsShort : 'มกรา_กุมภา_มีนา_เมษา_พฤษภา_มิถุนา_กรกฎา_สิงหา_กันยา_ตุลา_พฤศจิกา_ธันวา'.split('_'),
+        monthsParseExact: true,
+        weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
+        weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference
+        weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'H นาฬิกา m นาที',
+            LTS : 'H นาฬิกา m นาที s วินาที',
+            L : 'YYYY/MM/DD',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY เวลา H นาฬิกา m นาที',
+            LLLL : 'วันddddที่ D MMMM YYYY เวลา H นาฬิกา m นาที'
+        },
+        meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/,
+        isPM: function (input) {
+            return input === 'หลังเที่ยง';
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 12) {
+                return 'ก่อนเที่ยง';
+            } else {
+                return 'หลังเที่ยง';
+            }
+        },
+        calendar : {
+            sameDay : '[วันนี้ เวลา] LT',
+            nextDay : '[พรุ่งนี้ เวลา] LT',
+            nextWeek : 'dddd[หน้า เวลา] LT',
+            lastDay : '[เมื่อวานนี้ เวลา] LT',
+            lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'อีก %s',
+            past : '%sที่แล้ว',
+            s : 'ไม่กี่วินาที',
+            m : '1 นาที',
+            mm : '%d นาที',
+            h : '1 ชั่วโมง',
+            hh : '%d ชั่วโมง',
+            d : '1 วัน',
+            dd : '%d วัน',
+            M : '1 เดือน',
+            MM : '%d เดือน',
+            y : '1 ปี',
+            yy : '%d ปี'
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Tagalog/Filipino (tl-ph)
+    //! author : Dan Hagman
+
+    var tl_ph = moment__default.defineLocale('tl-ph', {
+        months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'),
+        monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
+        weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'),
+        weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
+        weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'MM/D/YYYY',
+            LL : 'MMMM D, YYYY',
+            LLL : 'MMMM D, YYYY HH:mm',
+            LLLL : 'dddd, MMMM DD, YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Ngayon sa] LT',
+            nextDay: '[Bukas sa] LT',
+            nextWeek: 'dddd [sa] LT',
+            lastDay: '[Kahapon sa] LT',
+            lastWeek: 'dddd [huling linggo] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'sa loob ng %s',
+            past : '%s ang nakalipas',
+            s : 'ilang segundo',
+            m : 'isang minuto',
+            mm : '%d minuto',
+            h : 'isang oras',
+            hh : '%d oras',
+            d : 'isang araw',
+            dd : '%d araw',
+            M : 'isang buwan',
+            MM : '%d buwan',
+            y : 'isang taon',
+            yy : '%d taon'
+        },
+        ordinalParse: /\d{1,2}/,
+        ordinal : function (number) {
+            return number;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Klingon (tlh)
+    //! author : Dominika Kruk : https://github.com/amaranthrose
+
+    var numbersNouns = 'pagh_wa’_cha’_wej_loS_vagh_jav_Soch_chorgh_Hut'.split('_');
+
+    function translateFuture(output) {
+        var time = output;
+        time = (output.indexOf('jaj') !== -1) ?
+    	time.slice(0, -3) + 'leS' :
+    	(output.indexOf('jar') !== -1) ?
+    	time.slice(0, -3) + 'waQ' :
+    	(output.indexOf('DIS') !== -1) ?
+    	time.slice(0, -3) + 'nem' :
+    	time + ' pIq';
+        return time;
+    }
+
+    function translatePast(output) {
+        var time = output;
+        time = (output.indexOf('jaj') !== -1) ?
+    	time.slice(0, -3) + 'Hu’' :
+    	(output.indexOf('jar') !== -1) ?
+    	time.slice(0, -3) + 'wen' :
+    	(output.indexOf('DIS') !== -1) ?
+    	time.slice(0, -3) + 'ben' :
+    	time + ' ret';
+        return time;
+    }
+
+    function tlh__translate(number, withoutSuffix, string, isFuture) {
+        var numberNoun = numberAsNoun(number);
+        switch (string) {
+            case 'mm':
+                return numberNoun + ' tup';
+            case 'hh':
+                return numberNoun + ' rep';
+            case 'dd':
+                return numberNoun + ' jaj';
+            case 'MM':
+                return numberNoun + ' jar';
+            case 'yy':
+                return numberNoun + ' DIS';
+        }
+    }
+
+    function numberAsNoun(number) {
+        var hundred = Math.floor((number % 1000) / 100),
+    	ten = Math.floor((number % 100) / 10),
+    	one = number % 10,
+    	word = '';
+        if (hundred > 0) {
+            word += numbersNouns[hundred] + 'vatlh';
+        }
+        if (ten > 0) {
+            word += ((word !== '') ? ' ' : '') + numbersNouns[ten] + 'maH';
+        }
+        if (one > 0) {
+            word += ((word !== '') ? ' ' : '') + numbersNouns[one];
+        }
+        return (word === '') ? 'pagh' : word;
+    }
+
+    var tlh = moment__default.defineLocale('tlh', {
+        months : 'tera’ jar wa’_tera’ jar cha’_tera’ jar wej_tera’ jar loS_tera’ jar vagh_tera’ jar jav_tera’ jar Soch_tera’ jar chorgh_tera’ jar Hut_tera’ jar wa’maH_tera’ jar wa’maH wa’_tera’ jar wa’maH cha’'.split('_'),
+        monthsShort : 'jar wa’_jar cha’_jar wej_jar loS_jar vagh_jar jav_jar Soch_jar chorgh_jar Hut_jar wa’maH_jar wa’maH wa’_jar wa’maH cha’'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
+        weekdaysShort : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
+        weekdaysMin : 'lojmItjaj_DaSjaj_povjaj_ghItlhjaj_loghjaj_buqjaj_ghInjaj'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[DaHjaj] LT',
+            nextDay: '[wa’leS] LT',
+            nextWeek: 'LLL',
+            lastDay: '[wa’Hu’] LT',
+            lastWeek: 'LLL',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : translateFuture,
+            past : translatePast,
+            s : 'puS lup',
+            m : 'wa’ tup',
+            mm : tlh__translate,
+            h : 'wa’ rep',
+            hh : tlh__translate,
+            d : 'wa’ jaj',
+            dd : tlh__translate,
+            M : 'wa’ jar',
+            MM : tlh__translate,
+            y : 'wa’ DIS',
+            yy : tlh__translate
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : turkish (tr)
+    //! authors : Erhan Gundogan : https://github.com/erhangundogan,
+    //!           Burak Yiğit Kaya: https://github.com/BYK
+
+    var tr__suffixes = {
+        1: '\'inci',
+        5: '\'inci',
+        8: '\'inci',
+        70: '\'inci',
+        80: '\'inci',
+        2: '\'nci',
+        7: '\'nci',
+        20: '\'nci',
+        50: '\'nci',
+        3: '\'üncü',
+        4: '\'üncü',
+        100: '\'üncü',
+        6: '\'ncı',
+        9: '\'uncu',
+        10: '\'uncu',
+        30: '\'uncu',
+        60: '\'ıncı',
+        90: '\'ıncı'
+    };
+
+    var tr = moment__default.defineLocale('tr', {
+        months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
+        monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
+        weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
+        weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
+        weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[bugün saat] LT',
+            nextDay : '[yarın saat] LT',
+            nextWeek : '[haftaya] dddd [saat] LT',
+            lastDay : '[dün] LT',
+            lastWeek : '[geçen hafta] dddd [saat] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : '%s sonra',
+            past : '%s önce',
+            s : 'birkaç saniye',
+            m : 'bir dakika',
+            mm : '%d dakika',
+            h : 'bir saat',
+            hh : '%d saat',
+            d : 'bir gün',
+            dd : '%d gün',
+            M : 'bir ay',
+            MM : '%d ay',
+            y : 'bir yıl',
+            yy : '%d yıl'
+        },
+        ordinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
+        ordinal : function (number) {
+            if (number === 0) {  // special case for zero
+                return number + '\'ıncı';
+            }
+            var a = number % 10,
+                b = number % 100 - a,
+                c = number >= 100 ? 100 : null;
+            return number + (tr__suffixes[a] || tr__suffixes[b] || tr__suffixes[c]);
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : talossan (tzl)
+    //! author : Robin van der Vliet : https://github.com/robin0van0der0v with the help of Iustì Canun
+
+
+    // After the year there should be a slash and the amount of years since December 26, 1979 in Roman numerals.
+    // This is currently too difficult (maybe even impossible) to add.
+    var tzl = moment__default.defineLocale('tzl', {
+        months : 'Januar_Fevraglh_Març_Avrïu_Mai_Gün_Julia_Guscht_Setemvar_Listopäts_Noemvar_Zecemvar'.split('_'),
+        monthsShort : 'Jan_Fev_Mar_Avr_Mai_Gün_Jul_Gus_Set_Lis_Noe_Zec'.split('_'),
+        weekdays : 'Súladi_Lúneçi_Maitzi_Márcuri_Xhúadi_Viénerçi_Sáturi'.split('_'),
+        weekdaysShort : 'Súl_Lún_Mai_Már_Xhú_Vié_Sát'.split('_'),
+        weekdaysMin : 'Sú_Lú_Ma_Má_Xh_Vi_Sá'.split('_'),
+        longDateFormat : {
+            LT : 'HH.mm',
+            LTS : 'HH.mm.ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D. MMMM [dallas] YYYY',
+            LLL : 'D. MMMM [dallas] YYYY HH.mm',
+            LLLL : 'dddd, [li] D. MMMM [dallas] YYYY HH.mm'
+        },
+        meridiemParse: /d\'o|d\'a/i,
+        isPM : function (input) {
+            return 'd\'o' === input.toLowerCase();
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours > 11) {
+                return isLower ? 'd\'o' : 'D\'O';
+            } else {
+                return isLower ? 'd\'a' : 'D\'A';
+            }
+        },
+        calendar : {
+            sameDay : '[oxhi à] LT',
+            nextDay : '[demà à] LT',
+            nextWeek : 'dddd [à] LT',
+            lastDay : '[ieiri à] LT',
+            lastWeek : '[sür el] dddd [lasteu à] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'osprei %s',
+            past : 'ja%s',
+            s : tzl__processRelativeTime,
+            m : tzl__processRelativeTime,
+            mm : tzl__processRelativeTime,
+            h : tzl__processRelativeTime,
+            hh : tzl__processRelativeTime,
+            d : tzl__processRelativeTime,
+            dd : tzl__processRelativeTime,
+            M : tzl__processRelativeTime,
+            MM : tzl__processRelativeTime,
+            y : tzl__processRelativeTime,
+            yy : tzl__processRelativeTime
+        },
+        ordinalParse: /\d{1,2}\./,
+        ordinal : '%d.',
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    function tzl__processRelativeTime(number, withoutSuffix, key, isFuture) {
+        var format = {
+            's': ['viensas secunds', '\'iensas secunds'],
+            'm': ['\'n míut', '\'iens míut'],
+            'mm': [number + ' míuts', '' + number + ' míuts'],
+            'h': ['\'n þora', '\'iensa þora'],
+            'hh': [number + ' þoras', '' + number + ' þoras'],
+            'd': ['\'n ziua', '\'iensa ziua'],
+            'dd': [number + ' ziuas', '' + number + ' ziuas'],
+            'M': ['\'n mes', '\'iens mes'],
+            'MM': [number + ' mesen', '' + number + ' mesen'],
+            'y': ['\'n ar', '\'iens ar'],
+            'yy': [number + ' ars', '' + number + ' ars']
+        };
+        return isFuture ? format[key][0] : (withoutSuffix ? format[key][0] : format[key][1]);
+    }
+
+    //! moment.js locale configuration
+    //! locale : Morocco Central Atlas Tamaziɣt in Latin (tzm-latn)
+    //! author : Abdel Said : https://github.com/abdelsaid
+
+    var tzm_latn = moment__default.defineLocale('tzm-latn', {
+        months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+        monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+        weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+        weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+        weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[asdkh g] LT',
+            nextDay: '[aska g] LT',
+            nextWeek: 'dddd [g] LT',
+            lastDay: '[assant g] LT',
+            lastWeek: 'dddd [g] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'dadkh s yan %s',
+            past : 'yan %s',
+            s : 'imik',
+            m : 'minuḍ',
+            mm : '%d minuḍ',
+            h : 'saɛa',
+            hh : '%d tassaɛin',
+            d : 'ass',
+            dd : '%d ossan',
+            M : 'ayowr',
+            MM : '%d iyyirn',
+            y : 'asgas',
+            yy : '%d isgasn'
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : Morocco Central Atlas Tamaziɣt (tzm)
+    //! author : Abdel Said : https://github.com/abdelsaid
+
+    var tzm = moment__default.defineLocale('tzm', {
+        months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+        monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+        weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+        weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+        weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS: 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[ⴰⵙⴷⵅ ⴴ] LT',
+            nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
+            nextWeek: 'dddd [ⴴ] LT',
+            lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
+            lastWeek: 'dddd [ⴴ] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s',
+            past : 'ⵢⴰⵏ %s',
+            s : 'ⵉⵎⵉⴽ',
+            m : 'ⵎⵉⵏⵓⴺ',
+            mm : '%d ⵎⵉⵏⵓⴺ',
+            h : 'ⵙⴰⵄⴰ',
+            hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ',
+            d : 'ⴰⵙⵙ',
+            dd : '%d oⵙⵙⴰⵏ',
+            M : 'ⴰⵢoⵓⵔ',
+            MM : '%d ⵉⵢⵢⵉⵔⵏ',
+            y : 'ⴰⵙⴳⴰⵙ',
+            yy : '%d ⵉⵙⴳⴰⵙⵏ'
+        },
+        week : {
+            dow : 6, // Saturday is the first day of the week.
+            doy : 12  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : ukrainian (uk)
+    //! author : zemlanin : https://github.com/zemlanin
+    //! Author : Menelion Elensúle : https://github.com/Oire
+
+    function uk__plural(word, num) {
+        var forms = word.split('_');
+        return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+    }
+    function uk__relativeTimeWithPlural(number, withoutSuffix, key) {
+        var format = {
+            'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин',
+            'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин',
+            'dd': 'день_дні_днів',
+            'MM': 'місяць_місяці_місяців',
+            'yy': 'рік_роки_років'
+        };
+        if (key === 'm') {
+            return withoutSuffix ? 'хвилина' : 'хвилину';
+        }
+        else if (key === 'h') {
+            return withoutSuffix ? 'година' : 'годину';
+        }
+        else {
+            return number + ' ' + uk__plural(format[key], +number);
+        }
+    }
+    function weekdaysCaseReplace(m, format) {
+        var weekdays = {
+            'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
+            'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
+            'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
+        },
+        nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
+            'accusative' :
+            ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
+                'genitive' :
+                'nominative');
+        return weekdays[nounCase][m.day()];
+    }
+    function processHoursFunction(str) {
+        return function () {
+            return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
+        };
+    }
+
+    var uk = moment__default.defineLocale('uk', {
+        months : {
+            'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'),
+            'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_')
+        },
+        monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'),
+        weekdays : weekdaysCaseReplace,
+        weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+        weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD.MM.YYYY',
+            LL : 'D MMMM YYYY р.',
+            LLL : 'D MMMM YYYY р., HH:mm',
+            LLLL : 'dddd, D MMMM YYYY р., HH:mm'
+        },
+        calendar : {
+            sameDay: processHoursFunction('[Сьогодні '),
+            nextDay: processHoursFunction('[Завтра '),
+            lastDay: processHoursFunction('[Вчора '),
+            nextWeek: processHoursFunction('[У] dddd ['),
+            lastWeek: function () {
+                switch (this.day()) {
+                case 0:
+                case 3:
+                case 5:
+                case 6:
+                    return processHoursFunction('[Минулої] dddd [').call(this);
+                case 1:
+                case 2:
+                case 4:
+                    return processHoursFunction('[Минулого] dddd [').call(this);
+                }
+            },
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : 'за %s',
+            past : '%s тому',
+            s : 'декілька секунд',
+            m : uk__relativeTimeWithPlural,
+            mm : uk__relativeTimeWithPlural,
+            h : 'годину',
+            hh : uk__relativeTimeWithPlural,
+            d : 'день',
+            dd : uk__relativeTimeWithPlural,
+            M : 'місяць',
+            MM : uk__relativeTimeWithPlural,
+            y : 'рік',
+            yy : uk__relativeTimeWithPlural
+        },
+        // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
+        meridiemParse: /ночі|ранку|дня|вечора/,
+        isPM: function (input) {
+            return /^(дня|вечора)$/.test(input);
+        },
+        meridiem : function (hour, minute, isLower) {
+            if (hour < 4) {
+                return 'ночі';
+            } else if (hour < 12) {
+                return 'ранку';
+            } else if (hour < 17) {
+                return 'дня';
+            } else {
+                return 'вечора';
+            }
+        },
+        ordinalParse: /\d{1,2}-(й|го)/,
+        ordinal: function (number, period) {
+            switch (period) {
+            case 'M':
+            case 'd':
+            case 'DDD':
+            case 'w':
+            case 'W':
+                return number + '-й';
+            case 'D':
+                return number + '-го';
+            default:
+                return number;
+            }
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 1st is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : uzbek (uz)
+    //! author : Sardor Muminov : https://github.com/muminoff
+
+    var uz = moment__default.defineLocale('uz', {
+        months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'),
+        monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
+        weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
+        weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'),
+        weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'D MMMM YYYY, dddd HH:mm'
+        },
+        calendar : {
+            sameDay : '[Бугун соат] LT [да]',
+            nextDay : '[Эртага] LT [да]',
+            nextWeek : 'dddd [куни соат] LT [да]',
+            lastDay : '[Кеча соат] LT [да]',
+            lastWeek : '[Утган] dddd [куни соат] LT [да]',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'Якин %s ичида',
+            past : 'Бир неча %s олдин',
+            s : 'фурсат',
+            m : 'бир дакика',
+            mm : '%d дакика',
+            h : 'бир соат',
+            hh : '%d соат',
+            d : 'бир кун',
+            dd : '%d кун',
+            M : 'бир ой',
+            MM : '%d ой',
+            y : 'бир йил',
+            yy : '%d йил'
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 7  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : vietnamese (vi)
+    //! author : Bang Nguyen : https://github.com/bangnk
+
+    var vi = moment__default.defineLocale('vi', {
+        months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'),
+        monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'),
+        weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+        weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+        weekdaysParseExact : true,
+        meridiemParse: /sa|ch/i,
+        isPM : function (input) {
+            return /^ch$/i.test(input);
+        },
+        meridiem : function (hours, minutes, isLower) {
+            if (hours < 12) {
+                return isLower ? 'sa' : 'SA';
+            } else {
+                return isLower ? 'ch' : 'CH';
+            }
+        },
+        longDateFormat : {
+            LT : 'HH:mm',
+            LTS : 'HH:mm:ss',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM [năm] YYYY',
+            LLL : 'D MMMM [năm] YYYY HH:mm',
+            LLLL : 'dddd, D MMMM [năm] YYYY HH:mm',
+            l : 'DD/M/YYYY',
+            ll : 'D MMM YYYY',
+            lll : 'D MMM YYYY HH:mm',
+            llll : 'ddd, D MMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay: '[Hôm nay lúc] LT',
+            nextDay: '[Ngày mai lúc] LT',
+            nextWeek: 'dddd [tuần tới lúc] LT',
+            lastDay: '[Hôm qua lúc] LT',
+            lastWeek: 'dddd [tuần rồi lúc] LT',
+            sameElse: 'L'
+        },
+        relativeTime : {
+            future : '%s tới',
+            past : '%s trước',
+            s : 'vài giây',
+            m : 'một phút',
+            mm : '%d phút',
+            h : 'một giờ',
+            hh : '%d giờ',
+            d : 'một ngày',
+            dd : '%d ngày',
+            M : 'một tháng',
+            MM : '%d tháng',
+            y : 'một năm',
+            yy : '%d năm'
+        },
+        ordinalParse: /\d{1,2}/,
+        ordinal : function (number) {
+            return number;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : pseudo (x-pseudo)
+    //! author : Andrew Hood : https://github.com/andrewhood125
+
+    var x_pseudo = moment__default.defineLocale('x-pseudo', {
+        months : 'J~áñúá~rý_F~ébrú~árý_~Márc~h_Áp~ríl_~Máý_~Júñé~_Júl~ý_Áú~gúst~_Sép~témb~ér_Ó~ctób~ér_Ñ~óvém~bér_~Décé~mbér'.split('_'),
+        monthsShort : 'J~áñ_~Féb_~Már_~Ápr_~Máý_~Júñ_~Júl_~Áúg_~Sép_~Óct_~Ñóv_~Déc'.split('_'),
+        monthsParseExact : true,
+        weekdays : 'S~úñdá~ý_Mó~ñdáý~_Túé~sdáý~_Wéd~ñésd~áý_T~húrs~dáý_~Fríd~áý_S~átúr~dáý'.split('_'),
+        weekdaysShort : 'S~úñ_~Móñ_~Túé_~Wéd_~Thú_~Frí_~Sát'.split('_'),
+        weekdaysMin : 'S~ú_Mó~_Tú_~Wé_T~h_Fr~_Sá'.split('_'),
+        weekdaysParseExact : true,
+        longDateFormat : {
+            LT : 'HH:mm',
+            L : 'DD/MM/YYYY',
+            LL : 'D MMMM YYYY',
+            LLL : 'D MMMM YYYY HH:mm',
+            LLLL : 'dddd, D MMMM YYYY HH:mm'
+        },
+        calendar : {
+            sameDay : '[T~ódá~ý át] LT',
+            nextDay : '[T~ómó~rró~w át] LT',
+            nextWeek : 'dddd [át] LT',
+            lastDay : '[Ý~ést~érdá~ý át] LT',
+            lastWeek : '[L~ást] dddd [át] LT',
+            sameElse : 'L'
+        },
+        relativeTime : {
+            future : 'í~ñ %s',
+            past : '%s á~gó',
+            s : 'á ~féw ~sécó~ñds',
+            m : 'á ~míñ~úté',
+            mm : '%d m~íñú~tés',
+            h : 'á~ñ hó~úr',
+            hh : '%d h~óúrs',
+            d : 'á ~dáý',
+            dd : '%d d~áýs',
+            M : 'á ~móñ~th',
+            MM : '%d m~óñt~hs',
+            y : 'á ~ýéár',
+            yy : '%d ý~éárs'
+        },
+        ordinalParse: /\d{1,2}(th|st|nd|rd)/,
+        ordinal : function (number) {
+            var b = number % 10,
+                output = (~~(number % 100 / 10) === 1) ? 'th' :
+                (b === 1) ? 'st' :
+                (b === 2) ? 'nd' :
+                (b === 3) ? 'rd' : 'th';
+            return number + output;
+        },
+        week : {
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : chinese (zh-cn)
+    //! author : suupic : https://github.com/suupic
+    //! author : Zeno Zeng : https://github.com/zenozeng
+
+    var zh_cn = moment__default.defineLocale('zh-cn', {
+        months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+        weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'),
+        weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+        longDateFormat : {
+            LT : 'Ah点mm分',
+            LTS : 'Ah点m分s秒',
+            L : 'YYYY-MM-DD',
+            LL : 'YYYY年MMMD日',
+            LLL : 'YYYY年MMMD日Ah点mm分',
+            LLLL : 'YYYY年MMMD日ddddAh点mm分',
+            l : 'YYYY-MM-DD',
+            ll : 'YYYY年MMMD日',
+            lll : 'YYYY年MMMD日Ah点mm分',
+            llll : 'YYYY年MMMD日ddddAh点mm分'
+        },
+        meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+        meridiemHour: function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === '凌晨' || meridiem === '早上' ||
+                    meridiem === '上午') {
+                return hour;
+            } else if (meridiem === '下午' || meridiem === '晚上') {
+                return hour + 12;
+            } else {
+                // '中午'
+                return hour >= 11 ? hour : hour + 12;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            var hm = hour * 100 + minute;
+            if (hm < 600) {
+                return '凌晨';
+            } else if (hm < 900) {
+                return '早上';
+            } else if (hm < 1130) {
+                return '上午';
+            } else if (hm < 1230) {
+                return '中午';
+            } else if (hm < 1800) {
+                return '下午';
+            } else {
+                return '晚上';
+            }
+        },
+        calendar : {
+            sameDay : function () {
+                return this.minutes() === 0 ? '[今天]Ah[点整]' : '[今天]LT';
+            },
+            nextDay : function () {
+                return this.minutes() === 0 ? '[明天]Ah[点整]' : '[明天]LT';
+            },
+            lastDay : function () {
+                return this.minutes() === 0 ? '[昨天]Ah[点整]' : '[昨天]LT';
+            },
+            nextWeek : function () {
+                var startOfWeek, prefix;
+                startOfWeek = moment__default().startOf('week');
+                prefix = this.diff(startOfWeek, 'days') >= 7 ? '[下]' : '[本]';
+                return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
+            },
+            lastWeek : function () {
+                var startOfWeek, prefix;
+                startOfWeek = moment__default().startOf('week');
+                prefix = this.unix() < startOfWeek.unix()  ? '[上]' : '[本]';
+                return this.minutes() === 0 ? prefix + 'dddAh点整' : prefix + 'dddAh点mm';
+            },
+            sameElse : 'LL'
+        },
+        ordinalParse: /\d{1,2}(日|月|周)/,
+        ordinal : function (number, period) {
+            switch (period) {
+            case 'd':
+            case 'D':
+            case 'DDD':
+                return number + '日';
+            case 'M':
+                return number + '月';
+            case 'w':
+            case 'W':
+                return number + '周';
+            default:
+                return number;
+            }
+        },
+        relativeTime : {
+            future : '%s内',
+            past : '%s前',
+            s : '几秒',
+            m : '1 分钟',
+            mm : '%d 分钟',
+            h : '1 小时',
+            hh : '%d 小时',
+            d : '1 天',
+            dd : '%d 天',
+            M : '1 个月',
+            MM : '%d 个月',
+            y : '1 年',
+            yy : '%d 年'
+        },
+        week : {
+            // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
+            dow : 1, // Monday is the first day of the week.
+            doy : 4  // The week that contains Jan 4th is the first week of the year.
+        }
+    });
+
+    //! moment.js locale configuration
+    //! locale : traditional chinese (zh-tw)
+    //! author : Ben : https://github.com/ben-lin
+
+    var zh_tw = moment__default.defineLocale('zh-tw', {
+        months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+        monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+        weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+        weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
+        weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+        longDateFormat : {
+            LT : 'Ah點mm分',
+            LTS : 'Ah點m分s秒',
+            L : 'YYYY年MMMD日',
+            LL : 'YYYY年MMMD日',
+            LLL : 'YYYY年MMMD日Ah點mm分',
+            LLLL : 'YYYY年MMMD日ddddAh點mm分',
+            l : 'YYYY年MMMD日',
+            ll : 'YYYY年MMMD日',
+            lll : 'YYYY年MMMD日Ah點mm分',
+            llll : 'YYYY年MMMD日ddddAh點mm分'
+        },
+        meridiemParse: /早上|上午|中午|下午|晚上/,
+        meridiemHour : function (hour, meridiem) {
+            if (hour === 12) {
+                hour = 0;
+            }
+            if (meridiem === '早上' || meridiem === '上午') {
+                return hour;
+            } else if (meridiem === '中午') {
+                return hour >= 11 ? hour : hour + 12;
+            } else if (meridiem === '下午' || meridiem === '晚上') {
+                return hour + 12;
+            }
+        },
+        meridiem : function (hour, minute, isLower) {
+            var hm = hour * 100 + minute;
+            if (hm < 900) {
+                return '早上';
+            } else if (hm < 1130) {
+                return '上午';
+            } else if (hm < 1230) {
+                return '中午';
+            } else if (hm < 1800) {
+                return '下午';
+            } else {
+                return '晚上';
+            }
+        },
+        calendar : {
+            sameDay : '[今天]LT',
+            nextDay : '[明天]LT',
+            nextWeek : '[下]ddddLT',
+            lastDay : '[昨天]LT',
+            lastWeek : '[上]ddddLT',
+            sameElse : 'L'
+        },
+        ordinalParse: /\d{1,2}(日|月|週)/,
+        ordinal : function (number, period) {
+            switch (period) {
+            case 'd' :
+            case 'D' :
+            case 'DDD' :
+                return number + '日';
+            case 'M' :
+                return number + '月';
+            case 'w' :
+            case 'W' :
+                return number + '週';
+            default :
+                return number;
+            }
+        },
+        relativeTime : {
+            future : '%s內',
+            past : '%s前',
+            s : '幾秒',
+            m : '1分鐘',
+            mm : '%d分鐘',
+            h : '1小時',
+            hh : '%d小時',
+            d : '1天',
+            dd : '%d天',
+            M : '1個月',
+            MM : '%d個月',
+            y : '1年',
+            yy : '%d年'
+        }
+    });
+
+    var moment_with_locales = moment__default;
+    moment_with_locales.locale('en');
+
+    return moment_with_locales;
+
+}));
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/moment/2.13.0/moment-with-locales.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/moment/2.13.0/moment-with-locales.min.js
new file mode 100644
index 0000000..4b3fe51
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/moment/2.13.0/moment-with-locales.min.js
@@ -0,0 +1,76 @@
+!function(a,b){"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.moment=b()}(this,function(){"use strict";function a(){return ce.apply(null,arguments)}function b(a){ce=a}function c(a){return a instanceof Array||"[object Array]"===Object.prototype.toString.call(a)}function d(a){return a instanceof Date||"[object Date]"===Object.prototype.toString.call(a)}function e(a,b){var c,d=[];for(c=0;c<a.length;++c)d.push(b(a[c], [...]
+return a=K(a),this[a+"s"]()}function $c(a){return function(){return this._data[a]}}function _c(){return q(this.days()/7)}function ad(a,b,c,d,e){return e.relativeTime(b||1,!!c,a,d)}function bd(a,b,c){var d=db(a).abs(),e=Zf(d.as("s")),f=Zf(d.as("m")),g=Zf(d.as("h")),h=Zf(d.as("d")),i=Zf(d.as("M")),j=Zf(d.as("y")),k=e<$f.s&&["s",e]||1>=f&&["m"]||f<$f.m&&["mm",f]||1>=g&&["h"]||g<$f.h&&["hh",g]||1>=h&&["d"]||h<$f.d&&["dd",h]||1>=i&&["M"]||i<$f.M&&["MM",i]||1>=j&&["y"]||["yy",j];return k[2]=b, [...]
+//! moment.js locale configuration
+//! locale : belarusian (be)
+//! author : Dmitry Demidov : https://github.com/demidov91
+//! author: Praleska: http://praleska.pro/
+//! Author : Menelion Elensúle : https://github.com/Oire
+function fd(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function gd(a,b,c){var d={mm:b?"хвіліна_хвіліны_хвілін":"хвіліну_хвіліны_хвілін",hh:b?"гадзіна_гадзіны_гадзін":"гадзіну_гадзіны_гадзін",dd:"дзень_дні_дзён",MM:"месяц_месяцы_месяцаў",yy:"год_гады_гадоў"};return"m"===c?b?"хвіліна":"хвіліну":"h"===c?b?"гадзіна":"гадзіну":a+" "+fd(d[c],+a)}
+//! moment.js locale configuration
+//! locale : breton (br)
+//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
+function hd(a,b,c){var d={mm:"munutenn",MM:"miz",dd:"devezh"};return a+" "+kd(d[c],a)}function id(a){switch(jd(a)){case 1:case 3:case 4:case 5:case 9:return a+" bloaz";default:return a+" vloaz"}}function jd(a){return a>9?jd(a%10):a}function kd(a,b){return 2===b?ld(a):a}function ld(a){var b={m:"v",b:"v",d:"z"};return void 0===b[a.charAt(0)]?a:b[a.charAt(0)]+a.substring(1)}
+//! moment.js locale configuration
+//! locale : bosnian (bs)
+//! author : Nedim Cholich : https://github.com/frontyard
+//! based on (hr) translation by Bojan Marković
+function md(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}function nd(a){return a>1&&5>a&&1!==~~( [...]
+//! moment.js locale configuration
+//! locale : austrian german (de-at)
+//! author : lluchs : https://github.com/lluchs
+//! author: Menelion Elensúle: https://github.com/Oire
+//! author : Martin Groller : https://github.com/MadMG
+//! author : Mikolaj Dadela : https://github.com/mik01aj
+function pd(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}
+//! moment.js locale configuration
+//! locale : german (de)
+//! author : lluchs : https://github.com/lluchs
+//! author: Menelion Elensúle: https://github.com/Oire
+//! author : Mikolaj Dadela : https://github.com/mik01aj
+function qd(a,b,c,d){var e={m:["eine Minute","einer Minute"],h:["eine Stunde","einer Stunde"],d:["ein Tag","einem Tag"],dd:[a+" Tage",a+" Tagen"],M:["ein Monat","einem Monat"],MM:[a+" Monate",a+" Monaten"],y:["ein Jahr","einem Jahr"],yy:[a+" Jahre",a+" Jahren"]};return b?e[c][0]:e[c][1]}
+//! moment.js locale configuration
+//! locale : estonian (et)
+//! author : Henry Kehlmann : https://github.com/madhenry
+//! improvements : Illimar Tambek : https://github.com/ragulka
+function rd(a,b,c,d){var e={s:["mõne sekundi","mõni sekund","paar sekundit"],m:["ühe minuti","üks minut"],mm:[a+" minuti",a+" minutit"],h:["ühe tunni","tund aega","üks tund"],hh:[a+" tunni",a+" tundi"],d:["ühe päeva","üks päev"],M:["kuu aja","kuu aega","üks kuu"],MM:[a+" kuu",a+" kuud"],y:["ühe aasta","aasta","üks aasta"],yy:[a+" aasta",a+" aastat"]};return b?e[c][2]?e[c][2]:e[c][1]:d?e[c][0]:e[c][1]}function sd(a,b,c,d){var e="";switch(c){case"s":return d?"muutaman sekunnin":"muutama se [...]
+//! moment.js locale configuration
+//! locale : hrvatski (hr)
+//! author : Bojan Marković : https://github.com/bmarkovic
+function ud(a,b,c){var d=a+" ";switch(c){case"m":return b?"jedna minuta":"jedne minute";case"mm":return d+=1===a?"minuta":2===a||3===a||4===a?"minute":"minuta";case"h":return b?"jedan sat":"jednog sata";case"hh":return d+=1===a?"sat":2===a||3===a||4===a?"sata":"sati";case"dd":return d+=1===a?"dan":"dana";case"MM":return d+=1===a?"mjesec":2===a||3===a||4===a?"mjeseca":"mjeseci";case"yy":return d+=1===a?"godina":2===a||3===a||4===a?"godine":"godina"}}function vd(a,b,c,d){var e=a;switch(c){ [...]
+//! moment.js locale configuration
+//! locale : icelandic (is)
+//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik
+function xd(a){return a%100===11?!0:a%10===1?!1:!0}function yd(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nokkrar sekúndur":"nokkrum sekúndum";case"m":return b?"mínúta":"mínútu";case"mm":return xd(a)?e+(b||d?"mínútur":"mínútum"):b?e+"mínúta":e+"mínútu";case"hh":return xd(a)?e+(b||d?"klukkustundir":"klukkustundum"):e+"klukkustund";case"d":return b?"dagur":d?"dag":"degi";case"dd":return xd(a)?b?e+"dagar":e+(d?"daga":"dögum"):b?e+"dagur":e+(d?"dag":"degi");case"M":return b?"mánuður [...]
+//! moment.js locale configuration
+//! locale : Luxembourgish (lb)
+//! author : mweimerskirch : https://github.com/mweimerskirch, David Raison : https://github.com/kwisatz
+function zd(a,b,c,d){var e={m:["eng Minutt","enger Minutt"],h:["eng Stonn","enger Stonn"],d:["een Dag","engem Dag"],M:["ee Mount","engem Mount"],y:["ee Joer","engem Joer"]};return b?e[c][0]:e[c][1]}function Ad(a){var b=a.substr(0,a.indexOf(" "));return Cd(b)?"a "+a:"an "+a}function Bd(a){var b=a.substr(0,a.indexOf(" "));return Cd(b)?"viru "+a:"virun "+a}function Cd(a){if(a=parseInt(a,10),isNaN(a))return!1;if(0>a)return!0;if(10>a)return a>=4&&7>=a?!0:!1;if(100>a){var b=a%10,c=a/10;return  [...]
+//! moment.js locale configuration
+//! locale : romanian (ro)
+//! author : Vlad Gurdiga : https://github.com/gurdiga
+//! author : Valentin Agachi : https://github.com/avaly
+function Pd(a,b,c){var d={mm:"minute",hh:"ore",dd:"zile",MM:"luni",yy:"ani"},e=" ";return(a%100>=20||a>=100&&a%100===0)&&(e=" de "),a+e+d[c]}
+//! moment.js locale configuration
+//! locale : russian (ru)
+//! author : Viktorminator : https://github.com/Viktorminator
+//! Author : Menelion Elensúle : https://github.com/Oire
+//! author : Коренберг Марк : https://github.com/socketpair
+function Qd(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function Rd(a,b,c){var d={mm:b?"минута_минуты_минут":"минуту_минуты_минут",hh:"час_часа_часов",dd:"день_дня_дней",MM:"месяц_месяца_месяцев",yy:"год_года_лет"};return"m"===c?b?"минута":"минуту":a+" "+Qd(d[c],+a)}function Sd(a){return a>1&&5>a}function Td(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"pár sekúnd":"pár sekundami";case"m":return b?"minúta":d?"minútu":"m [...]
+//! moment.js locale configuration
+//! locale : slovenian (sl)
+//! author : Robert Sedovšek : https://github.com/sedovsek
+function Ud(a,b,c,d){var e=a+" ";switch(c){case"s":return b||d?"nekaj sekund":"nekaj sekundami";case"m":return b?"ena minuta":"eno minuto";case"mm":return e+=1===a?b?"minuta":"minuto":2===a?b||d?"minuti":"minutama":5>a?b||d?"minute":"minutami":b||d?"minut":"minutami";case"h":return b?"ena ura":"eno uro";case"hh":return e+=1===a?b?"ura":"uro":2===a?b||d?"uri":"urama":5>a?b||d?"ure":"urami":b||d?"ur":"urami";case"d":return b||d?"en dan":"enim dnem";case"dd":return e+=1===a?b||d?"dan":"dnem [...]
+//! moment.js locale configuration
+//! locale : ukrainian (uk)
+//! author : zemlanin : https://github.com/zemlanin
+//! Author : Menelion Elensúle : https://github.com/Oire
+function $d(a,b){var c=a.split("_");return b%10===1&&b%100!==11?c[0]:b%10>=2&&4>=b%10&&(10>b%100||b%100>=20)?c[1]:c[2]}function _d(a,b,c){var d={mm:b?"хвилина_хвилини_хвилин":"хвилину_хвилини_хвилин",hh:b?"година_години_годин":"годину_години_годин",dd:"день_дні_днів",MM:"місяць_місяці_місяців",yy:"рік_роки_років"};return"m"===c?b?"хвилина":"хвилину":"h"===c?b?"година":"годину":a+" "+$d(d[c],+a)}function ae(a,b){var c={nominative:"неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота".s [...]
+//! moment.js
+//! version : 2.13.0
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+a.version="2.13.0",b(Ka),a.fn=Bf,a.min=Ma,a.max=Na,a.now=ef,a.utc=h,a.unix=xc,a.months=Jc,a.isDate=d,a.locale=E,a.invalid=l,a.duration=db,a.isMoment=p,a.weekdays=Lc,a.parseZone=yc,a.localeData=H,a.isDuration=Pa,a.monthsShort=Kc,a.weekdaysMin=Nc,a.defineLocale=F,a.updateLocale=G,a.locales=I,a.weekdaysShort=Mc,a.normalizeUnits=K,a.relativeTimeThreshold=cd,a.prototype=Bf;var bg=a,cg=(bg.defineLocale("af",{months:"Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_Nove [...]
+y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(a){var b=a%10,c=1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th";return a+c},week:{dow:1,doy:4}}),bg.defineLocale("eo",{months:"januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro".split("_"),monthsShort:"jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec".split("_"),weekdays:"Dimanĉo_Lundo_Mardo_Merkredo_Ĵaŭdo_Vendredo_Sabato".split("_"),weekdaysShort:"Dim_Lun_Ma [...]
+sameElse:"L"},relativeTime:{future:"%s ичинде",past:"%s мурун",s:"бирнече секунд",m:"бир мүнөт",mm:"%d мүнөт",h:"бир саат",hh:"%d саат",d:"бир күн",dd:"%d күн",M:"бир ай",MM:"%d ай",y:"бир жыл",yy:"%d жыл"},ordinalParse:/\d{1,2}-(чи|чы|чү|чу)/,ordinal:function(a){var b=a%10,c=a>=100?100:null;return a+(Kg[a]||Kg[b]||Kg[c])},week:{dow:1,doy:7}}),bg.defineLocale("lb",{months:"Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember".split("_"),monthsShort:"Jan._F [...]
+case 3:return"[v] [sredo] [ob] LT";case 6:return"[v] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[v] dddd [ob] LT"}},lastDay:"[včeraj ob] LT",lastWeek:function(){switch(this.day()){case 0:return"[prejšnjo] [nedeljo] [ob] LT";case 3:return"[prejšnjo] [sredo] [ob] LT";case 6:return"[prejšnjo] [soboto] [ob] LT";case 1:case 2:case 4:case 5:return"[prejšnji] dddd [ob] LT"}},sameElse:"L"},relativeTime:{future:"čez %s",past:"pred %s",s:Ud,m:Ud,mm:Ud,h:Ud,hh:Ud,d:Ud,dd:Ud,M:Ud,MM:Ud,y:U [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-calendar.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-calendar.js
new file mode 100644
index 0000000..c144d79
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-calendar.js
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.DateTime = {};
+
+Tobago.DateTime.init = function (elements) {
+
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-date")
+      .not("[disabled]")
+      .not("[readonly]")
+      .each(function () {
+        var $date = jQuery(this);
+
+        var analyzed = Tobago.DateTime.analyzePattern($date.data("tobago-pattern"));
+        var options = {
+          format: analyzed,
+          icons: {
+            time: 'fa fa-clock-o',
+            date: 'fa fa-calendar',
+            up: 'fa fa-chevron-up',
+            down: 'fa fa-chevron-down',
+            previous: 'fa fa-chevron-left',
+            next: 'fa fa-chevron-right',
+            today: 'fa fa-calendar-check-o',
+            clear: 'fa fa-trash',
+            close: 'fa fa-times'
+          },
+          widgetParent: '.tobago-page'
+        };
+
+        var i18n = $date.data("tobago-date-time-i18n");
+        if (i18n) {
+          var monthNames = i18n.monthNames;
+          if (monthNames) {
+            moment.localeData()._months = monthNames;
+          }
+          var monthNamesShort = i18n.monthNamesShort;
+          if (monthNamesShort) {
+            moment.localeData()._monthsShort = monthNamesShort;
+          }
+          var dayNames = i18n.dayNames;
+          if (dayNames) {
+            moment.localeData()._weekdays = dayNames;
+          }
+          var dayNamesShort = i18n.dayNamesShort;
+          if (dayNamesShort) {
+            moment.localeData()._weekdaysShort = dayNamesShort;
+          }
+          var dayNamesMin = i18n.dayNamesMin;
+          if (dayNamesMin) {
+            moment.localeData()._weekdaysMin = dayNamesMin;
+          }
+          var firstDay = i18n.firstDay;
+          if (firstDay) {
+            moment.localeData()._week.dow = firstDay;
+          }
+        }
+
+        $date.parent().datetimepicker(options);
+
+        // we need to add the change listener here, because
+        // in line 1307 of bootstrap-datetimepicker.js
+        // the 'stopImmediatePropagation()' stops the change-event
+        // execution of line 686 in tobago.js
+        $date.parent().on('dp.change', function (event) {
+          var commands = jQuery(this).find("input").data("tobago-commands");
+          if (commands && commands.change) {
+            if (commands.change.execute || commands.change.render) {
+              jsf.ajax.request(
+                  jQuery(this).find("input").attr("name"),
+                  event,
+                  {
+                    "javax.faces.behavior.event": "change",
+                    execute: commands.change.execute,
+                    render: commands.change.render
+                  });
+            } else if (commands.change.action) {
+              Tobago.submitAction(this.firstElementChild, commands.change.action, commands.change);
+            }
+          }
+        });
+
+        /*
+         XXX need for fixing wrong positioning of bootstrap datepicker.
+         See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+         */
+        $date.parent().on('dp.show', function () {
+          var datepicker = jQuery('.bootstrap-datetimepicker-widget');
+          var $div = jQuery(this);
+          var top, left;
+          if (datepicker.hasClass('bottom')) {
+            top = $div.offset().top + $div.outerHeight() - jQuery("body").offset().top;
+            left = $div.offset().left;
+            datepicker.css({
+              'top': top + 'px',
+              'bottom': 'auto',
+              'left': left + 'px'
+            });
+          }
+          else if (datepicker.hasClass('top')) {
+            top = $div.offset().top - datepicker.outerHeight() - jQuery("body").offset().top;
+            left = $div.offset().left;
+            datepicker.css({
+              'top': top + 'px',
+              'bottom': 'auto',
+              'left': left + 'px'
+            });
+          }
+        });
+      });
+};
+
+/*
+ Get the pattern from the "Java world" (http://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html)
+ and convert it to 'moment.js'.
+ Attention: Not every pattern char is supported.
+ */
+Tobago.DateTime.analyzePattern = function (pattern) {
+
+  if (!pattern || pattern.length > 100) {
+    console.warn("Pattern not supported: " + pattern);  // @DEV_ONLY
+    pattern = "";
+  }
+
+  var analyzedPattern = "";
+  var nextSegment = "";
+  var escMode = false;
+  for (i = 0; i < pattern.length; i++) {
+    var currentChar = pattern.charAt(i);
+    if (currentChar == "'" && escMode == false) {
+      escMode = true;
+      analyzedPattern += Tobago.DateTime.analyzePatternPart(nextSegment);
+      nextSegment = "";
+    } else if (currentChar == "'" && pattern.charAt(i + 1) == "'") {
+      if (escMode) {
+        nextSegment += "\\";
+      }
+      nextSegment += "'";
+      i++;
+    } else if (currentChar == "'" && escMode == true) {
+      escMode = false;
+      analyzedPattern += nextSegment;
+      nextSegment = "";
+    } else {
+      if (escMode) {
+        nextSegment += "\\";
+      }
+      nextSegment += currentChar;
+    }
+  }
+  if (nextSegment != "") {
+    if (escMode) {
+      analyzedPattern += nextSegment;
+    } else {
+      analyzedPattern += Tobago.DateTime.analyzePatternPart(nextSegment);
+    }
+  }
+
+  return analyzedPattern;
+};
+
+Tobago.DateTime.analyzePatternPart = function (pattern) {
+
+  if (pattern.search("G") > -1 || pattern.search("W") > -1 || pattern.search("F") > -1
+      || pattern.search("K") > -1 || pattern.search("z") > -1 || pattern.search("X") > -1) {
+    console.warn("Pattern chars 'G', 'W', 'F', 'K', 'z' and 'X' are not supported: " + pattern); // @DEV_ONLY
+    pattern = "";
+  }
+
+  if (pattern.search("y") > -1) {
+    pattern = pattern.replace(/y/g, "Y");
+  }
+  if (pattern.search("Y") > -1) {
+    pattern = pattern.replace(/\bY\b/g, "YYYY");
+    pattern = pattern.replace(/\bYYY\b/g, "YY");
+    pattern = pattern.replace(/YYYYYY+/g, "YYYYY");
+  }
+
+  if (pattern.search("MMMMM") > -1) {
+    pattern = pattern.replace(/MMMMM+/g, "MMMM");
+  }
+
+  if (pattern.search("w") > -1) {
+    pattern = pattern.replace(/\bw\b/g, "W");
+    pattern = pattern.replace(/www+/g, "WW");
+  }
+
+  if (pattern.search("D") > -1) {
+    pattern = pattern.replace(/DDD+/g, "DDDD");
+    pattern = pattern.replace(/\bD{1,2}\b/g, "DDD");
+  }
+
+  if (pattern.search("d") > -1) {
+    pattern = pattern.replace(/dd+/g, "DD");
+    pattern = pattern.replace(/\bd\b/g, "D");
+  }
+
+  if (pattern.search("E") > -1) {
+    pattern = pattern.replace(/\bE{1,3}\b/g, "dd");
+    pattern = pattern.replace(/EEEE+/g, "dddd");
+  }
+
+  if (pattern.search("u") > -1) {
+    pattern = pattern.replace(/u+/g, "E");
+  }
+  if (pattern.search("a") > -1) {
+    pattern = pattern.replace(/a+/g, "A");
+  }
+  if (pattern.search("HHH") > -1) {
+    pattern = pattern.replace(/HHH+/g, "HH");
+  }
+  if (pattern.search("kkk") > -1) {
+    pattern = pattern.replace(/kkk+/g, "kk");
+  }
+  if (pattern.search("hhh") > -1) {
+    pattern = pattern.replace(/hhh+/g, "hh");
+  }
+  if (pattern.search("mmm") > -1) {
+    pattern = pattern.replace(/mmm+/g, "mm");
+  }
+  if (pattern.search("sss") > -1) {
+    pattern = pattern.replace(/sss+/g, "ss");
+  }
+  if (pattern.search("SSSS") > -1) {
+    pattern = pattern.replace(/SSSS+/g, "SSS");
+  }
+  if (pattern.search("Z") > -1) {
+    pattern = pattern.replace(/\bZ\b/g, "ZZ");
+    pattern = pattern.replace(/ZZZ+/g, "ZZ");
+  }
+
+  return pattern;
+};
+
+Tobago.registerListener(Tobago.DateTime.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.DateTime.init, Tobago.Phase.AFTER_UPDATE);
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-console.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-console.js
new file mode 100644
index 0000000..46c184b
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-console.js
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * This is a "fill-in".
+ * If a browser doesn't support "console", or some of its methods, it will be defined.
+ * So you don't have to worry about browser support of the calls.
+ * This is NOT a wrapper, so stacktraces, and line numbers remain valid.
+ *
+ * You can use, surely the following methods:
+ *
+ * console.log()
+ *
+ * console.debug() // deprecated, use console.log() instead
+ *
+ * console.info()
+ *
+ * console.warn()
+ *
+ * console.error()
+ *
+ * console.assert()
+ *
+ * console.time()
+ *
+ * console.timeEnd()
+ *
+ * console.count()
+ *
+ * console.dir()
+ *
+ * console.exception()
+ *
+ * console.group() // not implemented
+ *
+ * console.groupCollapsed() // not implemented
+ *
+ * console.groupEnd() // not implemented
+ *
+ * console.profile() // not implemented
+ *
+ * console.profileEnd() // not implemented
+ *
+ * console.trace()
+ *
+ * Hint: Should be used for development only!
+ *
+ * Restriction: multi args: printf is not implemented for console.log()
+ */
+
+if (!window.console) {
+  console = {};
+}
+
+if (!console.log) {
+  console.log = function (message, other) {
+    var div = jQuery(".tobago-console");
+    if (! console.isConsoleHidden()) {
+      div.show();
+    }
+    var body = div.children(":last");
+    var parameters = Array.prototype.slice.call(arguments).join(", ");
+    parameters.substr(0, parameters.length - 2);
+
+    // todo: make encoding for all array elements...
+    parameters = parameters.replace(/&/g, "&amp;");
+    parameters = parameters.replace(/</g, "&lt;");
+    parameters = parameters.replace(/>/g, "&gt;");
+    parameters = parameters.replace(/"/g, "&quot;");
+    jQuery("<p>").appendTo(body).html("<pre>" + parameters + "</pre>");
+  };
+
+  jQuery(document).ready(function () {
+    var div = jQuery("<div>").appendTo("body");
+    div.addClass("tobago-console");
+    div.css({
+      border: "2px solid red",
+      padding: "10px",
+      position: "absolute",
+      left: "50px",
+      top: "50px",
+      width: "500px",
+      height: "200px",
+      backgroundColor: "#ffffff",
+      filter: "alpha(opacity=70)",
+      opacity: 0.7,
+      overflow: "auto"
+    });
+    div.hide();
+    var header = jQuery("<div>").appendTo(div);
+    header.css({
+//      border: "1px solid red",
+      padding: "0 15px 5px 0"
+    });
+    var body = jQuery("<div>").appendTo(div);
+    var title = jQuery("<span>simple console replacement</span>").appendTo(header);
+    title.css({fontWeight: "bolder"});
+    var close = jQuery("<button>").appendTo(header);
+    close.attr("type", "button");
+    close.append("Hide");
+    close.click(function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      div.hide();
+    });
+    var closeForSession = jQuery("<button>").appendTo(header);
+    closeForSession.attr("type", "button");
+    closeForSession.append("Hide for this Session");
+    closeForSession.click(function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      div.hide();
+      console.hideConsoleForThisSession();
+    });
+    var clear = jQuery("<button>").appendTo(header);
+    clear.attr("type", "button");
+    clear.append("Clear");
+    clear.click(function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      body.children("p").detach();
+    });
+  });
+}
+
+console.util_array_slice = function (args, drop) {
+  var result = [];
+  for (var i = drop; i < args.length; i++) {
+    result[i - drop] = args[i];
+  }
+  return result;
+};
+
+console.util_stack_trace = function () {
+  var result;
+  var e = new Error();
+  var textarea = jQuery("textarea");
+  textarea.val("Start Logging...");
+  if (e.stack) { // Firefox && WebKit
+    textarea.val(textarea.val() + "\n\n" + e.stack);
+    result = e.stack.split('\n');
+  } else {
+    // poor implementation, but might not better possible
+    var currentFunction = arguments.callee.caller;
+    result = [];
+    var i = 0;
+    while (currentFunction) {
+      result[i++] = currentFunction.toString();
+      currentFunction = currentFunction.caller;
+    }
+  }
+
+  textarea.val(textarea.val() + "\n\n" + result);
+
+  return result;
+};
+
+if (!console.debug) {
+  console.debug = function (message, other) {
+    console.log("DEBUG: " + message, console.util_array_slice(arguments, 1));
+  };
+}
+
+if (!console.info) {
+  console.info = function (message, other) {
+    console.log("INFO: " + message, console.util_array_slice(arguments, 1));
+  };
+}
+
+if (!console.warn) {
+  console.warn = function (message, other) {
+    console.log("WARN: " + message, console.util_array_slice(arguments, 1));
+  };
+}
+
+if (!console.error) {
+  console.error = function (message, other) {
+    console.log("ERROR: " + message, console.util_array_slice(arguments, 1));
+  };
+}
+
+if (!console.assert) {
+  console.assert = function (test, message, other) { // multiargs?
+    if (test == false) {
+      console.log("ASSERTION FAILED: " + message, console.util_array_slice(arguments, 2));
+    }
+  };
+}
+
+if (!console.time) {
+  console.time = function (name) {
+    if (!console.timerMap) {
+      console.timerMap = {};
+    }
+    console.timerMap[name] = new Date().getTime();
+  };
+}
+
+if (!console.timeEnd) {
+  console.timeEnd = function (name) {
+    if (!console.timerMap) {
+      console.timerMap = {};
+    }
+    var start = console.timerMap[name];
+    if (start) {
+      console.info("Timer '" + name + "': " + (new Date().getTime() - start) + " ms");
+      console.timerMap[name] = null;
+    } else {
+      console.warn("Timer '" + name + "' not found!");
+    }
+  };
+}
+
+if (!console.dir) {
+  console.dir = function (name) {
+    // todo
+    console.debug("(dir() not implemented) " + name);
+  };
+}
+
+if (!console.count) {
+  console.count = function (name) {
+    if (!console.counterMap) {
+      console.counterMap = {};
+    }
+    if (typeof console.counterMap[name] == "number") {
+      console.counterMap[name] = console.counterMap[name] + 1;
+    } else {
+      console.counterMap[name] = 1;
+    }
+    console.info(name  + ": " + console.counterMap[name]);
+  };
+}
+
+if (!console.exception) {
+  console.exception = function (other) {
+    console.error(arguments);
+  };
+}
+
+if (!console.group) {
+  console.group = function (other) {
+    // todo
+    console.warn("(group() not implemented)");
+  };
+}
+
+if (!console.groupCollapsed) {
+  console.groupCollapsed = function (other) {
+    // todo
+    console.warn("(groupCollapsed() not implemented)");
+  };
+}
+
+if (!console.groupEnd) {
+  console.groupEnd = function (other) {
+    // todo
+    console.warn("(groupEnd() not implemented)");
+  };
+}
+
+if (!console.profile) {
+  console.profile = function (other) {
+    console.warn("(profile() not implemented)");
+  };
+}
+
+if (!console.profileEnd) {
+  console.profileEnd = function (other) {
+    console.warn("(profileEnd() not implemented)");
+  };
+}
+
+if (!console.trace) {
+  console.trace = function () {
+    console.log("STACK TRACE: " + console.util_stack_trace());
+  };
+}
+
+console.hideConsoleForThisSession = function() {
+  document.cookie = "tobagoHideConsole";
+};
+
+console.isConsoleHidden = function () {
+  var part = document.cookie.split(';');
+  for (var i = 0; i < part.length; i++) {
+    if ("tobagoHideConsole" == part[i]) {
+      return true;
+    }
+  }
+  return false;
+};
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-in.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-in.js
new file mode 100644
index 0000000..4b326ae
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-in.js
@@ -0,0 +1,17 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-jsf.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-jsf.js
new file mode 100644
index 0000000..d4b7027
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-jsf.js
@@ -0,0 +1,9510 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * XXX This is a modified copy of MyFaces 2.2.10 jsf-uncompressed-full.js
+ * XXX Modifications are marked with TOBAGO-JSF-JS
+ */
+
+/**
+ * @namespace
+ * @name window
+ * @description Eval routines, depending on the browser.
+ * <p/>
+ * The problem solved in this class is the problem on how to perform
+ * a global eval on multiple browsers. Some browsers auto eval themselves
+ * they do not need to be called
+ * <li>Some work with a window.eval.call(window,... </li>
+ * <li>Others use simply execScript <li>
+ * <li>Some others work only with the head appendix method
+ * head.appendChild(&lt;script...., head.removeChild(&lt;script </li>
+ * <p/>
+ * Note: The code here already is precompressed because the compressor
+ * fails on it, the deficits in readability will be covered by more comments
+ *
+ */
+
+
+if (!window.myfaces) {
+    /**
+     * @namespace
+     * @name myfaces
+     */
+    var myfaces = new function() {
+    };
+    window.myfaces = myfaces;
+}
+
+/**
+ * @memberOf myfaces
+ * @namespace
+ * @name _impl
+ */
+myfaces._impl = (myfaces._impl) ? myfaces._impl : {};
+/**
+ * @memberOf myfaces._impl
+ * @namespace
+ * @name core
+ */
+myfaces._impl.core = (myfaces._impl.core) ? myfaces._impl.core :{};
+
+if (!myfaces._impl.core._EvalHandlers) {
+    /**
+     * @memberOf myfaces._impl.core
+     * @namespace
+     * @name _EvalHandlers
+     */
+    myfaces._impl.core._EvalHandlers = new function() {
+        //the rest of the namespaces can be handled by our namespace feature
+        //helper to avoid unneeded hitches
+        /**
+         * @borrows myfaces._impl.core._Runtime as _T
+         */
+        var _T = this;
+
+        /*cascaded eval methods depending upon the browser*/
+
+        /**
+         * @function
+         * @param code
+
+         *
+         * evals a script globally using exec script (ie6 fallback)
+         * @param {String} code the code which has to be evaluated
+         * @borrows myfaces._impl.core._Runtime as _T
+         *
+         * TODO eval if we cannot replace this method with the head appendix
+         * method which is faster for ie this also would reduce our code
+         * by a few bytes
+         */
+        _T._evalExecScript = function(code) {
+            //execScript definitely only for IE otherwise we might have a custom
+            //window extension with undefined behavior on our necks
+            //window.execScript does not return anything
+            //on htmlunit it return "null object"
+            //_r == ret
+            var _r = window.execScript(code);
+            if ('undefined' != typeof _r && _r == "null" /*htmlunit bug*/) {
+                return null;
+            }
+            return _r;
+        };
+
+        /**
+         * flakey head appendix method which does not work in the correct
+         * order or at all for all modern browsers
+         * but seems to be the only method which works on blackberry correctly
+         * hence we are going to use it as fallback
+         *
+         * @param {String} code the code part to be evaled
+         * @borrows myfaces._impl.core._Runtime as _T
+         */
+        _T._evalHeadAppendix = function(code) {
+            //_l == location
+            var _l = document.getElementsByTagName("head")[0] || document.documentElement;
+            //_p == placeHolder
+            var _p = document.createElement("script");
+            _p.type = "text/javascript";
+            _p.text = code;
+            _l.insertBefore(_p, _l.firstChild);
+            _l.removeChild(_p);
+            return null;
+        };
+
+        /**
+         * @name myfaces._impl.core._Runtime._standardGlobalEval
+         * @private
+         * @param {String} code
+         */
+        _T._standardGlobalEval = function(code) {
+            //fix which works in a cross browser way
+            //we used to scope an anonymous function
+            //but I think this is better
+            //the reason is some Firefox versions
+            // apply a wrong scope
+            //if we call eval by not scoping
+            //_U == "undefined"
+            var _U = "undefined";
+            var gEval = function () {
+                //_r == retVal;
+                var _r = window.eval.call(window, code);
+                if (_U == typeof _r) return null;
+                return _r;
+            };
+            var _r = gEval();
+            if (_U == typeof _r) return null;
+            return _r;
+        };
+
+        /**
+         * global eval on scripts
+         * @param {String} c (code abbreviated since the compression does not work here)
+         * @name myfaces._impl.core._Runtime.globalEval
+         * @function
+         */
+        _T.globalEval = function(c) {
+            //TODO add a config param which allows to evaluate global scripts even if the call
+            //is embedded in an iframe
+            //We lazy init the eval type upon the browsers
+            //capabilities
+            var _e = "_evalType";
+            var _w = window;
+            var _b = myfaces._impl.core._Runtime.browser;
+            //central routine to determine the eval method
+            if (!_T[_e]) {
+                //execScript supported
+                _T[_e] = _w.execScript ? "_evalExecScript" : null;
+
+                //in case of no support we go to the standard global eval  window.eval.call(window,
+                // with Firefox fixes for scoping
+                _T[_e] = _T[_e] ||(( _w.eval && (!_b.isBlackBerry ||_b.isBlackBerry >= 6)) ? "_standardGlobalEval" : null);
+
+                //this one routes into the hed appendix method
+                _T[_e] = _T[_e] ||((_w.eval ) ? "_evalHeadAppendix" : null);
+            }
+            if (_T[_e]) {
+                //we now execute the eval method
+                return _T[_T[_e]](c);
+            }
+            //we probably have covered all browsers, but this is a safety net which might be triggered
+            //by some foreign browser which is not covered by the above cases
+            eval.call(window, c);
+            return null;
+        };
+
+    };
+}
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * Runtime/Startup class
+ * this is the central class which initializes all base mechanisms
+ * used by the rest of the system such as
+ * a) namespacing system
+ * b) browser detection
+ * c) loose configuration coupling
+ * d) utils methods to fetch the implementation
+ * e) ajaxed script loading
+ * f) global eval (because it is used internally)
+ * g) Structural base patterns as singleton, delegate and inheritance
+ *
+ * Note this class is self contained and must!!! be loaded
+ * as absolute first class before going into anything else
+ *
+ *
+ */
+/** @namespace myfaces._impl.core._Runtime*/
+
+myfaces._impl.core = (myfaces._impl.core) ? myfaces._impl.core : {};
+//now this is the only time we have to do this cascaded and manually
+//for the rest of the classes our reserveNamespace function will do the trick
+//Note, this class uses the classical closure approach (to save code)
+//it cannot be inherited by our inheritance mechanism, but must be delegated
+//if you want to derive from it
+//closures and prototype inheritance do not mix, closures and delegation however do
+/**
+ * @ignore
+ */
+if (!myfaces._impl.core._Runtime) {
+    /**
+     * @memberOf myfaces._impl.core
+     * @namespace
+     * @name _Runtime
+     */
+    myfaces._impl.core._Runtime = new function() {
+        //the rest of the namespaces can be handled by our namespace feature
+        //helper to avoid unneeded hitches
+        /**
+         * @borrows myfaces._impl.core._Runtime as _T
+         */
+        var _T = this;
+
+        //namespace idx to speed things up by hitting eval way less
+        this._reservedNMS = {};
+        this._registeredSingletons = {};
+        this._registeredClasses = [];
+        /**
+         * replacement counter for plugin classes
+         */
+        this._classReplacementCnt = 0;
+
+        /**
+         * global eval on scripts
+         * @param {String} code
+         * @name myfaces._impl.core._Runtime.globalEval
+         * @function
+         */
+        _T.globalEval = function(code) {
+            return myfaces._impl.core._EvalHandlers.globalEval(code);
+        };
+
+        /**
+         * applies an object to a namespace
+         * basically does what bla.my.name.space = obj does
+         * note we cannot use var myNameSpace = fetchNamespace("my.name.space")
+         * myNameSpace = obj because the result of fetch is already the object
+         * which the namespace points to, hence this function
+         *
+         * @param {String} nms the namespace to be assigned to
+         * @param {Object} obj the  object to be assigned
+         * @name myfaces._impl.core._Runtime.applyToGlobalNamespace
+         * @function
+         */
+        _T.applyToGlobalNamespace = function(nms, obj) {
+            var splitted = nms.split(/\./);
+            if (splitted.length == 1) {
+                window[nms] = obj;
+                return;
+            }
+            var parent = splitted.slice(0, splitted.length - 1);
+            var child = splitted[splitted.length - 1];
+            var parentNamespace = _T.fetchNamespace(parent.join("."));
+            parentNamespace[child] = obj;
+        };
+
+        /**
+         * fetches the object the namespace points to
+         * @param {String} nms the namespace which has to be fetched
+         * @return the object the namespace points to or null if nothing is found
+         */
+        this.fetchNamespace = function(nms) {
+            if ('undefined' == typeof nms || null == nms || !_T._reservedNMS[nms]) {
+                return null;
+            }
+
+            var ret = null;
+            try {
+                //blackberries have problems as well in older non webkit versions
+                if (!_T.browser.isIE) {
+                    //in ie 6 and 7 we get an error entry despite the suppression
+                    ret = _T.globalEval("window." + nms);
+                }
+                //namespace could point to numeric or boolean hence full
+                //save check
+
+            } catch (e) {/*wanted*/
+            }
+            //ie fallback for some ie versions path because it cannot eval namespaces
+            //ie in any version does not like that particularily
+            //we do it the hard way now
+            if ('undefined' != typeof ret && null != ret) {
+                return ret;
+            }
+            return _T._manuallyResolveNMS(nms);
+
+        };
+
+        _T._manuallyResolveNMS = function(nms) {
+             //ie fallback for some ie versions path because it cannot eval namespaces
+            //ie in any version does not like that particularily
+            //we do it the hard way now
+
+            nms = nms.split(/\./);
+            var ret = window;
+            var len = nms.length;
+
+            for (var cnt = 0; cnt < len; cnt++) {
+                ret = ret[nms[cnt]];
+                if ('undefined' == typeof ret || null == ret) {
+                    return null;
+                }
+            }
+            return ret;
+        };
+
+        /**
+         * Backported from dojo
+         * a failsafe string determination method
+         * (since in javascript String != "" typeof alone fails!)
+         * @param {Object} it  the object to be checked for being a string
+         * @return {boolean} true in case of being a string false otherwise
+         */
+        this.isString = function(/*anything*/ it) {
+            //	summary:
+            //		Return true if it is a String
+            return !!arguments.length && it != null && (typeof it == "string" || it instanceof String); // Boolean
+        };
+
+        /**
+         * reserves a namespace in the specific scope
+         *
+         * usage:
+         * if(_T.reserve("org.apache.myfaces.MyUtils")) {
+         *      org.apache.myfaces.MyUtils = function() {
+         *      }
+         * }
+         *
+         * reserves a namespace and if the namespace is new the function itself is reserved
+         *
+         *
+         *
+         * or:
+         * _T.reserve("org.apache.myfaces.MyUtils", function() { .. });
+         *
+         * reserves a namespace and if not already registered directly applies the function the namespace
+         *
+         * note for now the reserved namespaces reside as global maps justl like jsf.js but
+         * we also use a speedup index which is kept internally to reduce the number of evals or loops to walk through those
+         * namespaces (eval is a heavy operation and loops even only for namespace resolution introduce (O)2 runtime
+         * complexity while a simple map lookup is (O)log n with additional speedup from the engine.
+         *
+         *
+         * @param {String} nms
+         * @returns {boolean} true if it was not provided
+         * false otherwise for further action
+         */
+        this.reserveNamespace = function(nms, obj) {
+
+            if (!_T.isString(nms)) {
+                throw Error("Namespace must be a string with . as delimiter");
+            }
+            if (_T._reservedNMS[nms] || null != _T.fetchNamespace(nms)) {
+                return false;
+            }
+
+            var entries = nms.split(/\./);
+            var currNms = window;
+
+            var tmpNmsName = [];
+            var  UDEF = "undefined";
+            for (var cnt = 0; cnt < entries.length; cnt++) {
+                var subNamespace = entries[cnt];
+                tmpNmsName.push(subNamespace);
+                if (UDEF == typeof currNms[subNamespace]) {
+                    currNms[subNamespace] = {};
+                }
+                if (cnt == entries.length - 1 && UDEF != typeof obj) {
+                    currNms[subNamespace] = obj;
+                } else {
+                    currNms = currNms[subNamespace];
+                }
+                _T._reservedNMS[tmpNmsName.join(".")] = true;
+            }
+            return true;
+        };
+
+        /**
+         * iterates over all registered singletons in the namespace
+         * @param operator a closure which applies a certain function
+         * on the namespace singleton
+         */
+        this.iterateSingletons = function(operator) {
+            var singletons = _T._registeredSingletons;
+            for(var key in singletons) {
+                var nms = _T.fetchNamespace(key);
+                operator(nms);
+            }
+        };
+        /**
+         * iterates over all registered singletons in the namespace
+         * @param operator a closure which applies a certain function
+         * on the namespace singleton
+         */
+        this.iterateClasses = function(operator) {
+            var classes = _T._registeredClasses;
+            for(var cnt  = 0; cnt < classes.length; cnt++) {
+                operator(classes[cnt], cnt);
+            }
+        };
+
+        /**
+         * check if an element exists in the root
+         * also allows to check for subelements
+         * usage
+         * _T.exists(rootElem,"my.name.space")
+         * @param {Object} root the root element
+         * @param {String} subNms the namespace
+         */
+        this.exists = function(root, subNms) {
+            if (!root) {
+                return false;
+            }
+            //special case locally reserved namespace
+            if (root == window && _T._reservedNMS[subNms]) {
+                return true;
+            }
+
+            //initial condition root set element not set or null
+            //equals to element exists
+            if (!subNms) {
+                return true;
+            }
+            var UDEF = "undefined";
+            try {
+                //special condition subnamespace exists as full blown key with . instead of function map
+                if (UDEF != typeof root[subNms]) {
+                    return true;
+                }
+
+                //crossported from the dojo toolkit
+                // summary: determine if an object supports a given method
+                // description: useful for longer api chains where you have to test each object in the chain
+                var p = subNms.split(".");
+                var len = p.length;
+                for (var i = 0; i < len; i++) {
+                    //the original dojo code here was false because
+                    //they were testing against ! which bombs out on exists
+                    //which has a value set to false
+                    // (TODO send in a bugreport to the Dojo people)
+
+                    if (UDEF == typeof root[p[i]]) {
+                        return false;
+                    } // Boolean
+                    root = root[p[i]];
+                }
+                return true; // Boolean
+
+            } catch (e) {
+                //ie (again) has a special handling for some object attributes here which automatically throw an unspecified error if not existent
+                return false;
+            }
+        };
+
+
+
+        /**
+         * fetches a global config entry
+         * @param {String} configName the name of the configuration entry
+         * @param {Object} defaultValue
+         *
+         * @return either the config entry or if none is given the default value
+         */
+        this.getGlobalConfig = function(configName, defaultValue) {
+            /**
+             * note we could use exists but this is an heavy operation, since the config name usually
+             * given this function here is called very often
+             * is a single entry without . in between we can do the lighter shortcut
+             */
+            return (myfaces["config"] && 'undefined' != typeof myfaces.config[configName] ) ?
+                    myfaces.config[configName]
+                    :
+                    defaultValue;
+        };
+
+        /**
+         * gets the local or global options with local ones having higher priority
+         * if no local or global one was found then the default value is given back
+         *
+         * @param {String} configName the name of the configuration entry
+         * @param {String} localOptions the local options root for the configuration myfaces as default marker is added implicitely
+         *
+         * @param {Object} defaultValue
+         *
+         * @return either the config entry or if none is given the default value
+         */
+        this.getLocalOrGlobalConfig = function(localOptions, configName, defaultValue) {
+            /*use(myfaces._impl._util)*/
+            var _local = !!localOptions;
+            var _localResult;
+            var MYFACES = "myfaces";
+
+            if (_local) {
+                //note we also do not use exist here due to performance improvement reasons
+                //not for now we loose the subnamespace capabilities but we do not use them anyway
+                //this code will give us a performance improvement of 2-3%
+                _localResult = (localOptions[MYFACES]) ? localOptions[MYFACES][configName] : undefined;
+                _local = "undefined" != typeof _localResult;
+            }
+
+            return (!_local) ? _T.getGlobalConfig(configName, defaultValue) : _localResult;
+        };
+
+        /**
+         * determines the xhr level which either can be
+         * 1 for classical level1
+         * 1.5 for mozillas send as binary implementation
+         * 2 for xhr level 2
+         */
+        this.getXHRLvl = function() {
+            if (!_T.XHR_LEVEL) {
+                _T.getXHRObject();
+            }
+            return _T.XHR_LEVEL;
+        };
+
+        /**
+         * encapsulated xhr object which tracks down various implementations
+         * of the xhr object in a browser independent fashion
+         * (ie pre 7 used to have non standard implementations because
+         * the xhr object standard came after IE had implemented it first
+         * newer ie versions adhere to the standard and all other new browsers do anyway)
+         *
+         * @return the xhr object according to the browser type
+         */
+        this.getXHRObject = function() {
+            var _ret = new XMLHttpRequest();
+            //we now check the xhr level
+            //sendAsBinary = 1.5 which means mozilla only
+            //upload attribute present == level2
+            var XHR_LEVEL = "XHR_LEVEL";
+            if (!_T[XHR_LEVEL]) {
+                var _e = _T.exists;
+                _T[XHR_LEVEL] = (_e(_ret, "sendAsBinary")) ? 1.5 : 1;
+                _T[XHR_LEVEL] = (_e(_ret, "upload") && 'undefined' != typeof FormData) ? 2 : _T.XHR_LEVEL;
+            }
+            return _ret;
+        };
+
+        /**
+         * loads a script and executes it under a global scope
+         * @param {String} src  the source of the script
+         * @param {String} type the type of the script
+         * @param {Boolean} defer  defer true or false, same as the javascript tag defer param
+         * @param {String} charSet the charset under which the script has to be loaded
+         * @param {Boolean} async tells whether the script can be asynchronously loaded or not, currently
+         * not used
+         */
+        this.loadScriptEval = function(src, type, defer, charSet, async) {
+            var xhr = _T.getXHRObject();
+            xhr.open("GET", src, false);
+
+            if (charSet) {
+                xhr.setRequestHeader("Content-Type", "text/javascript; charset:" + charSet);
+            }
+
+            xhr.send(null);
+
+            //since we are synchronous we do it after not with onReadyStateChange
+
+            if (xhr.readyState == 4) {
+                if (xhr.status == 200) {
+                    //defer also means we have to process after the ajax response
+                    //has been processed
+                    //we can achieve that with a small timeout, the timeout
+                    //triggers after the processing is done!
+                    if (!defer) {
+                        //we moved the sourceurl notation to # instead of @ because ie does not cover it correctly
+                        //newer browsers understand # including ie since windows 8.1
+                        //see http://updates.html5rocks.com/2013/06/sourceMappingURL-and-sourceURL-syntax-changed
+                        _T.globalEval(xhr.responseText.replace("\n", "\r\n") + "\r\n//# sourceURL=" + src);
+                    } else {
+                        //TODO not ideal we maybe ought to move to something else here
+                        //but since it is not in use yet, it is ok
+                        setTimeout(function() {
+                            _T.globalEval(xhr.responseText.replace("\n", "\r\n") + "\r\n//# sourceURL=" + src);
+                        }, 1);
+                    }
+                } else {
+                    throw Error(xhr.responseText);
+                }
+            } else {
+                throw Error("Loading of script " + src + " failed ");
+            }
+
+        };
+
+        /**
+         * load script functionality which utilizes the browser internal
+         * script loading capabilities
+         *
+         * @param {String} src  the source of the script
+         * @param {String} type the type of the script
+         * @param {Boolean} defer  defer true or false, same as the javascript tag defer param
+         * @param {String} charSet the charset under which the script has to be loaded
+         */
+        this.loadScriptByBrowser = function(src, type, defer, charSet, async) {
+            //if a head is already present then it is safer to simply
+            //use the body, some browsers prevent head alterations
+            //after the first initial rendering
+
+            //ok this is nasty we have to do a head modification for ie pre 8
+            //the rest can be finely served with body
+            var position = "head";
+            var UDEF = "undefined";
+            try {
+                var holder = document.getElementsByTagName(position)[0];
+                if (UDEF == typeof holder || null == holder) {
+                    holder = document.createElement(position);
+                    var html = document.getElementsByTagName("html");
+                    html.appendChild(holder);
+                }
+                var script = document.createElement("script");
+
+                script.type = type || "text/javascript";
+                script.src = src;
+                if (charSet) {
+                    script.charset = charSet;
+                }
+                if (defer) {
+                    script.defer = defer;
+                }
+                /*html5 capable browsers can deal with script.async for
+                 * proper head loading*/
+                if (UDEF != typeof script.async) {
+                    script.async = async;
+                }
+                holder.appendChild(script);
+
+            } catch (e) {
+                //in case of a loading error we retry via eval
+                return false;
+            }
+
+            return true;
+        };
+
+        this.loadScript = function(src, type, defer, charSet, async) {
+            //the chrome engine has a nasty javascript bug which prevents
+            //a correct order of scripts being loaded
+            //if you use script source on the head, we  have to revert
+            //to xhr+ globalEval for those
+            var b = _T.browser;
+            if (!b.isFF && !b.isWebkit && !b.isOpera >= 10) {
+                _T.loadScriptEval(src, type, defer, charSet);
+            } else {
+                //only firefox keeps the order, sorry ie...
+                _T.loadScriptByBrowser(src, type, defer, charSet, async);
+            }
+        };
+
+        //Base Patterns, Inheritance, Delegation and Singleton
+
+
+
+        /*
+         * prototype based delegation inheritance
+         *
+         * implements prototype delegaton inheritance dest <- a
+         *
+         * usage
+         * <pre>
+         *  var newClass = _T.extends( function (var1, var2) {
+         *                                          _T._callSuper("constructor", var1,var2);
+         *                                     };
+         *                                  ,origClass);
+         *
+         *       newClass.prototype.myMethod = function(arg1) {
+         *              _T._callSuper("myMethod", arg1,"hello world");
+         *       ....
+         *
+         * other option
+         *
+         * myfaces._impl._core._Runtime.extends("myNamespace.newClass", parent, {
+         *                              init: function() {constructor...},
+         *                              method1: function(f1, f2) {},
+         *                              method2: function(f1, f2,f3) {
+         *                                  _T._callSuper("method2", F1,"hello world");
+         *                              }
+         *              });
+         * </p>
+         * @param {function|String} newCls either a unnamed function which can be assigned later or a namespace
+         * @param {function} extendCls the function class to be extended
+         * @param {Object} protoFuncs (Map) an optional map of prototype functions which in case of overwriting a base function get an inherited method
+         *
+         * To explain further
+         * prototype functions:
+         * <pre>
+         *  newClass.prototype.<prototypeFunction>
+         * namspace function
+         *  newCls.<namespaceFunction> = function() {...}
+         *  </pre>
+         */
+
+        this.extendClass = function(newCls, extendCls, protoFuncs, nmsFuncs) {
+
+            if (!_T.isString(newCls)) {
+                throw Error("new class namespace must be of type String");
+            }
+            var className = newCls;
+
+            if (_T._reservedNMS[newCls]) {
+                return _T.fetchNamespace(newCls);
+            }
+            var constr = "constructor_";
+            var parClassRef = "_mfClazz";
+            if(!protoFuncs[constr]) {
+              protoFuncs[constr] =  (extendCls[parClassRef]  || (extendCls.prototype && extendCls.prototype[parClassRef])) ?
+                      function() {this._callSuper("constructor_");}: function() {};
+              var assigned = true;
+            }
+
+            if ('function' != typeof newCls) {
+                newCls = _reserveClsNms(newCls, protoFuncs);
+                if (!newCls) return null;
+            }
+            //if the type information is known we use that one
+            //with this info we can inherit from objects also
+            //instead of only from classes
+            //sort of like   this.extendClass(newCls, extendObj._mfClazz...
+
+            if (extendCls[parClassRef]) {
+                extendCls = extendCls[parClassRef];
+            }
+
+            if ('undefined' != typeof extendCls && null != extendCls) {
+                //first we have to get rid of the constructor calling problem
+                //problem
+                var tmpFunc = function() {
+                };
+                tmpFunc.prototype = extendCls.prototype;
+
+                var newClazz = newCls;
+                newClazz.prototype = new tmpFunc();
+                tmpFunc = null;
+                var clzProto = newClazz.prototype;
+                clzProto.constructor = newCls;
+                clzProto._parentCls = extendCls.prototype;
+                //in case of overrides the namespace is altered with mfclazz
+                //we want the final namespace
+                clzProto._nameSpace = className.replace(/(\._mfClazz)+$/,"");
+                /**
+                 * @ignore
+                 */
+                clzProto._callSuper = function(methodName) {
+                    var passThrough = (arguments.length == 1) ? [] : Array.prototype.slice.call(arguments, 1);
+                    var accDescLevel = "_mfClsDescLvl";
+                    //we store the descension level of each method under a mapped
+                    //name to avoid name clashes
+                    //to avoid name clashes with internal methods of array
+                    //if we don't do this we trap the callSuper in an endless
+                    //loop after descending one level
+                    var _mappedName = ["_",methodName,"_mf_r"].join("");
+                    this[accDescLevel] = this[accDescLevel] || new Array();
+                    var descLevel = this[accDescLevel];
+                    //we have to detect the descension level
+                    //we now check if we are in a super descension for the current method already
+                    //if not we are on this level
+                    var _oldDescLevel = this[accDescLevel][_mappedName] || this;
+                    //we now step one level down
+                    var _parentCls = _oldDescLevel._parentCls;
+                    var ret = null;
+                    try {
+                        //we now store the level position as new descension level for callSuper
+                        descLevel[_mappedName] = _parentCls;
+                        //and call the code on this
+                        if(!_parentCls[methodName]) {
+                            throw Error("Method _callSuper('"+ methodName+"')  called from "+className+" Method does not exist ");
+                        }
+                        ret = _parentCls[methodName].apply(this, passThrough);
+                    } finally {
+                        descLevel[_mappedName] = _oldDescLevel;
+                    }
+                    if('undefined' != typeof ret) {
+                        return ret;
+                    }
+                };
+                //reference to its own type
+                clzProto[parClassRef] = newCls;
+                _T._registeredClasses.push(clzProto);
+            }
+
+            //we now map the function map in
+            _T._applyFuncs(newCls, protoFuncs, true);
+            //we could add inherited but that would make debugging harder
+            //see http://www.ruzee.com/blog/2008/12/javascript-inheritance-via-prototypes-and-closures on how to do it
+
+            _T._applyFuncs(newCls, nmsFuncs, false);
+
+            return newCls;
+        };
+
+
+
+        /**
+         * Extends a class and puts a singleton instance at the reserved namespace instead
+         * of its original class
+         *
+         * @param {function|String} newCls either a unnamed function which can be assigned later or a namespace
+         * @param {function} extendsCls the function class to be extended
+         * @param {Object} protoFuncs (Map) an optional map of prototype functions which in case of overwriting a base function get an inherited method
+         */
+        this.singletonExtendClass = function(newCls, extendsCls, protoFuncs, nmsFuncs) {
+            _T._registeredSingletons[newCls] = true;
+            return _T._makeSingleton(_T.extendClass, newCls, extendsCls, protoFuncs, nmsFuncs);
+        };
+
+
+
+        //since the object is self contained and only
+        //can be delegated we can work with real private
+        //functions here, the other parts of the
+        //system have to emulate them via _ prefixes
+        this._makeSingleton = function(ooFunc, newCls, delegateObj, protoFuncs, nmsFuncs) {
+            if (_T._reservedNMS[newCls]) {
+                return _T._reservedNMS[newCls];
+            }
+
+            var clazz = ooFunc(newCls + "._mfClazz", delegateObj, protoFuncs, nmsFuncs);
+            if (clazz != null) {
+                _T.applyToGlobalNamespace(newCls, new clazz());
+            }
+            return _T.fetchNamespace(newCls)["_mfClazz"] = clazz;
+        };
+
+        //internal class namespace reservation depending on the type (string or function)
+        var _reserveClsNms = function(newCls, protoFuncs) {
+            var constr = null;
+            var UDEF = "undefined";
+            if (UDEF != typeof protoFuncs && null != protoFuncs) {
+                constr = (UDEF != typeof null != protoFuncs['constructor_'] && null != protoFuncs['constructor_']) ? protoFuncs['constructor_'] : function() {
+                };
+            } else {
+                constr = function() {
+                };
+            }
+
+            if (!_T.reserveNamespace(newCls, constr)) {
+                return null;
+            }
+            newCls = _T.fetchNamespace(newCls);
+            return newCls;
+        };
+
+        this._applyFuncs = function (newCls, funcs, proto) {
+            if (funcs) {
+                for (var key in funcs) {
+                    //constructor already passed, callSuper already assigned
+                    if ('undefined' == typeof key || null == key || key == "_callSuper") {
+                        continue;
+                    }
+                    if (!proto)
+                        newCls[key] = funcs[key];
+                    else
+                        newCls.prototype[key] = funcs[key];
+                }
+            }
+        };
+
+        /**
+         * general type assertion routine
+         *
+         * @param probe the probe to be checked for the correct type
+         * @param theType the type to be checked for
+         */
+        this.assertType = function(probe, theType) {
+            return _T.isString(theType) ? probe == typeof theType : probe instanceof theType;
+        };
+
+        /**
+         * onload wrapper for chaining the onload cleanly
+         * @param func the function which should be added to the load
+         * chain (note we cannot rely on return values here, hence jsf.util.chain will fail)
+         */
+        this.addOnLoad = function(target, func) {
+            var oldonload = (target) ? target.onload : null;
+            target.onload = (!oldonload) ? func : function() {
+                try {
+                    oldonload();
+                } catch (e) {
+                    throw e;
+                } finally {
+                    func();
+                }
+            };
+        };
+
+        /**
+         * returns the internationalisation setting
+         * for the given browser so that
+         * we can i18n our messages
+         *
+         * @returns a map with following entires:
+         * <ul>
+         *      <li>language: the lowercase language iso code</li>
+         *      <li>variant: the uppercase variant iso code</li>
+         * </ul>
+         * null is returned if the browser fails to determine the language settings
+         */
+        this.getLanguage = function(lOverride) {
+            var deflt = {language: "en", variant: "UK"}; //default language and variant
+            try {
+                var lang = lOverride || navigator.language || navigator.browserLanguage;
+                if (!lang || lang.length < 2) return deflt;
+                return {
+                    language: lang.substr(0, 2),
+                    variant: (lang.length >= 5) ? lang.substr(3, 5) : null
+                };
+            } catch(e) {
+                return deflt;
+            }
+        };
+
+        //implemented in extruntime
+        this.singletonDelegateObj = function()  {};
+
+        /**
+        * browser detection code
+        * cross ported from dojo 1.2
+        *
+        * dojos browser detection code is very sophisticated
+        * hence we port it over it allows a very fine grained detection of
+        * browsers including the version number
+        * this however only can work out if the user
+        * does not alter the user agent, which they normally dont!
+        *
+        * the exception is the ie detection which relies on specific quirks in ie
+        */
+       var n = navigator;
+       var dua = n.userAgent,
+               dav = n.appVersion,
+               tv = parseFloat(dav);
+       var _T = this;
+       _T.browser = {};
+       myfaces._impl.core._EvalHandlers.browser = _T.browser;
+       var d = _T.browser;
+
+       if (dua.indexOf("Opera") >= 0) {
+           _T.isOpera = tv;
+       }
+       if (dua.indexOf("AdobeAIR") >= 0) {
+           d.isAIR = 1;
+       }
+       if (dua.indexOf("BlackBerry") >= 0) {
+           d.isBlackBerry = tv;
+       }
+       d.isKhtml = (dav.indexOf("Konqueror") >= 0) ? tv : 0;
+       d.isWebKit = parseFloat(dua.split("WebKit/")[1]) || undefined;
+       d.isChrome = parseFloat(dua.split("Chrome/")[1]) || undefined;
+
+       // safari detection derived from:
+       //		http://developer.apple.com/internet/safari/faq.html#anchor2
+       //		http://developer.apple.com/internet/safari/uamatrix.html
+       var index = Math.max(dav.indexOf("WebKit"), dav.indexOf("Safari"), 0);
+       if (index && !d.isChrome) {
+           // try to grab the explicit Safari version first. If we don't get
+           // one, look for less than 419.3 as the indication that we're on something
+           // "Safari 2-ish".
+           d.isSafari = parseFloat(dav.split("Version/")[1]);
+           if (!d.isSafari || parseFloat(dav.substr(index + 7)) <= 419.3) {
+               d.isSafari = 2;
+           }
+       }
+
+       //>>excludeStart("webkitMobile", kwArgs.webkitMobile);
+
+       if (dua.indexOf("Gecko") >= 0 && !d.isKhtml && !d.isWebKit) {
+           d.isMozilla = d.isMoz = tv;
+       }
+       if (d.isMoz) {
+           //We really need to get away from _T. Consider a sane isGecko approach for the future.
+           d.isFF = parseFloat(dua.split("Firefox/")[1] || dua.split("Minefield/")[1] || dua.split("Shiretoko/")[1]) || undefined;
+       }
+
+       if (document.all && !d.isOpera && !d.isBlackBerry) {
+           d.isIE = parseFloat(dav.split("MSIE ")[1]) || undefined;
+           d.isIEMobile = parseFloat(dua.split("IEMobile")[1]);
+           //In cases where the page has an HTTP header or META tag with
+           //X-UA-Compatible, then it is in emulation mode, for a previous
+           //version. Make sure isIE reflects the desired version.
+           //document.documentMode of 5 means quirks mode.
+
+           /** @namespace document.documentMode */
+           if (d.isIE >= 8 && document.documentMode != 5) {
+               d.isIE = document.documentMode;
+           }
+       }
+    };
+}
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+if (!document.querySelectorAll || !window.XMLHttpRequest) {
+
+    //initial browser detection, we encapsule it in a closure
+    //to drop all temporary variables from ram as soon as possible
+    //we run into the quirks fallback if XMLHttpRequest is not enabled
+    (function() {
+        var _T  = myfaces._impl.core._Runtime;
+
+        _T.getXHRObject = function() {
+            //since this is a global object ie hates it if we do not check for undefined
+            if (window.XMLHttpRequest) {
+                var _ret = new XMLHttpRequest();
+                //we now check the xhr level
+                //sendAsBinary = 1.5 which means mozilla only
+                //upload attribute present == level2
+
+                if (!_T.XHR_LEVEL) {
+                    var _e = _T.exists;
+                    _T.XHR_LEVEL = (_e(_ret, "sendAsBinary")) ? 1.5 : 1;
+                    _T.XHR_LEVEL = (_e(_ret, "upload") && 'undefined' != typeof FormData) ? 2 : _T.XHR_LEVEL;
+                }
+                return _ret;
+            }
+            //IE
+            try {
+                _T.XHR_LEVEL = 1;
+                return new ActiveXObject("Msxml2.XMLHTTP");
+            } catch (e) {
+
+            }
+            return new ActiveXObject('Microsoft.XMLHTTP');
+        };
+
+
+    })();
+}
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*we cannot privatize with a global function hence we store the values away for the init part*/
+(function() {
+    var target = window || document.body;
+    var impl = "myfaces._impl.";
+    var params = {_PFX_UTIL: impl + "_util.",
+            _PFX_CORE:impl + "core.",
+            _PFX_XHR: impl + "xhrCore.",
+            _PFX_I18N: impl + "i18n."};
+    if ('undefined' != typeof target.myfaces) {
+        //some mobile browsers do not have a window object
+        var _RT = myfaces._impl.core._Runtime;
+        params._MF_CLS = _RT.extendClass;
+        params._MF_SINGLTN = _RT.singletonExtendClass;
+    } else {
+        params._MF_CLS = false;
+        params._MF_SINGLTN = false;
+        target.myfaces = {};
+    }
+    target.myfaces._implTemp = {};
+    for (var key in params) {
+            target.myfaces._implTemp[key] = target[key];
+            target[key] = params[key];
+    }
+})();
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @memberOf myfaces._impl
+ * @namespace
+ * @name i18n
+ */
+
+/**
+ * System messages base version    <p />
+ * (note the base version is basically the en_US) version
+ * of all messages
+ *
+ * @class
+ * @name Messages
+ * @memberOf myfaces._impl.i18n
+ */
+_MF_CLS && _MF_CLS(_PFX_I18N+"Messages", Object,
+/**
+ * @lends myfaces._impl.i18n.Messages.prototype
+ */
+{
+
+    MSG_TEST:               "Testmessage",
+
+    /*Messages*/
+    /** @constant */
+    MSG_DEV_MODE:           "Note, this message is only sent, because project stage is development and no " +
+                            "other error listeners are registered.",
+    /** @constant */
+    MSG_AFFECTED_CLASS:     "Affected Class:",
+    /** @constant */
+    MSG_AFFECTED_METHOD:    "Affected Method:",
+    /** @constant */
+    MSG_ERROR_NAME:         "Error Name:",
+    /** @constant */
+    MSG_ERROR_MESSAGE:      "Error Message:",
+    /** @constant */
+    MSG_SERVER_ERROR_NAME:  "Server Error Name:",
+
+    /** @constant */
+    MSG_ERROR_DESC:         "Error Description:",
+    /** @constant */
+    MSG_ERROR_NO:           "Error Number:",
+    /** @constant */
+    MSG_ERROR_LINENO:       "Error Line Number:",
+
+    /*Errors and messages*/
+    /** @constant */
+    ERR_FORM:               "Sourceform could not be determined, either because element is not attached to a form or we have multiple forms with named elements of the same identifier or name, stopping the ajax processing",
+    /** @constant */
+    ERR_VIEWSTATE:          "jsf.viewState: param value not of type form!",
+    /** @constant */
+    ERR_TRANSPORT:          "Transport type {0} does not exist",
+    /** @constant */
+    ERR_EVT_PASS:           "an event must be passed down (either a an event object null or undefined) ",
+    /** @constant */
+    ERR_CONSTRUCT:          "Parts of the response couldn't be retrieved when constructing the event data: {0} ",
+    /** @constant */
+    ERR_MALFORMEDXML:       "The server response could not be parsed, the server has returned with a response which is not xml !",
+    /** @constant */
+    ERR_SOURCE_FUNC:        "source cannot be a function (probably source and event were not defined or set to null",
+    /** @constant */
+    ERR_EV_OR_UNKNOWN:      "An event object or unknown must be passed as second parameter",
+    /** @constant */
+    ERR_SOURCE_NOSTR:       "source cannot be a string",
+    /** @constant */
+    ERR_SOURCE_DEF_NULL:    "source must be defined or null",
+
+    //_Lang.js
+    /** @constant */
+    ERR_MUST_STRING:        "{0}: {1} namespace must be of type String",
+    /** @constant */
+    ERR_REF_OR_ID:          "{0}: {1} a reference node or identifier must be provided",
+    /** @constant */
+    ERR_PARAM_GENERIC:      "{0}: parameter {1} must be of type {2}",
+    /** @constant */
+    ERR_PARAM_STR:          "{0}: {1} param must be of type string",
+    /** @constant */
+    ERR_PARAM_STR_RE:       "{0}: {1} param must be of type string or a regular expression",
+    /** @constant */
+    ERR_PARAM_MIXMAPS:      "{0}: both a source as well as a destination map must be provided",
+    /** @constant */
+    ERR_MUST_BE_PROVIDED:   "{0}: an {1} and a {2} must be provided",
+    /** @constant */
+    ERR_MUST_BE_PROVIDED1:  "{0}: {1} must be set",
+
+    /** @constant */
+    ERR_REPLACE_EL:         "replaceElements called while evalNodes is not an array",
+
+    /** @constant */
+    ERR_EMPTY_RESPONSE:     "{0}: The response cannot be null or empty!",
+    /** @constant */
+    ERR_ITEM_ID_NOTFOUND:   "{0}: item with identifier {1} could not be found",
+    /** @constant */
+    ERR_PPR_IDREQ:          "{0}: Error in PPR Insert, id must be present",
+    /** @constant */
+    ERR_PPR_INSERTBEFID:    "{0}: Error in PPR Insert, before id or after id must be present",
+    /** @constant */
+    ERR_PPR_INSERTBEFID_1:  "{0}: Error in PPR Insert, before  node of id {1} does not exist in document",
+    /** @constant */
+    ERR_PPR_INSERTBEFID_2:  "{0}: Error in PPR Insert, after  node of id {1} does not exist in document",
+
+    /** @constant */
+    ERR_PPR_DELID:          "{0}: Error in delete, id not in xml markup",
+    /** @constant */
+    ERR_PPR_UNKNOWNCID:     "{0}:  Unknown Html-Component-ID: {1}",
+
+    /** @constant */
+    ERR_NO_VIEWROOTATTR:    "{0}: Changing of ViewRoot attributes is not supported",
+    /** @constant */
+    ERR_NO_HEADATTR:        "{0}: Changing of Head attributes is not supported",
+    /** @constant */
+    ERR_RED_URL:            "{0}: Redirect without url",
+
+    /** @constant */
+    ERR_REQ_FAILED_UNKNOWN: "Request failed with unknown status",
+
+    /** @constant */
+    ERR_REQU_FAILED: "Request failed with status {0} and reason {1}",
+
+    /** @constant */
+    UNKNOWN: "UNKNOWN",
+
+    ERR_NO_MULTIPART_FORM: "The form with the id {0} has an input file element, but is not a multipart form"
+});
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * System messages german version
+ * (note the base version is basically the en_US) version
+ * of all messages
+ * <p />
+ * We use inheritance to overide the default messages with our
+ * german one, variants can derive from the german one (like
+ * suisse which do not have the emphasized s)
+ * <p />
+ * By using inheritance we can be sure that we fall back to the default one
+ * automatically and that our variants only have to override the parts
+ * which have changed from the baseline
+ *
+ * @class
+ * @name Messages_de
+ * @extends myfaces._impl.i18n.Messages
+ * @memberOf myfaces._impl.i18n
+ */
+
+_MF_CLS && _MF_CLS(_PFX_I18N + "Messages_de", myfaces._impl.i18n.Messages,
+        /** @lends myfaces._impl.i18n.Messages_de.prototype */
+        {
+
+            MSG_TEST:               "Testnachricht",
+
+            /*Messages*/
+            MSG_DEV_MODE:           "Sie sehen diese Nachricht, da sie sich gerade im Entwicklungsmodus befinden " +
+                    "und sie keine Fehlerbehandlungsfunktionen registriert haben.",
+
+            MSG_AFFECTED_CLASS:     "Klasse:",
+            MSG_AFFECTED_METHOD:    "Methode:",
+
+            MSG_ERROR_NAME:         "Fehler Name:",
+            MSG_ERROR_MESSAGE:      "Nachricht:",
+            MSG_SERVER_ERROR_NAME:  "Server Fehler Name:",
+
+            MSG_ERROR_DESC:         "Fehlerbeschreibung:",
+            MSG_ERROR_NO:           "Fehlernummer:",
+            MSG_ERROR_LINENO:       "Zeilennummer:",
+
+            /*Errors and messages*/
+            ERR_FORM:                "Das Quellformular konnte nicht gefunden werden. " +
+                    "Mögliche Gründe: Sie haben entweder kein formular definiert, oder es kommen mehrere Formulare vor, " +
+                    "die alle das auslösende Element mit demselben Namen besitzen. " +
+                    "Die Weitere Ajax Ausführung wird gestoppt.",
+
+            ERR_VIEWSTATE:          "jsf.viewState: der Parameter ist not vom Typ form!",
+
+            ERR_TRANSPORT:          "Transport typ {0} existiert nicht",
+            ERR_EVT_PASS:           "Ein Event Objekt muss übergeben werden (entweder ein event Objekt oder null oder undefined)",
+            ERR_CONSTRUCT:          "Teile des response konnten nicht ermittelt werden während die Event Daten bearbeitet wurden: {0} ",
+            ERR_MALFORMEDXML:       "Es gab zwar eine Antwort des Servers, jedoch war diese nicht im erwarteten XML Format. Der Server hat kein valides XML gesendet! Bearbeitung abgebrochen.",
+            ERR_SOURCE_FUNC:        "source darf keine Funktion sein",
+            ERR_EV_OR_UNKNOWN:      "Ein Ereignis Objekt oder UNKNOWN muss als 2. Parameter übergeben werden",
+            ERR_SOURCE_NOSTR:       "source darf kein String sein",
+            ERR_SOURCE_DEF_NULL:    "source muss entweder definiert oder null sein",
+
+            //_Lang.js
+            ERR_MUST_STRING:        "{0}: {1} namespace muss vom Typ String sein",
+            ERR_REF_OR_ID:          "{0}: {1} Ein Referenzknoten oder id muss übergeben werden",
+            ERR_PARAM_GENERIC:      "{0}: Paramter {1} muss vom Typ {2} sein",
+            ERR_PARAM_STR:          "{0}: Parameter {1} muss vom Typ String sein",
+            ERR_PARAM_STR_RE:       "{0}: Parameter {1} muss entweder ein String oder ein Regulärer Ausdruck sein",
+            ERR_PARAM_MIXMAPS:      "{0}: both a source as well as a destination map must be provided",
+            ERR_MUST_BE_PROVIDED:   "{0}: ein {1} und ein {2} müssen übergeben werden",
+            ERR_MUST_BE_PROVIDED1:  "{0}: {1} muss gesetzt sein",
+
+            ERR_REPLACE_EL:         "replaceElements aufgerufen während evalNodes nicht ein Array ist",
+            ERR_EMPTY_RESPONSE:     "{0}: Die Antwort darf nicht null oder leer sein!",
+            ERR_ITEM_ID_NOTFOUND:   "{0}: Element mit ID {1} konnte nicht gefunden werden",
+            ERR_PPR_IDREQ:          "{0}: Fehler im PPR Insert, ID muss gesetzt sein",
+            ERR_PPR_INSERTBEFID:    "{0}: Fehler im PPR Insert, before ID oder after ID muss gesetzt sein",
+            ERR_PPR_INSERTBEFID_1:  "{0}: Fehler im PPR Insert, before  Knoten mit ID {1} Existiert nicht",
+            ERR_PPR_INSERTBEFID_2:  "{0}: Fehler im PPR Insert, after  Knoten mit ID {1} Existiert nicht",
+
+            ERR_PPR_DELID:          "{0}: Fehler im PPR delete, id ist nicht im xml Markup vorhanden",
+            ERR_PPR_UNKNOWNCID:     "{0}: Unbekannte Html-Komponenten-ID: {1}",
+            ERR_NO_VIEWROOTATTR:    "{0}: Änderung von ViewRoot Attributen ist nicht erlaubt",
+            ERR_NO_HEADATTR:        "{0}: Änderung von Head Attributen ist nicht erlaubt",
+            ERR_RED_URL:            "{0}: Redirect ohne URL",
+
+            ERR_REQ_FAILED_UNKNOWN: "Anfrage mit unbekanntem Status fehlgeschlagen",
+            ERR_REQU_FAILED: "Anfrage mit Status {0} and Ursache {1} fehlgeschlagen",
+            UNKNOWN: "Unbekannt",
+            ERR_NO_MULTIPART_FORM: "Das Form Element mit der ID {0} hat ein Fileupload Feld aber ist kein Multipart Form"
+
+        });
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * System messages dutch version
+ *
+ * @class
+ * @name Messages_nl
+ * @extends myfaces._impl.i18n.Messages
+ * @memberOf myfaces._impl.i18n
+ */
+_MF_CLS && _MF_CLS(_PFX_I18N + "Messages_nl", myfaces._impl.i18n.Messages,
+        /** @lends myfaces._impl.i18n.Messages_nl.prototype */
+        {
+
+            MSG_TEST:               "Testbericht",
+
+            /*Messages*/
+            MSG_DEV_MODE:           "Opmerking, dit bericht is enkel gestuurd omdat het project stadium develoment is en er geen " +
+                    "andere listeners zijn geconfigureerd.",
+            MSG_AFFECTED_CLASS:     "Betrokken Klasse:",
+            MSG_AFFECTED_METHOD:    "Betrokken Methode:",
+
+            MSG_ERROR_NAME:         "Naam foutbericht:",
+            MSG_ERROR_MESSAGE:      "Naam foutbericht:",
+
+            MSG_ERROR_DESC:         "Omschrijving fout:",
+            MSG_ERROR_NO:           "Fout nummer:",
+            MSG_ERROR_LINENO:       "Fout lijn nummer:",
+
+            /*Errors and messages*/
+            ERR_FORM:               "De doel form kon niet bepaald worden, ofwel omdat het element niet tot een form behoort, ofwel omdat er verschillende forms zijn met 'named element' met dezelfde identifier of naam, ajax verwerking is gestopt.",
+            ERR_VIEWSTATE:          "jsf.viewState: param waarde is niet van het type form!",
+            ERR_TRANSPORT:          "Transport type {0} bestaat niet",
+            ERR_EVT_PASS:           "een event moet opgegegevn worden (ofwel een event object null of undefined) ",
+            ERR_CONSTRUCT:          "Delen van het antwoord konden niet opgehaald worden bij het aanmaken van de event data: {0} ",
+            ERR_MALFORMEDXML:       "Het antwoordt van de server kon niet ontleed worden, de server heeft een antwoord gegeven welke geen xml bevat!",
+            ERR_SOURCE_FUNC:        "source kan geen functie zijn (waarschijnlijk zijn source en event niet gedefinieerd of kregen de waarde null)",
+            ERR_EV_OR_UNKNOWN:      "Een event object of 'unknown' moet gespecifieerd worden als tweede parameter",
+            ERR_SOURCE_NOSTR:       "source kan geen string zijn",
+            ERR_SOURCE_DEF_NULL:    "source moet gedefinieerd zijn of null bevatten",
+
+            //_Lang.js
+            ERR_MUST_STRING:        "{0}: {1} namespace moet van het type String zijn",
+            ERR_REF_OR_ID:          "{0}: {1} een referentie node of identifier moet opgegeven worden",
+            ERR_PARAM_GENERIC:      "{0}: parameter {1} moet van het type {2} zijn",
+            ERR_PARAM_STR:          "{0}: {1} parameter moet van het type string zijn",
+            ERR_PARAM_STR_RE:       "{0}: {1} parameter moet van het type string zijn of een reguliere expressie",
+            ERR_PARAM_MIXMAPS:      "{0}: zowel source als destination map moeten opgegeven zijn",
+            ERR_MUST_BE_PROVIDED:   "{0}: een {1} en een {2} moeten opgegeven worden",
+            ERR_MUST_BE_PROVIDED1:  "{0}: {1} moet gezet zijn",
+
+            ERR_REPLACE_EL:         "replaceElements opgeroepen maar evalNodes is geen array",
+            ERR_EMPTY_RESPONSE:     "{0}: Het antwoord kan geen null of leeg zijn!",
+            ERR_ITEM_ID_NOTFOUND:   "{0}: item met identifier {1} kan niet gevonden worden",
+            ERR_PPR_IDREQ:          "{0}: Fout in PPR Insert, id moet bestaan",
+            ERR_PPR_INSERTBEFID:    "{0}: Fout in PPR Insert, before id of after id moet bestaan",
+            ERR_PPR_INSERTBEFID_1:  "{0}: Fout in PPR Insert, before node van id {1} bestaat niet in het document",
+            ERR_PPR_INSERTBEFID_2:  "{0}: Fout in PPR Insert, after node van id {1} bestaat niet in het document",
+
+            ERR_PPR_DELID:          "{0}: Fout in delete, id is niet in de xml markup",
+            ERR_PPR_UNKNOWNCID:     "{0}: Onbekende Html-Component-ID: {1}",
+            ERR_NO_VIEWROOTATTR:    "{0}: Wijzigen van ViewRoot attributen is niet ondersteund",
+            ERR_NO_HEADATTR:        "{0}: Wijzigen van Head attributen is niet ondersteund",
+            ERR_RED_URL:            "{0}: Redirect zonder url",
+
+            ERR_REQ_FAILED_UNKNOWN: "Request mislukt met onbekende status",
+            ERR_REQU_FAILED:        "Request mislukt met status {0} en reden {1}",
+            UNKNOWN:                "ONBEKEND"
+
+        });
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * System messages spanish version version
+ * (note the base version is basically the en_US) version
+ * of all messages
+ *
+ * @class
+ * @name Messages_es
+ * @extends myfaces._impl.i18n.Messages
+ * @memberOf myfaces._impl.i18n
+ */
+
+_MF_CLS && _MF_CLS(_PFX_I18N + "Messages_es", myfaces._impl.i18n.Messages,
+        /** @lends myfaces._impl.i18n.Messages_es.prototype */
+        {
+
+
+            MSG_TEST:               "Mensajeprueba",
+
+            /*Messages*/
+            MSG_DEV_MODE:           "Aviso. Este mensaje solo se envia porque el 'Project Stage' es 'Development' y no hay otros 'listeners' de errores registrados.",
+            MSG_AFFECTED_CLASS:     "Clase Afectada:",
+            MSG_AFFECTED_METHOD:    "M�todo Afectado:",
+
+            MSG_ERROR_NAME:         "Nombre del Error:",
+            MSG_ERROR_MESSAGE:      "Mensaje del Error:",
+            MSG_SERVER_ERROR_NAME:  "Mensaje de error de servidor:",
+
+            MSG_ERROR_DESC:         "Descripci�n del Error:",
+            MSG_ERROR_NO:           "N�mero de Error:",
+            MSG_ERROR_LINENO:       "N�mero de L�nea del Error:",
+
+            /*Errors and messages*/
+            ERR_FORM:               "El formulario de origen no ha podido ser determinado, debido a que el elemento no forma parte de un formulario o hay diversos formularios con elementos usando el mismo nombre o identificador. Parando el procesamiento de Ajax.",
+            ERR_VIEWSTATE:          "jsf.viewState: el valor del par�metro no es de tipo 'form'!",
+            ERR_TRANSPORT:          "El tipo de transporte {0} no existe",
+            ERR_EVT_PASS:           "un evento debe ser transmitido (sea null o no definido)",
+            ERR_CONSTRUCT:          "Partes de la respuesta no pudieron ser recuperadas cuando construyendo los datos del evento: {0} ",
+            ERR_MALFORMEDXML:       "La respuesta del servidor no ha podido ser interpretada. El servidor ha devuelto una respuesta que no es xml !",
+            ERR_SOURCE_FUNC:        "el origen no puede ser una funci�n (probablemente 'source' y evento no han sido definidos o son 'null'",
+            ERR_EV_OR_UNKNOWN:      "Un objeto de tipo evento o desconocido debe ser pasado como segundo par�metro",
+            ERR_SOURCE_NOSTR:       "el origen no puede ser 'string'",
+            ERR_SOURCE_DEF_NULL:    "el origen debe haber sido definido o ser 'null'",
+
+            //_Lang.js
+            ERR_MUST_STRING:        "{0}: {1} namespace debe ser de tipo String",
+            ERR_REF_OR_ID:          "{0}: {1} una referencia a un nodo o identificador tiene que ser pasada",
+            ERR_PARAM_GENERIC:      "{0}: el par�metro {1} tiene que ser de tipo {2}",
+            ERR_PARAM_STR:          "{0}: el par�metro {1} tiene que ser de tipo string",
+            ERR_PARAM_STR_RE:       "{0}: el par�metro {1} tiene que ser de tipo string o una expresi�n regular",
+            ERR_PARAM_MIXMAPS:      "{0}: han de ser pasados tanto un origen como un destino",
+            ERR_MUST_BE_PROVIDED:   "{0}: {1} y {2} deben ser pasados",
+            ERR_MUST_BE_PROVIDED1:  "{0}: {1} debe estar definido",
+
+            ERR_REPLACE_EL:         "replaceElements invocado mientras que evalNodes no es un an array",
+            ERR_EMPTY_RESPONSE:     "{0}: �La respuesta no puede ser de tipo 'null' o vac�a!",
+            ERR_ITEM_ID_NOTFOUND:   "{0}: el elemento con identificador {1} no ha sido encontrado",
+            ERR_PPR_IDREQ:          "{0}: Error en PPR Insert, 'id' debe estar presente",
+            ERR_PPR_INSERTBEFID:    "{0}: Error in PPR Insert, antes de 'id' o despu�s de 'id' deben estar presentes",
+            ERR_PPR_INSERTBEFID_1:  "{0}: Error in PPR Insert, antes de nodo con id {1} no existe en el documento",
+            ERR_PPR_INSERTBEFID_2:  "{0}: Error in PPR Insert, despu�s de nodo con id {1} no existe en el documento",
+
+            ERR_PPR_DELID:          "{0}: Error durante borrado, id no presente en xml",
+            ERR_PPR_UNKNOWNCID:     "{0}:  Desconocido Html-Component-ID: {1}",
+            ERR_NO_VIEWROOTATTR:    "{0}: El cambio de atributos de ViewRoot attributes no es posible",
+            ERR_NO_HEADATTR:        "{0}: El cambio de los atributos de Head attributes no es posible",
+            ERR_RED_URL:            "{0}: Redirecci�n sin url",
+
+            ERR_REQ_FAILED_UNKNOWN: "La petici�n ha fallado con estado desconocido",
+            ERR_REQU_FAILED:        "La petici�n ha fallado con estado {0} y raz�n {1}",
+            UNKNOWN:                "DESCONOCIDO"
+
+        });
+
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+    /**
+     * System messages french version version
+     * (note the base version is basically the en) version
+     * of all messages
+     *
+     * @class
+     * @name Messages_fr
+     * @extends myfaces._impl.i18n.Messages
+     * @memberOf myfaces._impl.i18n
+     */
+_MF_CLS && _MF_CLS(_PFX_I18N + "Messages_fr", myfaces._impl.i18n.Messages,
+            /** @lends myfaces._impl.i18n.Messages_fr.prototype */
+            {
+                MSG_TEST:               "MessageTest FR",
+
+                /*Messages*/
+                MSG_DEV_MODE:           "Note : ce message n'est envoyé que parce que le projet est au stade de développement et " +
+                        "qu'aucun autre listener d'erreurs n'est enregistré.",
+                MSG_AFFECTED_CLASS:     "Classe affectée : ",
+                MSG_AFFECTED_METHOD:    "Méthode affectée : ",
+
+                MSG_ERROR_NAME:         "Nom de l'erreur : ",
+                MSG_ERROR_MESSAGE:      "Nom de l'erreur : ",
+
+                MSG_ERROR_DESC:         "Description de l'erreur : ",
+                MSG_ERROR_NO:           "Numéro de l'erreur : ",
+                MSG_ERROR_LINENO:       "Erreur à la ligne : ",
+
+                /*Errors and messages*/
+                ERR_FORM:               "Le formulaire source n'a pas pu être déterminé, soit parce que l'élément n'est rattaché à aucun formulaire, soit parce qu'ils y a plusieurs formulaires contenant des éléments avec le même nom ou identifiant. Arrêt du traitement AJAX",
+                ERR_VIEWSTATE:          "jsf.viewState: La valeur de 'param' n'est pas de type 'form' !",
+                ERR_TRANSPORT:          "Le type de tansport {0} n'existe pas",
+                ERR_EVT_PASS:           "Un évènement doit être transmis (soit un objet évènement, soit null ou undefined) ",
+                ERR_CONSTRUCT:          "Des éléments de la réponse n'ont pu être récupérés lors de la construction des données de l'évènement : {0} ",
+                ERR_MALFORMEDXML:       "La réponse du serveur n'a pas pu être analysée : le serveur n'a pas renvoyé une réponse en xml !",
+                ERR_SOURCE_FUNC:        "La source ne peut pas être une fonction (Il est probable que 'source' et 'event' n'ont pas été définis ou mis à null",
+                ERR_EV_OR_UNKNOWN:      "Le second paramètre doit être un objet évènement ou 'unknown' ",
+                ERR_SOURCE_NOSTR:       "La source ne peut pas être de type String",
+                ERR_SOURCE_DEF_NULL:    "La source doit être définie ou égale à null",
+
+                //_Lang.js
+                ERR_MUST_STRING:        "{0}: Le namespace {1} doit être de type String",
+                ERR_REF_OR_ID:          "{0}: {1} un noeud de référence ou un identifiant doit être passé",
+                ERR_PARAM_GENERIC:      "{0}: Le paramètre {1} doit être de type {2}",
+                ERR_PARAM_STR:          "{0}: Le paramètre {1} doit être de type String",
+                ERR_PARAM_STR_RE:       "{0}: Le paramètre {1} doit être de type String ou être une expression régulière",
+                ERR_PARAM_MIXMAPS:      "{0}: Un Map de source et un Map de destination doivent être passés",
+                ERR_MUST_BE_PROVIDED:   "{0}: un(e) {1} et un(e) {2} doivent être passés",
+                ERR_MUST_BE_PROVIDED1:  "{0}: {1} doit être défini",
+
+                ERR_REPLACE_EL:         "replaceElements a été appelé alors que evalNodes n'est pas un tableau",
+                ERR_EMPTY_RESPONSE:     "{0}: La réponse ne peut pas être nulle ou vide !",
+                ERR_ITEM_ID_NOTFOUND:   "{0}: l'élément portant l'identifiant {1} n'a pas pu être trouvé",
+                ERR_PPR_IDREQ:          "{0}: Erreur lors de l'insertion PPR, l'id doit être présent",
+                ERR_PPR_INSERTBEFID:    "{0}: Erreur lors de l'insertion PPR, 'before id' ou 'after id' doivent être présents",
+                ERR_PPR_INSERTBEFID_1:  "{0}: Erreur lors de l'insertion PPR, le noeud before de l'id {1} n'existe pas dans le document",
+                ERR_PPR_INSERTBEFID_2:  "{0}: Erreur lors de l'insertion PPR, le noeud after  de l'id {1} n'existe pas dans le document",
+
+                ERR_PPR_DELID:          "{0}: Erreur lors de la suppression, l'id n'est pas présent dans le xml",
+                ERR_PPR_UNKNOWNCID:     "{0}:  Html-Component-ID inconnu : {1}",
+                ERR_NO_VIEWROOTATTR:    "{0}: Le changement d'attributs dans ViewRoot n'est pas supporté",
+                ERR_NO_HEADATTR:        "{0}: Le changement d'attributs dans Head n'est pas supporté",
+                ERR_RED_URL:            "{0}: Redirection sans url"
+            });
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * System messages italian version version
+ * (note the base version is basically the en_US) version
+ * of all messages
+ *
+ * @class
+ * @name Messages_it
+ * @extends myfaces._impl.i18n.Messages
+ * @memberOf myfaces._impl.i18n
+ */
+_MF_CLS && _MF_CLS(_PFX_I18N + "Messages_it", myfaces._impl.i18n.Messages,
+        /** @lends myfaces._impl.i18n.Messages_it.prototype */
+        {
+            /*Messages*/
+            MSG_DEV_MODE:           "Questo messaggio � stato inviato esclusivamente perch� il progetto � in development stage e nessun altro listener � stato registrato.",
+            MSG_AFFECTED_CLASS:     "Classi coinvolte:",
+            MSG_AFFECTED_METHOD:    "Metodi coinvolti:",
+
+            MSG_ERROR_NAME:         "Nome dell'errore:",
+            MSG_ERROR_MESSAGE:      "Nome dell'errore:",
+
+            MSG_ERROR_DESC:         "Descrizione dell'errore:",
+            MSG_ERROR_NO:           "Numero errore:",
+            MSG_ERROR_LINENO:       "Numero di riga dell'errore:",
+
+            /*Errors and messages*/
+            ERR_FORM:               "Il Sourceform non puo' essere determinato a causa di una delle seguenti ragioni: l'elemento non e' agganciato ad un form oppure sono presenti pi� form con elementi con lo stesso nome, il che blocca l'elaborazione ajax",
+            ERR_VIEWSTATE:          "jsf.viewState: il valore del parametro non � di tipo form!",
+            ERR_TRANSPORT:          "Il transport type {0} non esiste",
+            ERR_EVT_PASS:           "� necessario passare un evento (sono accettati anche gli event object null oppure undefined) ",
+            ERR_CONSTRUCT:          "Durante la costruzione dell' event data: {0} non � stato possibile acquisire alcune parti della response ",
+            ERR_MALFORMEDXML:       "Il formato della risposta del server non era xml, non � stato quindi possibile effettuarne il parsing!",
+            ERR_SOURCE_FUNC:        "source non puo' essere una funzione (probabilmente source and event non erano stati definiti o sono null",
+            ERR_EV_OR_UNKNOWN:      "Come secondo parametro bisogna passare un event object oppure unknown",
+            ERR_SOURCE_NOSTR:       "source non pu� essere una stringa di testo",
+            ERR_SOURCE_DEF_NULL:    "source deve essere definito oppure  null",
+
+            //_Lang.js
+            ERR_MUST_STRING:        "{0}: {1} namespace deve essere di tipo String",
+            ERR_REF_OR_ID:          "{0}: {1} un reference node oppure un identificatore deve essere fornito",
+            ERR_PARAM_GENERIC:      "{0}: il parametro {1} deve essere di tipo {2}",
+            ERR_PARAM_STR:          "{0}: {1} parametro deve essere di tipo String",
+            ERR_PARAM_STR_RE:       "{0}: {1} parametro deve essere di tipo String oppure una regular expression",
+            ERR_PARAM_MIXMAPS:      "{0}: � necessario specificare sia  source che destination map",
+            ERR_MUST_BE_PROVIDED:   "{0}: � necessario specificare sia {1} che {2} ",
+            ERR_MUST_BE_PROVIDED1:  "{0}: {1} deve essere settato",
+
+            ERR_REPLACE_EL:         "replaceElements chiamato metre evalNodes non � un array",
+            ERR_EMPTY_RESPONSE:     "{0}: La response non puo' essere nulla o vuota!",
+            ERR_ITEM_ID_NOTFOUND:   "{0}: non � stato trovato alcun item con identificativo {1}",
+            ERR_PPR_IDREQ:          "{0}: Errore durante la PPR Insert, l' id deve essere specificato",
+            ERR_PPR_INSERTBEFID:    "{0}: Errore durante la PPR Insert, before id o after id deve essere specificato",
+            ERR_PPR_INSERTBEFID_1:  "{0}: Errore durante la PPR Insert, before node of id {1} non esiste nel document",
+            ERR_PPR_INSERTBEFID_2:  "{0}: Errore durante la PPR Insert, after  node of id {1} non esiste nel in document",
+
+            ERR_PPR_DELID:          "{0}: Errore durante la delete, l'id non e' nella forma di un markup xml",
+            ERR_PPR_UNKNOWNCID:     "{0}:   Html-Component-ID: {1} sconosciuto",
+            ERR_NO_VIEWROOTATTR:    "{0}: La modifica degli attributi del ViewRoot non � supportata",
+            ERR_NO_HEADATTR:        "{0}: La modifica degli attributi di Head non � supportata",
+            ERR_RED_URL:            "{0}: Redirect senza url"
+        });
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+if (_MF_CLS) {
+/**
+ * System messages kyrillic/russian version
+ *
+ * @class
+ * @name Messages_nl
+ * @extends myfaces._impl.i18n.Messages
+ * @memberOf myfaces._impl.i18n
+ */
+_MF_CLS && _MF_CLS(_PFX_I18N + "Messages_ru", myfaces._impl.i18n.Messages,
+        /** myfaces._impl.i18n.Messages_ru.prototype */
+        {
+
+            MSG_TEST:               "ТестовоеСообщение",
+
+            /*Messages*/
+            MSG_DEV_MODE:           "Это сообщение выдано, потому что 'project stage' было присоено значение 'development', и никаких" +
+                    "других error listeners зарегистрировано не было.",
+            MSG_AFFECTED_CLASS:     "Задействованный класс:",
+            MSG_AFFECTED_METHOD:    "Задействованный метод:",
+
+            MSG_ERROR_NAME:         "Имя ошибки:",
+            MSG_ERROR_MESSAGE:      "Имя ошибки:",
+
+            MSG_ERROR_DESC:         "Описание ошибки:",
+            MSG_ERROR_NO:           "Номер ошибки:",
+            MSG_ERROR_LINENO:       "Номер строки ошибки:",
+
+            /*Errors and messages*/
+            ERR_FORM:               "Sourceform не найдена, потому что элемент не находится внутри <form>, либо были найдены элементы <form> с рдинаковым именем или идентификатором. Обработка ajax остановлена",
+            ERR_VIEWSTATE:          "jsf.viewState: Параметру присвоено значение, не являющееся элементом <form>!",
+            ERR_TRANSPORT:          "Несуществующий тип транспорта {0}",
+            ERR_EVT_PASS:           "Параметр event необходим, и не может быть null или undefined",
+            ERR_CONSTRUCT:          "Часть ответа не удалось прочитать при создании данных события: {0} ",
+            ERR_MALFORMEDXML:       "Ответ сервера не может быть обработан, он не в формате xml !",
+            ERR_SOURCE_FUNC:        "source не может быть функцией (возможно, для source и event не были даны значения",
+            ERR_EV_OR_UNKNOWN:      "Объект event или unknown должен быть всторым параметром",
+            ERR_SOURCE_NOSTR:       "source не может быть типа string",
+            ERR_SOURCE_DEF_NULL:    "source должно быть присвоено значение или null",
+
+            //_Lang.js
+            ERR_MUST_STRING:        "{0}: {1} namespace должно быть типа String",
+            ERR_REF_OR_ID:          "{0}: {1} a Ссылочный узел (reference node) или идентификатор необходимы",
+            ERR_PARAM_GENERIC:      "{0}: параметр {1} должен быть типа {2}",
+            ERR_PARAM_STR:          "{0}: {1} параметр должен быть типа string",
+            ERR_PARAM_STR_RE:       "{0}: {1} параметр должен быть типа string string или regular expression",
+            ERR_PARAM_MIXMAPS:      "{0}: source b destination map необходимы",
+            ERR_MUST_BE_PROVIDED:   "{0}: {1} и {2} необходимы",
+            ERR_MUST_BE_PROVIDED1:  "{0}: {1} должно быть присвоено значение",
+
+            ERR_REPLACE_EL:         "replaceElements вызвана, с evalNodes, не являющимся массивом",
+            ERR_EMPTY_RESPONSE:     "{0}: Ответ не может бвть null или пустым!",
+            ERR_ITEM_ID_NOTFOUND:   "{0}: Элемент с идентификатором {1} не найден",
+            ERR_PPR_IDREQ:          "{0}: Ошибка в PPR Insert, id необходим",
+            ERR_PPR_INSERTBEFID:    "{0}: Ошибка в PPR Insert, before id или after id необходимы",
+            ERR_PPR_INSERTBEFID_1:  "{0}: Ошибка в PPR Insert, before node c id {1} не найден в документе",
+            ERR_PPR_INSERTBEFID_2:  "{0}: Ошибка в PPR Insert, after node с id {1} не найден в документе",
+
+            ERR_PPR_DELID:          "{0}: Ошибка в удалении, id не найден в xml документе",
+            ERR_PPR_UNKNOWNCID:     "{0}: Неопознанный Html-Component-ID: {1}",
+            ERR_NO_VIEWROOTATTR:    "{0}: Изменение атрибутов ViewRoot не предусмотрено",
+            ERR_NO_HEADATTR:        "{0}: Изменение атрибутов Head не предусмотрено",
+            ERR_RED_URL:            "{0}: Перенаправление (Redirect) без url"
+
+        });
+}
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+if (_MF_CLS) {
+    /**
+     * System messages Simplified Chinese version
+     *
+     * @class
+     * @name Messages_zh_CN
+     * @extends myfaces._impl.i18n.Messages
+     * @memberOf myfaces._impl.i18n
+     */
+_MF_CLS && _MF_CLS(_PFX_I18N+"Messages_zh_CN", myfaces._impl.i18n.Messages,
+    /** @lends myfaces._impl.i18n.Messages_zh_CN.prototype */
+    {
+
+        MSG_TEST:               "测试信息",
+
+        /*Messages*/
+        /** @constant */
+        MSG_DEV_MODE:           "请注意,此信息只在项目发展阶段,及没有注册错误监听器而发放。",
+        /** @constant */
+        MSG_AFFECTED_CLASS:     "受影响类别:",
+        /** @constant */
+        MSG_AFFECTED_METHOD:    "受影响方法:",
+        /** @constant */
+        MSG_ERROR_NAME:         "错误名称:",
+        /** @constant */
+        MSG_ERROR_MESSAGE:      "错误信息:",
+        /** @constant */
+        MSG_SERVER_ERROR_NAME:  "伺服器错误名称:",
+        /** @constant */
+        MSG_ERROR_DESC:         "错误说明:",
+        /** @constant */
+        MSG_ERROR_NO:           "错误号码:",
+        /** @constant */
+        MSG_ERROR_LINENO:       "错误行号:",
+
+        /*Errors and messages*/
+        /** @constant */
+        ERR_FORM:               "不能判定源表单,要么没有连接元件到表单,要么有多个相同标识符或名称的表单,AJAX处理停止运作",
+        /** @constant */
+        ERR_VIEWSTATE:          "jsf.viewState:参数值不是表单类型!",
+        /** @constant */
+        ERR_TRANSPORT:          "不存在{0}传输类型",
+        /** @constant */
+        ERR_EVT_PASS:           "必须放弃事件(可能事件物件为空或未定义)",
+        /** @constant */
+        ERR_CONSTRUCT:          "构建事件数据时部分回应不能取得,原因是:{0}",
+        /** @constant */
+        ERR_MALFORMEDXML:       "无法解析伺服器的回应,伺服器返回的回应不是XML!",
+        /** @constant */
+        ERR_SOURCE_FUNC:        "来源不能是一个函数(可能来源和事件没有定义或设定为空)",
+        /** @constant */
+        ERR_EV_OR_UNKNOWN:      "事件物件或不明必须作为第二个参数传递",
+        /** @constant */
+        ERR_SOURCE_NOSTR:       "来源不能是字串",
+        /** @constant */
+        ERR_SOURCE_DEF_NULL:    "来源必须定义或为空",
+
+        //_Lang.js
+        /** @constant */
+        ERR_MUST_STRING:        "{0}:{1} 名称空间必须是字串类型",
+        /** @constant */
+        ERR_REF_OR_ID:          "{0}:{1} 必须提供参考节点或标识符",
+        /** @constant */
+        ERR_PARAM_GENERIC:      "{0}:{1} 参数必须是 {2} 类型",
+        /** @constant */
+        ERR_PARAM_STR:          "{0}:{1} 参数必须是字串类型",
+        /** @constant */
+        ERR_PARAM_STR_RE:       "{0}:{1} 参数必须是字串类型或正规表达式",
+        /** @constant */
+        ERR_PARAM_MIXMAPS:      "{0}:必须提供来源及目标映射",
+        /** @constant */
+        ERR_MUST_BE_PROVIDED:   "{0}:必须提供 {1} 及 {2}",
+        /** @constant */
+        ERR_MUST_BE_PROVIDED1:  "{0}:必须设定 {1}",
+
+        /** @constant */
+        ERR_REPLACE_EL:         "调用replaceElements函数时evalNodes变量不是阵列类型",
+
+        /** @constant */
+        ERR_EMPTY_RESPONSE:     "{0}:回应不能为空的!",
+        /** @constant */
+        ERR_ITEM_ID_NOTFOUND:   "{0}:找不到有 {1} 标识符的项目",
+        /** @constant */
+        ERR_PPR_IDREQ:          "{0}:局部页面渲染嵌入错误,标识符必须存在",
+        /** @constant */
+        ERR_PPR_INSERTBEFID:    "{0}:局部页面渲染嵌入错误,前或后标识符必须存在",
+        /** @constant */
+        ERR_PPR_INSERTBEFID_1:  "{0}:局部页面渲染嵌入错误,前节点的标识符 {1} 不在文件内",
+        /** @constant */
+        ERR_PPR_INSERTBEFID_2:  "{0}:局部页面渲染嵌入错误,后节点的标识符 {1} 不在文件内",
+
+        /** @constant */
+        ERR_PPR_DELID:          "{0}:删除错误,标识符不在XML标记中",
+        /** @constant */
+        ERR_PPR_UNKNOWNCID:     "{0}:不明的HTML组件标识符:{1}",
+
+        /** @constant */
+        ERR_NO_VIEWROOTATTR:    "{0}:不支援改变ViewRoot属性",
+        /** @constant */
+        ERR_NO_HEADATTR:        "{0}:不支援改变Head的属性",
+        /** @constant */
+        ERR_RED_URL:            "{0}:没有重导向网址",
+
+        /** @constant */
+        ERR_REQ_FAILED_UNKNOWN: "请求失败,状态不明",
+
+        /** @constant */
+        ERR_REQU_FAILED: "请求失败,状态是 {0} 和原因是 {1}",
+
+        /** @constant */
+        UNKNOWN: "不明"
+    });
+}
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * System messages Traditional Chinese (Hong Kong) version
+ *
+ * @class
+ * @name Messages_zh_HK
+ * @extends myfaces._impl.i18n.Messages
+ * @memberOf myfaces._impl.i18n
+ */
+_MF_CLS && _MF_CLS(_PFX_I18N + "Messages_zh_HK", myfaces._impl.i18n.Messages,
+        /** @lends myfaces._impl.i18n.Messages_zh_HK.prototype */
+        {
+
+            MSG_TEST:               "測試信息",
+
+            /*Messages*/
+            /** @constant */
+            MSG_DEV_MODE:           "請注意,此信息只在項目發展階段,及沒有註冊錯誤監聽器而發放。",
+            /** @constant */
+            MSG_AFFECTED_CLASS:     "受影響類別:",
+            /** @constant */
+            MSG_AFFECTED_METHOD:    "受影響方法:",
+            /** @constant */
+            MSG_ERROR_NAME:         "錯誤名稱:",
+            /** @constant */
+            MSG_ERROR_MESSAGE:      "錯誤信息:",
+            /** @constant */
+            MSG_SERVER_ERROR_NAME:  "伺服器錯誤名稱:",
+            /** @constant */
+            MSG_ERROR_DESC:         "錯誤說明:",
+            /** @constant */
+            MSG_ERROR_NO:           "錯誤號碼:",
+            /** @constant */
+            MSG_ERROR_LINENO:       "錯誤行號:",
+
+            /*Errors and messages*/
+            /** @constant */
+            ERR_FORM:               "不能判定源表單,要麼沒有連接元件到表單,要麼有多個相同標識符或名稱的表單,AJAX處理停止運作",
+            /** @constant */
+            ERR_VIEWSTATE:          "jsf.viewState:參數值不是表單類型!",
+            /** @constant */
+            ERR_TRANSPORT:          "不存在{0}傳輸類型",
+            /** @constant */
+            ERR_EVT_PASS:           "必須放棄事件(可能事件物件為空或未定義)",
+            /** @constant */
+            ERR_CONSTRUCT:          "構建事件數據時部分回應不能取得,原因是:{0}",
+            /** @constant */
+            ERR_MALFORMEDXML:       "無法解析伺服器的回應,伺服器返回的回應不是XML!",
+            /** @constant */
+            ERR_SOURCE_FUNC:        "來源不能是一個函數(可能來源和事件沒有定義或設定為空)",
+            /** @constant */
+            ERR_EV_OR_UNKNOWN:      "事件物件或不明必須作為第二個參數傳遞",
+            /** @constant */
+            ERR_SOURCE_NOSTR:       "來源不能是字串",
+            /** @constant */
+            ERR_SOURCE_DEF_NULL:    "來源必須定義或為空",
+
+            //_Lang.js
+            /** @constant */
+            ERR_MUST_STRING:        "{0}:{1} 名稱空間必須是字串類型",
+            /** @constant */
+            ERR_REF_OR_ID:          "{0}:{1} 必須提供參考節點或標識符",
+            /** @constant */
+            ERR_PARAM_GENERIC:      "{0}:{1} 參數必須是 {2} 類型",
+            /** @constant */
+            ERR_PARAM_STR:          "{0}:{1} 參數必須是字串類型",
+            /** @constant */
+            ERR_PARAM_STR_RE:       "{0}:{1} 參數必須是字串類型或正規表達式",
+            /** @constant */
+            ERR_PARAM_MIXMAPS:      "{0}:必須提供來源及目標映射",
+            /** @constant */
+            ERR_MUST_BE_PROVIDED:   "{0}:必須提供 {1} 及 {2}",
+            /** @constant */
+            ERR_MUST_BE_PROVIDED1:  "{0}:必須設定 {1}",
+
+            /** @constant */
+            ERR_REPLACE_EL:         "調用replaceElements函數時evalNodes變量不是陣列類型",
+
+            /** @constant */
+            ERR_EMPTY_RESPONSE:     "{0}:回應不能為空的!",
+            /** @constant */
+            ERR_ITEM_ID_NOTFOUND:   "{0}:找不到有 {1} 標識符的項目",
+            /** @constant */
+            ERR_PPR_IDREQ:          "{0}:局部頁面渲染嵌入錯誤,標識符必須存在",
+            /** @constant */
+            ERR_PPR_INSERTBEFID:    "{0}:局部頁面渲染嵌入錯誤,前或後標識符必須存在",
+            /** @constant */
+            ERR_PPR_INSERTBEFID_1:  "{0}:局部頁面渲染嵌入錯誤,前節點的標識符 {1} 不在文件內",
+            /** @constant */
+            ERR_PPR_INSERTBEFID_2:  "{0}:局部頁面渲染嵌入錯誤,後節點的標識符 {1} 不在文件內",
+
+            /** @constant */
+            ERR_PPR_DELID:          "{0}:刪除錯誤,標識符不在XML標記中",
+            /** @constant */
+            ERR_PPR_UNKNOWNCID:     "{0}:不明的HTML組件標識符:{1}",
+
+            /** @constant */
+            ERR_NO_VIEWROOTATTR:    "{0}:不支援改變ViewRoot屬性",
+            /** @constant */
+            ERR_NO_HEADATTR:        "{0}:不支援改變Head的屬性",
+            /** @constant */
+            ERR_RED_URL:            "{0}:沒有重導向網址",
+
+            /** @constant */
+            ERR_REQ_FAILED_UNKNOWN: "請求失敗,狀態不明",
+
+            /** @constant */
+            ERR_REQU_FAILED: "請求失敗,狀態是 {0} 和原因是 {1}",
+
+            /** @constant */
+            UNKNOWN: "不明"
+        });
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+if (_MF_CLS) {
+    /**
+     * System messages Traditional Chinese (Taiwan) version
+     *
+     * @class
+     * @name Messages_zh_TW
+     * @extends myfaces._impl.i18n.Messages
+     * @memberOf myfaces._impl.i18n
+     */
+_MF_CLS &&  _MF_CLS(_PFX_I18N + "Messages_zh_TW", myfaces._impl.i18n.Messages,
+            /** @lends myfaces._impl.i18n.Messages_zh_TW.prototype */
+            {
+
+                MSG_TEST:               "測試信息",
+
+                /*Messages*/
+                /** @constant */
+                MSG_DEV_MODE:           "請注意,此信息只在項目發展階段,及沒有註冊錯誤監聽器而發放。",
+                /** @constant */
+                MSG_AFFECTED_CLASS:     "受影響類別:",
+                /** @constant */
+                MSG_AFFECTED_METHOD:    "受影響方法:",
+                /** @constant */
+                MSG_ERROR_NAME:         "錯誤名稱:",
+                /** @constant */
+                MSG_ERROR_MESSAGE:      "錯誤信息:",
+                /** @constant */
+                MSG_SERVER_ERROR_NAME:  "伺服器錯誤名稱:",
+                /** @constant */
+                MSG_ERROR_DESC:         "錯誤說明:",
+                /** @constant */
+                MSG_ERROR_NO:           "錯誤號碼:",
+                /** @constant */
+                MSG_ERROR_LINENO:       "錯誤行號:",
+
+                /*Errors and messages*/
+                /** @constant */
+                ERR_FORM:               "不能判定源表單,要麼沒有連接元件到表單,要麼有多個相同標識符或名稱的表單,AJAX處理停止運作",
+                /** @constant */
+                ERR_VIEWSTATE:          "jsf.viewState:參數值不是表單類型!",
+                /** @constant */
+                ERR_TRANSPORT:          "不存在{0}傳輸類型",
+                /** @constant */
+                ERR_EVT_PASS:           "必須放棄事件(可能事件物件為空或未定義)",
+                /** @constant */
+                ERR_CONSTRUCT:          "構建事件數據時部分回應不能取得,原因是:{0}",
+                /** @constant */
+                ERR_MALFORMEDXML:       "無法解析伺服器的回應,伺服器返回的回應不是XML!",
+                /** @constant */
+                ERR_SOURCE_FUNC:        "來源不能是一個函數(可能來源和事件沒有定義或設定為空)",
+                /** @constant */
+                ERR_EV_OR_UNKNOWN:      "事件物件或不明必須作為第二個參數傳遞",
+                /** @constant */
+                ERR_SOURCE_NOSTR:       "來源不能是字串",
+                /** @constant */
+                ERR_SOURCE_DEF_NULL:    "來源必須定義或為空",
+
+                //_Lang.js
+                /** @constant */
+                ERR_MUST_STRING:        "{0}:{1} 名稱空間必須是字串類型",
+                /** @constant */
+                ERR_REF_OR_ID:          "{0}:{1} 必須提供參考節點或標識符",
+                /** @constant */
+                ERR_PARAM_GENERIC:      "{0}:{1} 參數必須是 {2} 類型",
+                /** @constant */
+                ERR_PARAM_STR:          "{0}:{1} 參數必須是字串類型",
+                /** @constant */
+                ERR_PARAM_STR_RE:       "{0}:{1} 參數必須是字串類型或正規表達式",
+                /** @constant */
+                ERR_PARAM_MIXMAPS:      "{0}:必須提供來源及目標映射",
+                /** @constant */
+                ERR_MUST_BE_PROVIDED:   "{0}:必須提供 {1} 及 {2}",
+                /** @constant */
+                ERR_MUST_BE_PROVIDED1:  "{0}:必須設定 {1}",
+
+                /** @constant */
+                ERR_REPLACE_EL:         "調用replaceElements函數時evalNodes變量不是陣列類型",
+
+                /** @constant */
+                ERR_EMPTY_RESPONSE:     "{0}:回應不能為空的!",
+                /** @constant */
+                ERR_ITEM_ID_NOTFOUND:   "{0}:找不到有 {1} 標識符的項目",
+                /** @constant */
+                ERR_PPR_IDREQ:          "{0}:局部頁面渲染嵌入錯誤,標識符必須存在",
+                /** @constant */
+                ERR_PPR_INSERTBEFID:    "{0}:局部頁面渲染嵌入錯誤,前或後標識符必須存在",
+                /** @constant */
+                ERR_PPR_INSERTBEFID_1:  "{0}:局部頁面渲染嵌入錯誤,前節點的標識符 {1} 不在文件內",
+                /** @constant */
+                ERR_PPR_INSERTBEFID_2:  "{0}:局部頁面渲染嵌入錯誤,後節點的標識符 {1} 不在文件內",
+
+                /** @constant */
+                ERR_PPR_DELID:          "{0}:刪除錯誤,標識符不在XML標記中",
+                /** @constant */
+                ERR_PPR_UNKNOWNCID:     "{0}:不明的HTML組件標識符:{1}",
+
+                /** @constant */
+                ERR_NO_VIEWROOTATTR:    "{0}:不支援改變ViewRoot屬性",
+                /** @constant */
+                ERR_NO_HEADATTR:        "{0}:不支援改變Head的屬性",
+                /** @constant */
+                ERR_RED_URL:            "{0}:沒有重導向網址",
+
+                /** @constant */
+                ERR_REQ_FAILED_UNKNOWN: "請求失敗,狀態不明",
+
+                /** @constant */
+                ERR_REQU_FAILED: "請求失敗,狀態是 {0} 和原因是 {1}",
+
+                /** @constant */
+                UNKNOWN: "不明"
+            });
+}
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ theoretically we could save some code
+ by
+ defining the parent object as
+ var parent = new Object();
+ parent.prototype = new myfaces._impl.core._Runtime();
+ extendClass(function () {
+ }, parent , {
+ But for now we are not doing it the little bit of saved
+ space is not worth the loss of readability
+ */
+/**
+ * @memberOf myfaces._impl
+ * @namespace
+ * @name _util
+ */
+/**
+ * @class
+ * @name _Lang
+ * @memberOf myfaces._impl._util
+ * @extends myfaces._impl.core._Runtime
+ * @namespace
+ * @description Object singleton for Language related methods, this object singleton
+ * decorates the namespace myfaces._impl.core._Runtime and adds a bunch of new methods to
+ * what _Runtime provided
+ * */
+_MF_SINGLTN(_PFX_UTIL + "_Lang", Object, /** @lends myfaces._impl._util._Lang.prototype */ {
+    _processedExceptions:{},
+    _installedLocale:null,
+    _RT:myfaces._impl.core._Runtime,
+    /**
+     * returns a given localized message upon a given key
+     * basic java log like templating functionality is included
+     *
+     * @param {String} key the key for the message
+     * @param {String} defaultMessage optional default message if none was found
+     *
+     * Additionally you can pass additional arguments, which are used
+     * in the same way java log templates use the params
+     *
+     * @param key
+     */
+    getMessage:function (key, defaultMessage /*,vararg templateParams*/) {
+        if (!this._installedLocale) {
+            //we first try to install language and variant, if that one fails
+            //we try to install the language only, and if that one fails
+            //we install the base messages
+            this.initLocale();
+        }
+        var msg = this._installedLocale[key] || defaultMessage || key + " - undefined message";
+        //we now make a simple templating replace of {0}, {1} etc... with their corresponding
+        //arguments
+        for (var cnt = 2; cnt < arguments.length; cnt++) {
+            msg = msg.replace(new RegExp(["\\{", cnt - 2, "\\}"].join(""), "g"), new String(arguments[cnt]));
+        }
+        return msg;
+    },
+    /**
+     * (re)inits the currently installed
+     * messages so that after loading the main scripts
+     * a new locale can be installed optionally
+     * to our i18n subsystem
+     *
+     * @param newLocale locale override
+     */
+    initLocale:function (newLocale) {
+        if (newLocale) {
+            this._installedLocale = new newLocale();
+            return;
+        }
+        var language_Variant = this._RT.getLanguage(this._RT.getGlobalConfig("locale")),
+                langStr = language_Variant ? language_Variant.language : "",
+                variantStr = language_Variant ? [language_Variant.language, "_", language_Variant.variant || ""].join("") : "",
+                i18nRoot = myfaces._impl.i18n, i18nHolder = i18nRoot["Messages_" + variantStr] || i18nRoot["Messages_" + langStr] || i18nRoot["Messages"];
+        this._installedLocale = new i18nHolder();
+    },
+    assertType:function (probe, theType) {
+        return this._RT.assertType(probe, theType);
+    },
+    exists:function (nms, theType) {
+        return this._RT.exists(nms, theType);
+    },
+    fetchNamespace:function (namespace) {
+        this._assertStr(namespace, "fetchNamespace", "namespace");
+        return this._RT.fetchNamespace(namespace);
+    },
+    reserveNamespace:function (namespace) {
+        this._assertStr(namespace, "reserveNamespace", "namespace");
+        return this._RT.reserveNamespace(namespace);
+    },
+    globalEval:function (code) {
+        this._assertStr(code, "globalEval", "code");
+        return  this._RT.globalEval(code);
+    },
+    /**
+     * determines the correct event depending
+     * on the browsers state
+     *
+     * @param evt incoming event object (note not all browsers
+     * have this)
+     *
+     * @return an event object no matter what is incoming
+     */
+    getEvent:function (evt) {
+        evt = (!evt) ? window.event || {} : evt;
+        return evt;
+    },
+    /**
+     * cross port from the dojo lib
+     * browser save event resolution
+     * @param evt the event object
+     * (with a fallback for ie events if none is present)
+     */
+    getEventTarget:function (evt) {
+        //ie6 and 7 fallback
+        evt = this.getEvent(evt);
+        /**
+         * evt source is defined in the jsf events
+         * seems like some component authors use our code
+         * so we add it here see also
+         * https://issues.apache.org/jira/browse/MYFACES-2458
+         * not entirely a bug but makes sense to add this
+         * behavior. I dont use it that way but nevertheless it
+         * does not break anything so why not
+         * */
+        var t = evt.srcElement || evt.target || evt.source || null;
+        while ((t) && (t.nodeType != 1)) {
+            t = t.parentNode;
+        }
+        return t;
+    },
+
+    /**
+     * equalsIgnoreCase, case insensitive comparison of two strings
+     *
+     * @param source
+     * @param destination
+     */
+    equalsIgnoreCase:function (source, destination) {
+        //either both are not set or null
+        if (!source && !destination) {
+            return true;
+        }
+        //source or dest is set while the other is not
+        if (!source || !destination) return false;
+        //in any other case we do a strong string comparison
+        return source.toLowerCase() === destination.toLowerCase();
+    },
+
+    /**
+     * Save document.getElementById (this code was ported over from dojo)
+     * the idea is that either a string or domNode can be passed
+     * @param {Object} reference the reference which has to be byIded
+     */
+    byId:function (/*object*/ reference) {
+        if (!reference) {
+            throw this.makeException(new Error(), null, null, this._nameSpace, "byId", this.getMessage("ERR_REF_OR_ID", null, "_Lang.byId", "reference"));
+        }
+        return (this.isString(reference)) ? document.getElementById(reference) : reference;
+    },
+
+    /**
+     * String to array function performs a string to array transformation
+     * @param {String} it the string which has to be changed into an array
+     * @param {RegExp} splitter our splitter reglar expression
+     * @return an array of the splitted string
+     */
+    strToArray:function (/*string*/ it, /*regexp*/ splitter) {
+        //	summary:
+        //		Return true if it is a String
+        this._assertStr(it, "strToArray", "it");
+        if (!splitter) {
+            throw this.makeException(new Error(), null, null, this._nameSpace, "strToArray", this.getMessage("ERR_PARAM_STR_RE", null, "myfaces._impl._util._Lang.strToArray", "splitter"));
+        }
+        var retArr = it.split(splitter);
+        var len = retArr.length;
+        for (var cnt = 0; cnt < len; cnt++) {
+            retArr[cnt] = this.trim(retArr[cnt]);
+        }
+        return retArr;
+    },
+    _assertStr:function (it, functionName, paramName) {
+        if (!this.isString(it)) {
+            throw this.makeException(new Error(), null, null, this._nameSpace, arguments.caller.toString(), this.getMessage("ERR_PARAM_STR", null, "myfaces._impl._util._Lang." + functionName, paramName));
+        }
+    },
+    /**
+     * hyperfast trim
+     * http://blog.stevenlevithan.com/archives/faster-trim-javascript
+     * crossported from dojo
+     */
+    trim:function (/*string*/ str) {
+        this._assertStr(str, "trim", "str");
+        str = str.replace(/^\s\s*/, '');
+        var ws = /\s/, i = str.length;
+
+        while (ws.test(str.charAt(--i))) {
+            //do nothing
+        }
+        return str.slice(0, i + 1);
+    },
+    /**
+     * Backported from dojo
+     * a failsafe string determination method
+     * (since in javascript String != "" typeof alone fails!)
+     * @param it {|Object|} the object to be checked for being a string
+     * @return true in case of being a string false otherwise
+     */
+    isString:function (/*anything*/ it) {
+        //	summary:
+        //		Return true if it is a String
+        return !!arguments.length && it != null && (typeof it == "string" || it instanceof String); // Boolean
+    },
+    /**
+     * hitch backported from dojo
+     * hitch allows to assign a function to a dedicated scope
+     * this is helpful in situations when function reassignments
+     * can happen
+     * (notably happens often in lazy xhr code)
+     *
+     * @param {Function} scope of the function to be executed in
+     * @param {Function} method to be executed, the method must be of type function
+     *
+     * @return whatever the executed method returns
+     */
+    hitch:function (scope, method) {
+        return !scope ? method : function () {
+            return method.apply(scope, arguments || []);
+        }; // Function
+    },
+    /**
+     * Helper function to merge two maps
+     * into one
+     * @param {Object} dest the destination map
+     * @param {Object} src the source map
+     * @param {boolean} overwrite if set to true the destination is overwritten if the keys exist in both maps
+     **/
+    mixMaps:function (dest, src, overwrite, blockFilter, whitelistFilter) {
+        if (!dest || !src) {
+            throw this.makeException(new Error(), null, null, this._nameSpace, "mixMaps", this.getMessage("ERR_PARAM_MIXMAPS", null, "_Lang.mixMaps"));
+        }
+        var _undef = "undefined";
+        for (var key in src) {
+            if (!src.hasOwnProperty(key)) continue;
+            if (blockFilter && blockFilter[key]) {
+                continue;
+            }
+            if (whitelistFilter && !whitelistFilter[key]) {
+                continue;
+            }
+            if (!overwrite) {
+                /**
+                 *we use exists instead of booleans because we cannot rely
+                 *on all values being non boolean, we would need an elvis
+                 *operator in javascript to shorten this :-(
+                 */
+                dest[key] = (_undef != typeof dest[key]) ? dest[key] : src[key];
+            } else {
+                dest[key] = (_undef != typeof src[key]) ? src[key] : dest[key];
+            }
+        }
+        return dest;
+    },
+    /**
+     * checks if an array contains an element
+     * @param {Array} arr   array
+     * @param {String} str string to check for
+     */
+    contains:function (arr, str) {
+        if (!arr || !str) {
+            throw this.makeException(new Error(), null, null, this._nameSpace, "contains", this.getMessage("ERR_MUST_BE_PROVIDED", null, "_Lang.contains", "arr {array}", "str {string}"));
+        }
+        return this.arrIndexOf(arr, str) != -1;
+    },
+    arrToMap:function (arr, offset) {
+        var ret = new Array(arr.length);
+        var len = arr.length;
+        offset = (offset) ? offset : 0;
+        for (var cnt = 0; cnt < len; cnt++) {
+            ret[arr[cnt]] = cnt + offset;
+        }
+        return ret;
+    },
+    objToArray:function (obj, offset, pack) {
+        if (!obj) {
+            return null;
+        }
+        //since offset is numeric we cannot use the shortcut due to 0 being false
+        //special condition array delivered no offset no pack
+        if (obj instanceof Array && !offset && !pack)  return obj;
+        var finalOffset = ('undefined' != typeof offset || null != offset) ? offset : 0;
+        var finalPack = pack || [];
+        try {
+            return finalPack.concat(Array.prototype.slice.call(obj, finalOffset));
+        } catch (e) {
+            //ie8 (again as only browser) delivers for css 3 selectors a non convertible object
+            //we have to do it the hard way
+            //ie8 seems generally a little bit strange in its behavior some
+            //objects break the function is everything methodology of javascript
+            //and do not implement apply call, or are pseudo arrays which cannot
+            //be sliced
+            for (var cnt = finalOffset; cnt < obj.length; cnt++) {
+                finalPack.push(obj[cnt]);
+            }
+            return finalPack;
+        }
+    },
+    /**
+     * foreach implementation utilizing the
+     * ECMAScript wherever possible
+     * with added functionality
+     *
+     * @param arr the array to filter
+     * @param func the closure to apply the function to, with the syntax defined by the ecmascript functionality
+     * function (element<,key, array>)
+     * <p />
+     * optional params
+     * <p />
+     * <ul>
+     *      <li>param startPos (optional) the starting position </li>
+     *      <li>param scope (optional) the scope to apply the closure to  </li>
+     * </ul>
+     */
+    arrForEach:function (arr, func /*startPos, scope*/) {
+        if (!arr || !arr.length) return;
+        var startPos = Number(arguments[2]) || 0;
+        var thisObj = arguments[3];
+        //check for an existing foreach mapping on array prototypes
+        //IE9 still does not pass array objects as result for dom ops
+        arr = this.objToArray(arr);
+        (startPos) ? arr.slice(startPos).forEach(func, thisObj) : arr.forEach(func, thisObj);
+    },
+    /**
+     * foreach implementation utilizing the
+     * ECMAScript wherever possible
+     * with added functionality
+     *
+     * @param arr the array to filter
+     * @param func the closure to apply the function to, with the syntax defined by the ecmascript functionality
+     * function (element<,key, array>)
+     * <p />
+     * additional params
+     * <ul>
+     *  <li> startPos (optional) the starting position</li>
+     *  <li> scope (optional) the scope to apply the closure to</li>
+     * </ul>
+     */
+    arrFilter:function (arr, func /*startPos, scope*/) {
+        if (!arr || !arr.length) return [];
+        arr = this.objToArray(arr);
+        return ((startPos) ? arr.slice(startPos).filter(func, thisObj) : arr.filter(func, thisObj));
+    },
+    /**
+     * adds a EcmaScript optimized indexOf to our mix,
+     * checks for the presence of an indexOf functionality
+     * and applies it, otherwise uses a fallback to the hold
+     * loop method to determine the index
+     *
+     * @param arr the array
+     * @param element the index to search for
+     */
+    arrIndexOf:function (arr, element /*fromIndex*/) {
+        if (!arr || !arr.length) return -1;
+        var pos = Number(arguments[2]) || 0;
+        arr = this.objToArray(arr);
+        return arr.indexOf(element, pos);
+    },
+    /**
+     * helper to automatically apply a delivered arguments map or array
+     * to its destination which has a field "_"<key> and a full field
+     *
+     * @param dest the destination object
+     * @param args the arguments array or map
+     * @param argNames the argument names to be transferred
+     */
+    applyArgs:function (dest, args, argNames) {
+        var UDEF = 'undefined';
+        if (argNames) {
+            for (var cnt = 0; cnt < args.length; cnt++) {
+                //dest can be null or 0 hence no shortcut
+                if (UDEF != typeof dest["_" + argNames[cnt]]) {
+                    dest["_" + argNames[cnt]] = args[cnt];
+                }
+                if (UDEF != typeof dest[ argNames[cnt]]) {
+                    dest[argNames[cnt]] = args[cnt];
+                }
+            }
+        } else {
+            for (var key in args) {
+                if (!args.hasOwnProperty(key)) continue;
+                if (UDEF != typeof dest["_" + key]) {
+                    dest["_" + key] = args[key];
+                }
+                if (UDEF != typeof dest[key]) {
+                    dest[key] = args[key];
+                }
+            }
+        }
+    },
+
+    /**
+     * transforms a key value pair into a string
+     * @param key the key
+     * @param val the value
+     * @param delimiter the delimiter
+     */
+    keyValToStr:function (key, val, delimiter) {
+        var ret = [], pushRet = this.hitch(ret, ret.push);
+        pushRet(key);
+        pushRet(val);
+        delimiter = delimiter || "\n";
+        pushRet(delimiter);
+        return ret.join("");
+    },
+    parseXML:function (txt) {
+        try {
+            var parser = new DOMParser();
+            return parser.parseFromString(txt, "text/xml");
+        } catch (e) {
+            //undefined internal parser error
+            return null;
+        }
+    },
+    serializeXML:function (xmlNode, escape) {
+        if (!escape) {
+            if (xmlNode.data) return xmlNode.data; //CDATA block has raw data
+            if (xmlNode.textContent) return xmlNode.textContent; //textNode has textContent
+        }
+        return (new XMLSerializer()).serializeToString(xmlNode);
+    },
+    serializeChilds:function (xmlNode) {
+        var buffer = [];
+        if (!xmlNode.childNodes) return "";
+        for (var cnt = 0; cnt < xmlNode.childNodes.length; cnt++) {
+            buffer.push(this.serializeXML(xmlNode.childNodes[cnt]));
+        }
+        return buffer.join("");
+    },
+    isXMLParseError:function (xmlContent) {
+        //no xml content
+        if (xmlContent == null) return true;
+        var findParseError = function (node) {
+            if (!node || !node.childNodes) return false;
+            for (var cnt = 0; cnt < node.childNodes.length; cnt++) {
+                var childNode = node.childNodes[cnt];
+                if (childNode.tagName && childNode.tagName == "parsererror") return true;
+            }
+            return false;
+        };
+        return !xmlContent ||
+                (this.exists(xmlContent, "parseError.errorCode") && xmlContent.parseError.errorCode != 0) ||
+                findParseError(xmlContent);
+    },
+    /**
+     * fetches the error message from the xml content
+     * in a browser independent way
+     *
+     * @param xmlContent
+     * @return a map with the following structure {errorMessage: the error Message, sourceText: the text with the error}
+     */
+    fetchXMLErrorMessage:function (text, xmlContent) {
+        var _t = this;
+        var findParseError = function (node) {
+            if (!node || !node.childNodes) return false;
+            for (var cnt = 0; cnt < node.childNodes.length; cnt++) {
+                var childNode = node.childNodes[cnt];
+                if (childNode.tagName && childNode.tagName == "parsererror") {
+                    var errorMessage = _t.serializeXML(childNode.childNodes[0]);
+                    //we now have to determine the row and column position
+                    var lastLine = errorMessage.split("\n");
+                    lastLine = lastLine[lastLine.length-1];
+                    var positions = lastLine.match(/[^0-9]*([0-9]+)[^0-9]*([0-9]+)[^0-9]*/);
+
+                    var ret = {
+                        errorMessage: errorMessage,
+                        sourceText: _t.serializeXML(childNode.childNodes[1].childNodes[0])
+                    }
+                    if(positions) {
+                        ret.line = Math.max(0, parseInt(positions[1])-1);
+                        ret.linePos = Math.max(0, parseInt(positions[2])-1);
+                    }
+                    return ret;
+                }
+            }
+            return null;
+        };
+        var ret = null;
+        if (!xmlContent) {
+            //chrome does not deliver any further data
+            ret =  (this.trim(text || "").length > 0)? {errorMessage:"Illegal response",sourceText:""} : {errorMessage:"Empty Response",sourceText:""};
+        } else if (this.exists(xmlContent, "parseError.errorCode") && xmlContent.parseError.errorCode != 0) {
+            ret =   {
+                errorMessage:xmlContent.parseError.reason,
+                line:Math.max(0, parseInt(xmlContent.parseError.line)-1),
+                linePos:Math.max(0,parseInt(xmlContent.parseError.linepos) -1),
+                sourceText:xmlContent.parseError.srcText
+            };
+        } else {
+            ret = findParseError(xmlContent);
+        }
+        //we have a line number we now can format the source accordingly
+        if(ret && 'undefined' != typeof ret.line) {
+            var source = ret.sourceText ||"";
+            source = source.split("\n");
+            if(source.length-1 < ret.line) return ret;
+            source = source[ret.line];
+            var secondLine = [];
+            var lineLen = (ret.linePos - 2);
+            for(var cnt = 0; cnt < lineLen; cnt++) {
+                secondLine.push(" ");
+            }
+            secondLine.push("^^");
+            ret.sourceText = source;
+            ret.visualError = secondLine;
+        }
+        return ret;
+    },
+
+    /**
+     * creates a neutral form data wrapper over an existing form Data element
+     * the wrapper delegates following methods, append
+     * and adds makeFinal as finalizing method which returns the final
+     * send representation of the element
+     *
+     * @param formData an array
+     */
+    createFormDataDecorator:function (formData) {
+        //we simulate the dom level 2 form element here
+        var _newCls = null;
+        var bufInstance = null;
+        if (!this.FormDataDecoratorArray) {
+            this.FormDataDecoratorArray = function (theFormData) {
+                this._valBuf = theFormData;
+                this._idx = {};
+            };
+            _newCls = this.FormDataDecoratorArray;
+            _newCls.prototype.append = function (key, val) {
+                this._valBuf.push([encodeURIComponent(key), encodeURIComponent(val)].join("="));
+                this._idx[key] = true;
+            };
+            _newCls.prototype.hasKey = function (key) {
+                return !!this._idx[key];
+            };
+            _newCls.prototype.makeFinal = function () {
+                return this._valBuf.join("&");
+            };
+        }
+        if (!this.FormDataDecoratorString) {
+            this.FormDataDecoratorString = function (theFormData) {
+                this._preprocessedData = theFormData;
+                this._valBuf = [];
+                this._idx = {};
+            };
+            _newCls = this.FormDataDecoratorString;
+            _newCls.prototype.append = function (key, val) {
+                this._valBuf.push([encodeURIComponent(key), encodeURIComponent(val)].join("="));
+                this._idx[key] = true;
+            };
+            //for now we check only for keys which are added subsequently otherwise we do not perform any checks
+            _newCls.prototype.hasKey = function (key) {
+                return !!this._idx[key];
+            };
+            _newCls.prototype.makeFinal = function () {
+                if (this._preprocessedData != "") {
+                    return this._preprocessedData + "&" + this._valBuf.join("&")
+                } else {
+                    return this._valBuf.join("&");
+                }
+            };
+        }
+        if (!this.FormDataDecoratorOther) {
+            this.FormDataDecoratorOther = function (theFormData) {
+                this._valBuf = theFormData;
+                this._idx = {};
+            };
+            _newCls = this.FormDataDecoratorOther;
+            _newCls.prototype.append = function (key, val) {
+                this._valBuf.append(key, val);
+                this._idx[key] = true;
+            };
+            _newCls.prototype.hasKey = function (key) {
+                return !!this._idx[key];
+            };
+            _newCls.prototype.makeFinal = function () {
+                return this._valBuf;
+            };
+        }
+        if (formData instanceof Array) {
+            bufInstance = new this.FormDataDecoratorArray(formData);
+        } else if (this.isString(formData)) {
+            bufInstance = new this.FormDataDecoratorString(formData);
+        } else {
+            bufInstance = new this.FormDataDecoratorOther(formData);
+        }
+        return bufInstance;
+    },
+    /**
+     * define a property mechanism which is browser neutral
+     * we cannot use the existing setter and getter mechanisms
+     * for now because old browsers do not support them
+     * in the long run we probably can switch over
+     * or make a code split between legacy and new
+     *
+     *
+     * @param obj
+     * @param name
+     * @param value
+     */
+    attr:function (obj, name, value) {
+        var findAccessor = function (theObj, theName) {
+            return (theObj["_" + theName]) ? "_" + theName : ( (theObj[theName]) ? theName : null)
+        };
+        var applyAttr = function (theObj, theName, value, isFunc) {
+            if (value) {
+                if (isFunc) {
+                    theObj[theName](value);
+                } else {
+                    theObj[theName] = value;
+                }
+                return null;
+            }
+            return (isFunc) ? theObj[theName]() : theObj[theName];
+        };
+        try {
+            var finalAttr = findAccessor(obj, name);
+            //simple attibute no setter and getter overrides
+            if (finalAttr) {
+                return applyAttr(obj, finalAttr, value);
+            }
+            //lets check for setter and getter overrides
+            var found = false;
+            var prefix = (value) ? "set" : "get";
+            finalAttr = [prefix, name.substr(0, 1).toUpperCase(), name.substr(1)].join("");
+            finalAttr = findAccessor(obj, finalAttr);
+            if (finalAttr) {
+                return applyAttr(obj, finalAttr, value, true);
+            }
+
+            throw this.makeException(new Error(), null, null, this._nameSpace, "contains", "property " + name + " not found");
+        } finally {
+            findAccessor = null;
+            applyAttr = null;
+        }
+    },
+
+    /**
+     * creates an exeption with additional internal parameters
+     * for extra information
+     *
+     * @param {String} title the exception title
+     * @param {String} name  the exception name
+     * @param {String} callerCls the caller class
+     * @param {String} callFunc the caller function
+     * @param {String} message the message for the exception
+     */
+    makeException:function (error, title, name, callerCls, callFunc, message) {
+        error.name = name || "clientError";
+        error.title = title || "";
+        error.message = message || "";
+        error._mfInternal = {};
+        error._mfInternal.name = name || "clientError";
+        error._mfInternal.title = title || "clientError";
+        error._mfInternal.caller = callerCls || this._nameSpace;
+        error._mfInternal.callFunc = callFunc || ("" + arguments.caller.toString());
+        return error;
+    }
+});
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/*
+ theoretically we could save some code
+ by
+ defining the parent object as
+ var parent = new Object();
+ parent.prototype = new myfaces._impl.core._Runtime();
+ extendClass(function () {
+ }, parent , {
+ But for now we are not doing it the little bit of saved
+ space is not worth the loss of readability
+ */
+
+//html5 ecmascript 3 compliant browser, no quirks mode needed
+if(!Array.prototype.forEach  && _MF_SINGLTN) {
+/**
+ * @memberOf myfaces._impl
+ * @namespace
+ * @name _util
+ */
+
+/**
+ * @class
+ * @name _Lang
+ * @memberOf myfaces._impl._util
+ * @extends myfaces._impl.core._Runtime
+ * @namespace
+ * @description Object singleton for Language related methods, this object singleton
+ * decorates the namespace myfaces._impl.core._Runtime and adds a bunch of new methods to
+ * what _Runtime provided
+ * <p>This class provides the proper fallbacks for ie8- and Firefox 3.6-</p>
+ * */
+_MF_SINGLTN(_PFX_UTIL+"_LangQuirks", myfaces._impl._util._Lang, {
+
+    constructor_: function() {
+        this._callSuper("constructor_");
+        var _RT = this._RT;
+        var _T = this;
+        //we only apply lazy if the jsf part is loaded already
+        //otherwise we are at the correct position
+        if(myfaces._impl.core.Impl) {
+            _RT.iterateClasses(function(proto) {
+                if(proto._Lang) proto._Lang = _T;
+            });
+        }
+
+        myfaces._impl._util._Lang = _T;
+    },
+
+    /**
+     * foreach implementation utilizing the
+     * ECMAScript wherever possible
+     * with added functionality
+     *
+     * @param arr the array to filter
+     * @param func the closure to apply the function to, with the syntax defined by the ecmascript functionality
+     * function (element<,key, array>)
+     * <p />
+     * optional params
+     * <p />
+     * <ul>
+     *      <li>param startPos (optional) the starting position </li>
+     *      <li>param scope (optional) the scope to apply the closure to  </li>
+     * </ul>
+     */
+    arrForEach: function(arr, func /*startPos, scope*/) {
+        if (!arr || !arr.length) return;
+        try {
+            var startPos = Number(arguments[2]) || 0;
+            var thisObj = arguments[3];
+
+            //check for an existing foreach mapping on array prototypes
+            //IE9 still does not pass array objects as result for dom ops
+            if (Array.prototype.forEach && arr.forEach) {
+                (startPos) ? arr.slice(startPos).forEach(func, thisObj) : arr.forEach(func, thisObj);
+            } else {
+                startPos = (startPos < 0) ? Math.ceil(startPos) : Math.floor(startPos);
+                if (typeof func != "function") {
+                    throw new TypeError();
+                }
+                for (var cnt = 0; cnt < arr.length; cnt++) {
+                    if (thisObj) {
+                        func.call(thisObj, arr[cnt], cnt, arr);
+                    } else {
+                        func(arr[cnt], cnt, arr);
+                    }
+                }
+            }
+        } finally {
+            func = null;
+        }
+    },
+
+    /**
+     * foreach implementation utilizing the
+     * ECMAScript wherever possible
+     * with added functionality
+     *
+     * @param arr the array to filter
+     * @param func the closure to apply the function to, with the syntax defined by the ecmascript functionality
+     * function (element<,key, array>)
+     * <p />
+     * additional params
+     * <ul>
+     *  <li> startPos (optional) the starting position</li>
+     *  <li> scope (optional) the scope to apply the closure to</li>
+     * </ul>
+     */
+    arrFilter: function(arr, func /*startPos, scope*/) {
+        if (!arr || !arr.length) return [];
+        try {
+            var startPos = Number(arguments[2]) || 0;
+            var thisObj = arguments[3];
+
+            //check for an existing foreach mapping on array prototypes
+            if (Array.prototype.filter) {
+                return ((startPos) ? arr.slice(startPos).filter(func, thisObj) : arr.filter(func, thisObj));
+            } else {
+                if (typeof func != "function") {
+                    throw new TypeError();
+                }
+                var ret = [];
+                startPos = (startPos < 0) ? Math.ceil(startPos) : Math.floor(startPos);
+
+                for (var cnt = startPos; cnt < arr.length; cnt++) {
+                    var elem = null;
+                    if (thisObj) {
+                        elem = arr[cnt];
+                        if (func.call(thisObj, elem, cnt, arr)) ret.push(elem);
+                    } else {
+                        elem = arr[cnt];
+                        if (func(arr[cnt], cnt, arr)) ret.push(elem);
+                    }
+                }
+            }
+        } finally {
+            func = null;
+        }
+    },
+
+    /**
+     * adds a EcmaScript optimized indexOf to our mix,
+     * checks for the presence of an indexOf functionality
+     * and applies it, otherwise uses a fallback to the hold
+     * loop method to determine the index
+     *
+     * @param arr the array
+     * @param element the index to search for
+     */
+    arrIndexOf: function(arr, element /*fromIndex*/) {
+        if (!arr || !arr.length) return -1;
+        var pos = Number(arguments[2]) || 0;
+
+        if (Array.prototype.indexOf) {
+            return arr.indexOf(element, pos);
+        }
+        //var cnt = this._space;
+        var len = arr.length;
+        pos = (pos < 0) ? Math.ceil(pos) : Math.floor(pos);
+
+        //if negative then it is taken from as offset from the length of the array
+        if (pos < 0) {
+            pos += len;
+        }
+        while (pos < len && arr[pos] !== element) {
+            pos++;
+        }
+        return (pos < len) ? pos : -1;
+    },
+
+    parseXML: function(txt) {
+        try {
+            var xmlDoc = null;
+            if (window.DOMParser) {
+                xmlDoc = this._callSuper("parseXML", txt);
+            }
+            else // Internet Explorer
+            {
+                xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
+                xmlDoc.async = "false";
+                xmlDoc.loadXML(txt);
+            }
+            return xmlDoc;
+        } catch (e) {
+            //undefined internal parser error
+            return null;
+        }
+    },
+
+    serializeXML: function(xmlNode, escape) {
+        if (xmlNode.xml) return xmlNode.xml; //IE
+        return this._callSuper("serializeXML", xmlNode, escape);
+    },
+
+     /**
+     * Concatenates an array to a string
+     * @param {Array} arr the array to be concatenated
+     * @param {String} delimiter the concatenation delimiter if none is set \n is used
+     *
+     * @return the concatenated array, one special behavior to enable j4fry compatibility has been added
+     * if no delimiter is used the [entryNumber]+entry is generated for a single entry
+     * TODO check if this is still needed it is somewhat outside of the scope of the function
+     * and functionality wise dirty
+     */
+    arrToString : function(/*String or array*/ arr, /*string*/ delimiter) {
+        if (!arr) {
+            throw this._Lang.makeException(new Error(), null, null, this._nameSpace,"arrToString",  this.getMessage("ERR_MUST_BE_PROVIDED1",null, "arr {array}"));
+        }
+        if (this.isString(arr)) {
+            return arr;
+        }
+
+        delimiter = delimiter || "\n";
+        return arr.join(delimiter);
+    }
+});
+
+}
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ Base class which provides several helper functions over all objects
+ */
+_MF_CLS(_PFX_CORE+"Object", Object, {
+
+
+
+    constructor_: function() {
+        this._resettableContent = {};
+        //to make those singleton references
+        //overridable in the instance we have
+        //to load them into the prototype instead
+        //of the instance
+        var proto = this._mfClazz.prototype;
+        var impl = myfaces._impl;
+        if(!proto._RT) {
+            proto._RT  =  impl.core._Runtime;
+            proto._Lang = impl._util._Lang;
+            proto._Dom =  impl._util._Dom;
+        }
+    },
+
+    /*optional functionality can be provided
+     * for ie6 but is turned off by default*/
+    _initDefaultFinalizableFields: function() {
+        var isIE = this._RT.browser.isIE;
+        if(!isIE || isIE > 7) return;
+        for (var key in this) {
+            //per default we reset everything which is not preinitalized
+            if (null == this[key] && key != "_resettableContent" && key.indexOf("_mf") != 0 && key.indexOf("_") == 0) {
+                this._resettableContent[key] = true;
+            }
+        }
+    },
+
+    /**
+     * ie6 cleanup
+     * This method disposes all properties manually in case of ie6
+     * hence reduces the chance of running into a gc problem tremendously
+     * on other browsers this method does nothing
+     */
+    _finalize: function() {
+        try {
+            if (this._isGCed || !this._RT.browser.isIE || !this._resettableContent) {
+                //no ie, no broken garbage collector
+                return;
+            }
+
+            for (var key in this._resettableContent) {
+                if (this._RT.exists(this[key], "_finalize")) {
+                    this[key]._finalize();
+                }
+                delete this[key];
+            }
+        } finally {
+            this._isGCed = true;
+        }
+    },
+
+    attr: function(name, value) {
+       return this._Lang.attr(this, name, value);
+    },
+
+    getImpl: function() {
+        this._Impl = this._Impl || this._RT.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+        return this._Impl;
+    },
+
+    applyArgs: function(args) {
+        this._Lang.applyArgs(this, args);
+    },
+
+    updateSingletons: function(key) {
+        var _T = this;
+        _T._RT.iterateSingletons(function(namespace) {
+            if(namespace[key]) namespace[key] = _T;
+        });
+    }
+
+});
+
+(function() {
+    /*some mobile browsers do not have a window object*/
+    var target = window ||document;
+    var _RT = myfaces._impl.core._Runtime;
+    _RT._MF_OBJECT = target._MF_OBJECT;
+
+     target._MF_OBJECT = myfaces._impl.core.Object;
+})();
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name _Queue
+ * @memberOf myfaces._impl._util
+ * @description Queue implementation used by our runtime system
+ * improved version of
+ * @see <a href="http://safalra.com/web-design/javascript/queues/Queue.js">http://safalra.com/web-design/javascript/queues/Queue.js</a>
+ */
+_MF_CLS(_PFX_UTIL+"_Queue", _MF_OBJECT,
+  /**
+   * @lends myfaces._impl._util._Queue.prototype
+   */
+{
+    //faster queue by http://safalra.com/web-design/javascript/queues/Queue.js
+    //license public domain
+    //The trick is to simply reduce the number of slice and slice ops to a bare minimum.
+
+    _q : null,
+    _space : 0,
+    _size: -1,
+
+    /**
+     * Standard constructor
+     */
+    constructor_: function() {
+        this._callSuper("constructor_");
+        this._q = [];
+    },
+
+    /**
+     * @return the length of the queue as integer
+     */
+    length: function() {
+        // return the number of elements in the queue
+        return this._q.length - this._space;
+
+    },
+
+    /**
+     * @return true if the current queue is empty false otherwise
+     */
+    isEmpty: function() {
+        // return true if the queue is empty, and false otherwise
+        return (this._q.length == 0);
+    },
+
+    /**
+     * Sets the current queue to a new size, all overflow elements at the end are stripped
+     * automatically
+     *
+     * @param {int} newSize as numeric value
+     */
+    setQueueSize: function(newSize) {
+        this._size = newSize;
+        this._readjust();
+    },
+
+    /**
+     * adds a listener to the queue
+     *
+     * @param element the listener to be added
+     */
+    enqueue : function(/*function*/element) {
+        this._q.push(element);
+        //qeuesize is bigger than the limit we drop one element so that we are
+        //back in line
+
+        this._readjust();
+    },
+
+    _readjust: function() {
+        var size = this._size;
+        while (size && size > -1 && this.length() > size) {
+            this.dequeue();
+        }
+    },
+
+    /**
+     * removes a listener form the queue
+     *
+     * @param element the listener to be removed
+     */
+    remove : function(/*function*/element) {
+        /*find element in queue*/
+        var index = this.indexOf(element);
+        /*found*/
+        if (index != -1) {
+            this._q.splice(index, 1);
+        }
+    },
+
+    /**
+     * dequeues the last element in the queue
+     * @return {Object} element which is dequeued
+     */
+    dequeue: function() {
+        // initialise the element to return to be undefined
+        var element = null;
+
+        // check whether the queue is empty
+        var qLen = this._q.length;
+        var queue = this._q;
+
+        if (qLen) {
+
+            // fetch the oldest element in the queue
+            element = queue[this._space];
+
+            // update the amount of space and check whether a shift should occur
+            //added here a max limit of 30
+            //now bit shift left is a tad faster than multiplication on most vms and does the same
+            //unless we run into a bit skipping which is impossible in our usecases here
+            if ((++this._space) << 1 >= qLen) {
+
+                // set the queue equal to the non-empty portion of the queue
+                this._q = queue.slice(this._space);
+
+                // reset the amount of space at the front of the queue
+                this._space = 0;
+
+            }
+
+        }
+
+        // return the removed element
+        return element;
+    },
+
+    /**
+     * simple foreach
+     *
+     * @param closure a closure which processes the element
+     * @code
+     *   queue.each(function(element) {
+     *      //do something with the element
+     *   });
+     */
+    each: function(closure) {
+        this._Lang.arrForEach(this._q, closure, this._space);
+    },
+
+    /**
+     * Simple filter
+     *
+     * @param closure a closure which returns true or false depending
+     * whether the filter has triggered
+     *
+     * @return an array of filtered queue entries
+     */
+    arrFilter: function(closure) {
+        return this._Lang.arrFilter(this._q, closure, this._space);
+    },
+
+    /**
+     * @param element
+     * @return the current index of the element in the queue or -1 if it is not found
+     */
+    indexOf: function(element) {
+        return this._Lang.arrIndexOf(this._q, element);
+    },
+
+    /**
+     * resets the queue to initial empty state
+     */
+    cleanup: function() {
+        this._q = [];
+        this._space = 0;
+    }
+});
+
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * a classical listener queue pattern
+ */
+
+
+
+/**
+ * @class
+ * @name _ListenerQueue
+ * @extends myfaces._impl._util._Queue
+ * @memberOf myfaces._impl._util
+ * @description Implementation of the listener queue for jsf.js
+ * <p>It is based upon our high performance queue and adds dedicated
+ * methods for listener based closures to the mix </p>
+ * */
+_MF_CLS(_PFX_UTIL+"_ListenerQueue", myfaces._impl._util._Queue,
+/**
+ * @lends myfaces._impl._util._ListenerQueue.prototype
+ */
+{
+    /**
+     * listener type safety assertion function
+     *
+     * @param {function} listener must be of type function otherwise an error is raised
+     */
+    _assertListener : function( listener) {
+        if ("function" != typeof (listener)) {
+            var msg = myfaces._impl._util._Lang.getMessage("ERR_PARAM_GENERIC",null,"_ListenerQueue", arguments.caller.toString(),"function" );
+            throw this._Lang.makeException(new Error(), null, null, this._nameSpace,arguments.caller.toString(),  msg);
+        }
+    },
+
+    /**
+     * adds a listener to the queue
+     *
+     * @param {function} listener the listener to be added
+     */
+    enqueue : function(listener) {
+        this._assertListener(listener);
+        this._callSuper("enqueue", listener);
+    },
+
+    /**
+     * removes a listener form the queue
+     *
+     * @param {function} listener the listener to be removed
+     */
+    remove : function(listener) {
+        this._assertListener(listener);
+        this._callSuper("remove", listener);
+    },
+
+    /**
+     * generic broadcast with a number of arguments being passed down
+     * @param {Object} argument the arguments passed down which are broadcast
+     */
+    broadcastEvent : function(argument) {
+        var _args = myfaces._impl._util._Lang.objToArray(arguments);
+
+        var broadCastFunc = function(element) {
+            element.apply(null, _args);
+        };
+        try {
+            this.each(broadCastFunc);
+        } finally {
+            broadCastFunc = null;
+        }
+    }
+});
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,©
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name _Dom
+ * @memberOf myfaces._impl._util
+ * @extends myfaces._impl.core._Runtime
+ * @description Object singleton collection of dom helper routines
+ * (which in later incarnations will
+ * get browser specific speed optimizations)
+ *
+ * Since we have to be as tight as possible
+ * we will focus with our dom routines to only
+ * the parts which our impl uses.
+ * A jquery like query API would be nice
+ * but this would increase up our codebase significantly
+ *
+ * <p>This class provides the proper fallbacks for ie8- and Firefox 3.6-</p>
+ */
+_MF_SINGLTN(_PFX_UTIL + "_Dom", Object, /** @lends myfaces._impl._util._Dom.prototype */ {
+
+    /*table elements which are used in various parts */
+    TABLE_ELEMS:  {
+        "thead": 1,
+        "tbody": 1,
+        "tr": 1,
+        "th": 1,
+        "td": 1,
+        "tfoot" : 1
+    },
+
+    _Lang:  myfaces._impl._util._Lang,
+    _RT:    myfaces._impl.core._Runtime,
+    _dummyPlaceHolder:null,
+
+    /**
+     * standard constructor
+     */
+    constructor_: function() {
+    },
+
+    runCss: function(item/*, xmlData*/) {
+
+        var  UDEF = "undefined",
+                _RT = this._RT,
+                _Lang = this._Lang,
+                applyStyle = function(item, style) {
+                    var newSS = document.createElement("style");
+
+                    newSS.setAttribute("rel", item.getAttribute("rel") || "stylesheet");
+                    newSS.setAttribute("type", item.getAttribute("type") || "text/css");
+                    document.getElementsByTagName("head")[0].appendChild(newSS);
+                    //ie merrily again goes its own way
+                    if (window.attachEvent && !_RT.isOpera && UDEF != typeof newSS.styleSheet && UDEF != newSS.styleSheet.cssText) newSS.styleSheet.cssText = style;
+                    else newSS.appendChild(document.createTextNode(style));
+                },
+
+                execCss = function(item) {
+                    var equalsIgnoreCase = _Lang.equalsIgnoreCase;
+                    var tagName = item.tagName;
+                    if (tagName && equalsIgnoreCase(tagName, "link") && equalsIgnoreCase(item.getAttribute("type"), "text/css")) {
+                        applyStyle(item, "@import url('" + item.getAttribute("href") + "');");
+                    } else if (tagName && equalsIgnoreCase(tagName, "style") && equalsIgnoreCase(item.getAttribute("type"), "text/css")) {
+                        var innerText = [];
+                        //compliant browsers know child nodes
+                        var childNodes = item.childNodes;
+                        if (childNodes) {
+                            var len = childNodes.length;
+                            for (var cnt = 0; cnt < len; cnt++) {
+                                innerText.push(childNodes[cnt].innerHTML || childNodes[cnt].data);
+                            }
+                            //non compliant ones innerHTML
+                        } else if (item.innerHTML) {
+                            innerText.push(item.innerHTML);
+                        }
+
+                        applyStyle(item, innerText.join(""));
+                    }
+                };
+
+        try {
+            var scriptElements = this.findByTagNames(item, {"link":1,"style":1}, true);
+            if (scriptElements == null) return;
+            for (var cnt = 0; cnt < scriptElements.length; cnt++) {
+                execCss(scriptElements[cnt]);
+            }
+
+        } finally {
+            //the usual ie6 fix code
+            //the IE6 garbage collector is broken
+            //nulling closures helps somewhat to reduce
+            //mem leaks, which are impossible to avoid
+            //at this browser
+            execCss = null;
+            applyStyle = null;
+        }
+    },
+
+
+    /**
+     * Run through the given Html item and execute the inline scripts
+     * (IE doesn't do this by itself)
+     * @param {Node} item
+     */
+    runScripts: function(item, xmlData) {
+        var _Lang = this._Lang,
+            _RT = this._RT,
+            finalScripts = [],
+            execScrpt = function(item) {
+                var tagName = item.tagName;
+                var type = item.type || "";
+                //script type javascript has to be handled by eval, other types
+                //must be handled by the browser
+                if (tagName && _Lang.equalsIgnoreCase(tagName, "script") &&
+                        (type === "" ||
+                        _Lang.equalsIgnoreCase(type,"text/javascript") ||
+                        _Lang.equalsIgnoreCase(type,"javascript") ||
+                        _Lang.equalsIgnoreCase(type,"text/ecmascript") ||
+                        _Lang.equalsIgnoreCase(type,"ecmascript"))) {
+
+                    var src = item.getAttribute('src');
+                    if ('undefined' != typeof src
+                            && null != src
+                            && src.length > 0
+                            ) {
+                        //we have to move this into an inner if because chrome otherwise chokes
+                        //due to changing the and order instead of relying on left to right
+                        //if jsf.js is already registered we do not replace it anymore
+                        if ((src.indexOf("ln=scripts") == -1 && src.indexOf("ln=javax.faces") == -1) || (src.indexOf("/jsf.js") == -1
+                                && src.indexOf("/jsf-uncompressed.js") == -1)) {
+                            if (finalScripts.length) {
+                                //script source means we have to eval the existing
+                                //scripts before running the include
+                                _RT.globalEval(finalScripts.join("\n"));
+
+                                finalScripts = [];
+                            }
+                            _RT.loadScriptEval(src, item.getAttribute('type'), false, "UTF-8", false);
+                        }
+
+                    } else {
+                        // embedded script auto eval
+                        var test = (!xmlData) ? item.text : _Lang.serializeChilds(item);
+                        var go = true;
+                        while (go) {
+                            go = false;
+                            if (test.substring(0, 1) == " ") {
+                                test = test.substring(1);
+                                go = true;
+                            }
+                            if (test.substring(0, 4) == "<!--") {
+                                test = test.substring(4);
+                                go = true;
+                            }
+                            if (test.substring(0, 11) == "//<![CDATA[") {
+                                test = test.substring(11);
+                                go = true;
+                            }
+                        }
+                        // we have to run the script under a global context
+                        //we store the script for less calls to eval
+                        finalScripts.push(test);
+
+                    }
+                }
+            };
+        try {
+            var scriptElements = this.findByTagName(item, "script", true);
+            if (scriptElements == null) return;
+            for (var cnt = 0; cnt < scriptElements.length; cnt++) {
+                execScrpt(scriptElements[cnt]);
+            }
+            if (finalScripts.length) {
+                _RT.globalEval(finalScripts.join("\n"));
+            }
+        } catch (e) {
+            //we are now in accordance with the rest of the system of showing errors only in development mode
+            //the default error output is alert we always can override it with
+            //window.myfaces = window.myfaces || {};
+            //myfaces.config =  myfaces.config || {};
+            //myfaces.config.defaultErrorOutput = console.error;
+            if(jsf.getProjectStage() === "Development") {
+                var defaultErrorOutput = myfaces._impl.core._Runtime.getGlobalConfig("defaultErrorOutput", alert);
+                defaultErrorOutput("Error in evaluated javascript:"+ (e.message || e.description || e));
+            }
+        } finally {
+            //the usual ie6 fix code
+            //the IE6 garbage collector is broken
+            //nulling closures helps somewhat to reduce
+            //mem leaks, which are impossible to avoid
+            //at this browser
+            execScrpt = null;
+        }
+    },
+
+
+    /**
+     * determines to fetch a node
+     * from its id or name, the name case
+     * only works if the element is unique in its name
+     * @param {String} elem
+     */
+    byIdOrName: function(elem) {
+        if (!elem) return null;
+        if (!this._Lang.isString(elem)) return elem;
+
+        var ret = this.byId(elem);
+        if (ret) return ret;
+        //we try the unique name fallback
+        var items = document.getElementsByName(elem);
+        return ((items.length == 1) ? items[0] : null);
+    },
+
+    /**
+     * node id or name, determines the valid form identifier of a node
+     * depending on its uniqueness
+     *
+     * Usually the id is chosen for an elem, but if the id does not
+     * exist we try a name fallback. If the passed element has a unique
+     * name we can use that one as subsequent identifier.
+     *
+     *
+     * @param {String} elem
+     */
+    nodeIdOrName: function(elem) {
+        if (elem) {
+            //just to make sure that the pas
+
+            elem = this.byId(elem);
+            if (!elem) return null;
+            //detached element handling, we also store the element name
+            //to get a fallback option in case the identifier is not determinable
+            // anymore, in case of a framework induced detachment the element.name should
+            // be shared if the identifier is not determinable anymore
+            //the downside of this method is the element name must be unique
+            //which in case of jsf it is
+            var elementId = elem.id || elem.name;
+            if ((elem.id == null || elem.id == '') && elem.name) {
+                elementId = elem.name;
+
+                //last check for uniqueness
+                if (document.getElementsByName(elementId).length > 1) {
+                    //no unique element name so we need to perform
+                    //a return null to let the caller deal with this issue
+                    return null;
+                }
+            }
+            return elementId;
+        }
+        return null;
+    },
+
+    deleteItems: function(items) {
+        if (! items || ! items.length) return;
+        for (var cnt = 0; cnt < items.length; cnt++) {
+            this.deleteItem(items[cnt]);
+        }
+    },
+
+    /**
+     * Simple delete on an existing item
+     */
+    deleteItem: function(itemIdToReplace) {
+        var item = this.byId(itemIdToReplace);
+        if (!item) {
+            throw this._Lang.makeException(new Error(),null, null, this._nameSpace, "deleteItem",  "_Dom.deleteItem  Unknown Html-Component-ID: " + itemIdToReplace);
+        }
+
+        this._removeNode(item, false);
+    },
+
+    /**
+     * creates a node upon a given node name
+     * @param nodeName {String} the node name to be created
+     * @param attrs {Array} a set of attributes to be set
+     */
+    createElement: function(nodeName, attrs) {
+        var ret = document.createElement(nodeName);
+        if (attrs) {
+            for (var key in attrs) {
+                if(!attrs.hasOwnProperty(key)) continue;
+                this.setAttribute(ret, key, attrs[key]);
+            }
+        }
+        return ret;
+    },
+
+    /**
+     * Checks whether the browser is dom compliant.
+     * Dom compliant means that it performs the basic dom operations safely
+     * without leaking and also is able to perform a native setAttribute
+     * operation without freaking out
+     *
+     *
+     * Not dom compliant browsers are all microsoft browsers in quirks mode
+     * and ie6 and ie7 to some degree in standards mode
+     * and pretty much every browser who cannot create ranges
+     * (older mobile browsers etc...)
+     *
+     * We dont do a full browser detection here because it probably is safer
+     * to test for existing features to make an assumption about the
+     * browsers capabilities
+     */
+    isDomCompliant: function() {
+        return true;
+    },
+
+    /**
+     * proper insert before which takes tables into consideration as well as
+     * browser deficiencies
+     * @param item the node to insert before
+     * @param markup the markup to be inserted
+     */
+    insertBefore: function(item, markup) {
+        this._assertStdParams(item, markup, "insertBefore");
+
+        markup = this._Lang.trim(markup);
+        if (markup === "") return null;
+
+        var evalNodes = this._buildEvalNodes(item, markup),
+                currentRef = item,
+                parentNode = item.parentNode,
+                ret = [];
+        for (var cnt = evalNodes.length - 1; cnt >= 0; cnt--) {
+            currentRef = parentNode.insertBefore(evalNodes[cnt], currentRef);
+            ret.push(currentRef);
+        }
+        ret = ret.reverse();
+        this._eval(ret);
+        return ret;
+    },
+
+    /**
+     * proper insert before which takes tables into consideration as well as
+     * browser deficiencies
+     * @param item the node to insert before
+     * @param markup the markup to be inserted
+     */
+    insertAfter: function(item, markup) {
+        this._assertStdParams(item, markup, "insertAfter");
+        markup = this._Lang.trim(markup);
+        if (markup === "") return null;
+
+        var evalNodes = this._buildEvalNodes(item, markup),
+                currentRef = item,
+                parentNode = item.parentNode,
+                ret = [];
+
+        for (var cnt = 0; cnt < evalNodes.length; cnt++) {
+            if (currentRef.nextSibling) {
+                //Winmobile 6 has problems with this strategy, but it is not really fixable
+                currentRef = parentNode.insertBefore(evalNodes[cnt], currentRef.nextSibling);
+            } else {
+                currentRef = parentNode.appendChild(evalNodes[cnt]);
+            }
+            ret.push(currentRef);
+        }
+        this._eval(ret);
+        return ret;
+    },
+
+    propertyToAttribute: function(name) {
+        if (name === 'className') {
+            return 'class';
+        } else if (name === 'xmllang') {
+            return 'xml:lang';
+        } else {
+            return name.toLowerCase();
+        }
+    },
+
+    isFunctionNative: function(func) {
+        return /^\s*function[^{]+{\s*\[native code\]\s*}\s*$/.test(String(func));
+    },
+
+    detectAttributes: function(element) {
+        //test if 'hasAttribute' method is present and its native code is intact
+        //for example, Prototype can add its own implementation if missing
+        if (element.hasAttribute && this.isFunctionNative(element.hasAttribute)) {
+            return function(name) {
+                return element.hasAttribute(name);
+            }
+        } else {
+            try {
+                //when accessing .getAttribute method without arguments does not throw an error then the method is not available
+                element.getAttribute;
+
+                var html = element.outerHTML;
+                var startTag = html.match(/^<[^>]*>/)[0];
+                return function(name) {
+                    return startTag.indexOf(name + '=') > -1;
+                }
+            } catch (ex) {
+                return function(name) {
+                    return element.getAttribute(name);
+                }
+            }
+        }
+    },
+
+    /**
+     * copy all attributes from one element to another - except id
+     * @param target element to copy attributes to
+     * @param source element to copy attributes from
+     * @ignore
+     */
+    cloneAttributes: function(target, source) {
+
+        // enumerate core element attributes - without 'dir' as special case
+        var coreElementProperties = ['className', 'title', 'lang', 'xmllang'];
+        // enumerate additional input element attributes
+        var inputElementProperties = [
+            'name', 'value', 'size', 'maxLength', 'src', 'alt', 'useMap', 'tabIndex', 'accessKey', 'accept', 'type'
+        ];
+        // enumerate additional boolean input attributes
+        var inputElementBooleanProperties = [
+            'checked', 'disabled', 'readOnly'
+        ];
+
+        // Enumerate all the names of the event listeners
+        var listenerNames =
+            [ 'onclick', 'ondblclick', 'onmousedown', 'onmousemove', 'onmouseout',
+                'onmouseover', 'onmouseup', 'onkeydown', 'onkeypress', 'onkeyup',
+                'onhelp', 'onblur', 'onfocus', 'onchange', 'onload', 'onunload', 'onabort',
+                'onreset', 'onselect', 'onsubmit'
+            ];
+
+        var sourceAttributeDetector = this.detectAttributes(source);
+        var targetAttributeDetector = this.detectAttributes(target);
+
+        var isInputElement = target.nodeName.toLowerCase() === 'input';
+        var propertyNames = isInputElement ? coreElementProperties.concat(inputElementProperties) : coreElementProperties;
+        var isXML = !source.ownerDocument.contentType || source.ownerDocument.contentType == 'text/xml';
+        for (var iIndex = 0, iLength = propertyNames.length; iIndex < iLength; iIndex++) {
+            var propertyName = propertyNames[iIndex];
+            var attributeName = this.propertyToAttribute(propertyName);
+            if (sourceAttributeDetector(attributeName)) {
+
+                //With IE 7 (quirks or standard mode) and IE 8/9 (quirks mode only),
+                //you cannot get the attribute using 'class'. You must use 'className'
+                //which is the same value you use to get the indexed property. The only
+                //reliable way to detect this (without trying to evaluate the browser
+                //mode and version) is to compare the two return values using 'className'
+                //to see if they exactly the same.  If they are, then use the property
+                //name when using getAttribute.
+                if( attributeName == 'class'){
+                    if( this._RT.browser.isIE && (source.getAttribute(propertyName) === source[propertyName]) ){
+                        attributeName = propertyName;
+                    }
+                }
+
+                var newValue = isXML ? source.getAttribute(attributeName) : source[propertyName];
+                var oldValue = target[propertyName];
+                if (oldValue != newValue) {
+                    target[propertyName] = newValue;
+                }
+            } else {
+                target.removeAttribute(attributeName);
+                if (attributeName == "value") {
+                    target[propertyName] = '';
+                }
+            }
+        }
+
+        var booleanPropertyNames = isInputElement ? inputElementBooleanProperties : [];
+        for (var jIndex = 0, jLength = booleanPropertyNames.length; jIndex < jLength; jIndex++) {
+            var booleanPropertyName = booleanPropertyNames[jIndex];
+            var newBooleanValue = source[booleanPropertyName];
+            var oldBooleanValue = target[booleanPropertyName];
+            if (oldBooleanValue != newBooleanValue) {
+                target[booleanPropertyName] = newBooleanValue;
+            }
+        }
+
+        //'style' attribute special case
+        if (sourceAttributeDetector('style')) {
+            var newStyle;
+            var oldStyle;
+            if (this._RT.browser.isIE) {
+                newStyle = source.style.cssText;
+                oldStyle = target.style.cssText;
+                if (newStyle != oldStyle) {
+                    target.style.cssText = newStyle;
+                }
+            } else {
+                newStyle = source.getAttribute('style');
+                oldStyle = target.getAttribute('style');
+                if (newStyle != oldStyle) {
+                    target.setAttribute('style', newStyle);
+                }
+            }
+        } else if (targetAttributeDetector('style')){
+            target.removeAttribute('style');
+        }
+
+        // Special case for 'dir' attribute
+        if (!this._RT.browser.isIE && source.dir != target.dir) {
+            if (sourceAttributeDetector('dir')) {
+                target.dir = source.dir;
+            } else if (targetAttributeDetector('dir')) {
+                target.dir = '';
+            }
+        }
+
+        for (var lIndex = 0, lLength = listenerNames.length; lIndex < lLength; lIndex++) {
+            var name = listenerNames[lIndex];
+            target[name] = source[name] ? source[name] : null;
+            if (source[name]) {
+                source[name] = null;
+            }
+        }
+
+        //clone HTML5 data-* attributes
+        try{
+            var targetDataset = target.dataset;
+            var sourceDataset = source.dataset;
+            if (targetDataset || sourceDataset) {
+                //cleanup the dataset
+                for (var tp in targetDataset) {
+                    delete targetDataset[tp];
+                }
+                //copy dataset's properties
+                for (var sp in sourceDataset) {
+                    targetDataset[sp] = sourceDataset[sp];
+                }
+            }
+        } catch (ex) {
+            //most probably dataset properties are not supported
+        }
+    },
+    //from
+    // http://blog.vishalon.net/index.php/javascript-getting-and-setting-caret-position-in-textarea/
+    getCaretPosition:function (ctrl) {
+        var caretPos = 0;
+
+        try {
+
+            // other browsers make it simpler by simply having a selection start element
+            if (ctrl.selectionStart || ctrl.selectionStart == '0')
+                caretPos = ctrl.selectionStart;
+            // ie 5 quirks mode as second option because
+            // this option is flakey in conjunction with text areas
+            // TODO move this into the quirks class
+            else if (document.selection) {
+                ctrl.focus();
+                var selection = document.selection.createRange();
+                //the selection now is start zero
+                selection.moveStart('character', -ctrl.value.length);
+                //the caretposition is the selection start
+                caretPos = selection.text.length;
+            }
+        } catch (e) {
+            //now this is ugly, but not supported input types throw errors for selectionStart
+            //this way we are future proof by having not to define every selection enabled
+            //input in an if (which will be a lot in the near future with html5)
+        }
+        return caretPos;
+    },
+
+    setCaretPosition:function (ctrl, pos) {
+
+        if (ctrl.createTextRange) {
+            var range = ctrl.createTextRange();
+            range.collapse(true);
+            range.moveEnd('character', pos);
+            range.moveStart('character', pos);
+            range.select();
+        }
+        //IE quirks mode again, TODO move this into the quirks class
+        else if (ctrl.setSelectionRange) {
+            ctrl.focus();
+            //the selection range is our caret position
+            ctrl.setSelectionRange(pos, pos);
+        }
+    },
+
+    /**
+     * outerHTML replacement which works cross browserlike
+     * but still is speed optimized
+     *
+     * @param item the item to be replaced
+     * @param markup the markup for the replacement
+     * @param preserveFocus, tries to preserve the focus within the outerhtml operation
+     * if set to true a focus preservation algorithm based on document.activeElement is
+     * used to preserve the focus at the exactly same location as it was
+     *
+     */
+    outerHTML : function(item, markup, preserveFocus) {
+        this._assertStdParams(item, markup, "outerHTML");
+        // we can work on a single element in a cross browser fashion
+        // regarding the focus thanks to the
+        // icefaces team for providing the code
+        if (item.nodeName.toLowerCase() === 'input') {
+            var replacingInput = this._buildEvalNodes(item, markup)[0];
+            this.cloneAttributes(item, replacingInput);
+            return item;
+        } else {
+            markup = this._Lang.trim(markup);
+            if (markup !== "") {
+                var ret = null;
+
+                var focusElementId = null;
+                var caretPosition = 0;
+                if (preserveFocus && 'undefined' != typeof document.activeElement) {
+                    focusElementId = (document.activeElement) ? document.activeElement.id : null;
+                    caretPosition = this.getCaretPosition(document.activeElement);
+                }
+                // we try to determine the browsers compatibility
+                // level to standards dom level 2 via various methods
+                if (this.isDomCompliant()) {
+                    ret = this._outerHTMLCompliant(item, markup);
+                } else {
+                    //call into abstract method
+                    ret = this._outerHTMLNonCompliant(item, markup);
+                }
+                if (focusElementId) {
+                    var newFocusElement = this.byId(focusElementId);
+                    if (newFocusElement && newFocusElement.nodeName.toLowerCase() === 'input') {
+                        //just in case the replacement element is not focusable anymore
+                        if ("undefined" != typeof newFocusElement.focus) {
+                            newFocusElement.focus();
+                        }
+                    }
+                    if (newFocusElement && caretPosition) {
+                        //zero caret position is set automatically on focus
+                        this.setCaretPosition(newFocusElement, caretPosition);
+                    }
+                }
+
+                // and remove the old item
+                //first we have to save the node newly insert for easier access in our eval part
+                this._eval(ret);
+                return ret;
+            }
+            // and remove the old item, in case of an empty newtag and do nothing else
+            this._removeNode(item, false);
+            return null;
+        }
+    },
+
+    isFunctionNative: function(func) {
+        return /^\s*function[^{]+{\s*\[native code\]\s*}\s*$/.test(String(func));
+    },
+
+    detectAttributes: function(element) {
+        //test if 'hasAttribute' method is present and its native code is intact
+        //for example, Prototype can add its own implementation if missing
+        if (element.hasAttribute && this.isFunctionNative(element.hasAttribute)) {
+            return function(name) {
+                return element.hasAttribute(name);
+            }
+        } else {
+            try {
+                //when accessing .getAttribute method without arguments does not throw an error then the method is not available
+                element.getAttribute;
+
+                var html = element.outerHTML;
+                var startTag = html.match(/^<[^>]*>/)[0];
+                return function(name) {
+                    return startTag.indexOf(name + '=') > -1;
+                }
+            } catch (ex) {
+                return function(name) {
+                    return element.getAttribute(name);
+                }
+            }
+        }
+    },
+
+    /**
+     * detaches a set of nodes from their parent elements
+     * in a browser independend manner
+     * @param {Object} items the items which need to be detached
+     * @return {Array} an array of nodes with the detached dom nodes
+     */
+    detach: function(items) {
+        var ret = [];
+        if ('undefined' != typeof items.nodeType) {
+            if (items.parentNode) {
+                ret.push(items.parentNode.removeChild(items));
+            } else {
+                ret.push(items);
+            }
+            return ret;
+        }
+        //all ies treat node lists not as arrays so we have to take
+        //an intermediate step
+        var nodeArr = this._Lang.objToArray(items);
+        for (var cnt = 0; cnt < nodeArr.length; cnt++) {
+            ret.push(nodeArr[cnt].parentNode.removeChild(nodeArr[cnt]));
+        }
+        return ret;
+    },
+
+    _outerHTMLCompliant: function(item, markup) {
+        //table element replacements like thead, tbody etc... have to be treated differently
+        var evalNodes = this._buildEvalNodes(item, markup);
+
+        if (evalNodes.length == 1) {
+            var ret = evalNodes[0];
+            item.parentNode.replaceChild(ret, item);
+            return ret;
+        } else {
+            return this.replaceElements(item, evalNodes);
+        }
+    },
+
+    /**
+     * checks if the provided element is a subelement of a table element
+     * @param item
+     */
+    _isTableElement: function(item) {
+        return !!this.TABLE_ELEMS[(item.nodeName || item.tagName).toLowerCase()];
+    },
+
+    /**
+     * non ie browsers do not have problems with embedded scripts or any other construct
+     * we simply can use an innerHTML in a placeholder
+     *
+     * @param markup the markup to be used
+     */
+    _buildNodesCompliant: function(markup) {
+        var dummyPlaceHolder = this.getDummyPlaceHolder(); //document.createElement("div");
+        dummyPlaceHolder.innerHTML = markup;
+        return this._Lang.objToArray(dummyPlaceHolder.childNodes);
+    },
+
+
+
+
+    /**
+     * builds up a correct dom subtree
+     * if the markup is part of table nodes
+     * The usecase for this is to allow subtable rendering
+     * like single rows thead or tbody
+     *
+     * @param item
+     * @param markup
+     */
+    _buildTableNodes: function(item, markup) {
+        var itemNodeName = (item.nodeName || item.tagName).toLowerCase();
+
+        var tmpNodeName = itemNodeName;
+        var depth = 0;
+        while (tmpNodeName != "table") {
+            item = item.parentNode;
+            tmpNodeName = (item.nodeName || item.tagName).toLowerCase();
+            depth++;
+        }
+
+        var dummyPlaceHolder = this.getDummyPlaceHolder();
+        if (itemNodeName == "td") {
+            dummyPlaceHolder.innerHTML = "<table><tbody><tr>" + markup + "</tr></tbody></table>";
+        } else {
+            dummyPlaceHolder.innerHTML = "<table>" + markup + "</table>";
+        }
+
+        for (var cnt = 0; cnt < depth; cnt++) {
+            dummyPlaceHolder = dummyPlaceHolder.childNodes[0];
+        }
+
+        return this.detach(dummyPlaceHolder.childNodes);
+    },
+
+    _removeChildNodes: function(node /*, breakEventsOpen */) {
+        if (!node) return;
+        node.innerHTML = "";
+    },
+
+
+
+    _removeNode: function(node /*, breakEventsOpen*/) {
+        if (!node) return;
+        var parentNode = node.parentNode;
+        if (parentNode) //if the node has a parent
+            parentNode.removeChild(node);
+    },
+
+
+    /**
+     * build up the nodes from html markup in a browser independend way
+     * so that it also works with table nodes
+     *
+     * @param item the parent item upon the nodes need to be processed upon after building
+     * @param markup the markup to be built up
+     */
+    _buildEvalNodes: function(item, markup) {
+        var evalNodes = null;
+        if (this._isTableElement(item)) {
+            evalNodes = this._buildTableNodes(item, markup);
+        } else {
+            var nonIEQuirks = (!this._RT.browser.isIE || this._RT.browser.isIE > 8);
+            //ie8 has a special problem it still has the swallow scripts and other
+            //elements bug, but it is mostly dom compliant so we have to give it a special
+            //treatment, IE9 finally fixes that issue finally after 10 years
+            evalNodes = (this.isDomCompliant() &&  nonIEQuirks) ?
+                    this._buildNodesCompliant(markup) :
+                    //ie8 or quirks mode browsers
+                    this._buildNodesNonCompliant(markup);
+        }
+        return evalNodes;
+    },
+
+    /**
+     * we have lots of methods with just an item and a markup as params
+     * this method builds an assertion for those methods to reduce code
+     *
+     * @param item  the item to be tested
+     * @param markup the markup
+     * @param caller caller function
+     * @param {optional} params array of assertion param names
+     */
+    _assertStdParams: function(item, markup, caller, params) {
+        //internal error
+        if (!caller) {
+            throw this._Lang.makeException(new Error(), null, null, this._nameSpace, "_assertStdParams",  "Caller must be set for assertion");
+        }
+        var _Lang = this._Lang,
+                ERR_PROV = "ERR_MUST_BE_PROVIDED1",
+                DOM = "myfaces._impl._util._Dom.",
+                finalParams = params || ["item", "markup"];
+
+        if (!item || !markup) {
+            _Lang.makeException(new Error(), null, null,DOM, ""+caller,  _Lang.getMessage(ERR_PROV, null, DOM +"."+ caller, (!item) ? finalParams[0] : finalParams[1]));
+            //throw Error(_Lang.getMessage(ERR_PROV, null, DOM + caller, (!item) ? params[0] : params[1]));
+        }
+    },
+
+    /**
+     * internal eval handler used by various functions
+     * @param _nodeArr
+     */
+    _eval: function(_nodeArr) {
+        if (this.isManualScriptEval()) {
+            var isArr = _nodeArr instanceof Array;
+            if (isArr && _nodeArr.length) {
+                for (var cnt = 0; cnt < _nodeArr.length; cnt++) {
+                    this.runScripts(_nodeArr[cnt]);
+                }
+            } else if (!isArr) {
+                this.runScripts(_nodeArr);
+            }
+        }
+    },
+
+    /**
+     * for performance reasons we work with replaceElement and replaceElements here
+     * after measuring performance it has shown that passing down an array instead
+     * of a single node makes replaceElement twice as slow, however
+     * a single node case is the 95% case
+     *
+     * @param item
+     * @param evalNode
+     */
+    replaceElement: function(item, evalNode) {
+        //browsers with defect garbage collection
+        item.parentNode.insertBefore(evalNode, item);
+        this._removeNode(item, false);
+    },
+
+
+    /**
+     * replaces an element with another element or a set of elements
+     *
+     * @param item the item to be replaced
+     *
+     * @param evalNodes the elements
+     */
+    replaceElements: function (item, evalNodes) {
+        var evalNodesDefined = evalNodes && 'undefined' != typeof evalNodes.length;
+        if (!evalNodesDefined) {
+            throw this._Lang.makeException(new Error(), null, null, this._nameSpace, "replaceElements",  this._Lang.getMessage("ERR_REPLACE_EL"));
+        }
+
+        var parentNode = item.parentNode,
+
+                sibling = item.nextSibling,
+                resultArr = this._Lang.objToArray(evalNodes);
+
+        for (var cnt = 0; cnt < resultArr.length; cnt++) {
+            if (cnt == 0) {
+                this.replaceElement(item, resultArr[cnt]);
+            } else {
+                if (sibling) {
+                    parentNode.insertBefore(resultArr[cnt], sibling);
+                } else {
+                    parentNode.appendChild(resultArr[cnt]);
+                }
+            }
+        }
+        return resultArr;
+    },
+
+    /**
+     * optimized search for an array of tag names
+     * deep scan will always be performed.
+     * @param fragment the fragment which should be searched for
+     * @param tagNames an map indx of tag names which have to be found
+     *
+     */
+    findByTagNames: function(fragment, tagNames) {
+        this._assertStdParams(fragment, tagNames, "findByTagNames", ["fragment", "tagNames"]);
+
+        var nodeType = fragment.nodeType;
+        if (nodeType != 1 && nodeType != 9 && nodeType != 11) return null;
+
+        //we can use the shortcut
+        if (fragment.querySelectorAll) {
+            var query = [];
+            for (var key in tagNames) {
+                if(!tagNames.hasOwnProperty(key)) continue;
+                query.push(key);
+            }
+            var res = [];
+            if (fragment.tagName && tagNames[fragment.tagName.toLowerCase()]) {
+                res.push(fragment);
+            }
+            return res.concat(this._Lang.objToArray(fragment.querySelectorAll(query.join(", "))));
+        }
+
+        //now the filter function checks case insensitively for the tag names needed
+        var filter = function(node) {
+            return node.tagName && tagNames[node.tagName.toLowerCase()];
+        };
+
+        //now we run an optimized find all on it
+        try {
+            return this.findAll(fragment, filter, true);
+        } finally {
+            //the usual IE6 is broken, fix code
+            filter = null;
+        }
+    },
+
+    /**
+     * determines the number of nodes according to their tagType
+     *
+     * @param {Node} fragment (Node or fragment) the fragment to be investigated
+     * @param {String} tagName the tag name (lowercase)
+     * (the normal usecase is false, which means if the element is found only its
+     * adjacent elements will be scanned, due to the recursive descension
+     * this should work out with elements with different nesting depths but not being
+     * parent and child to each other
+     *
+     * @return the child elements as array or null if nothing is found
+     *
+     */
+    findByTagName : function(fragment, tagName) {
+        this._assertStdParams(fragment, tagName, "findByTagName", ["fragment", "tagName"]);
+        var _Lang = this._Lang,
+                nodeType = fragment.nodeType;
+        if (nodeType != 1 && nodeType != 9 && nodeType != 11) return null;
+
+        //remapping to save a few bytes
+
+        var ret = _Lang.objToArray(fragment.getElementsByTagName(tagName));
+        if (fragment.tagName && _Lang.equalsIgnoreCase(fragment.tagName, tagName)) ret.unshift(fragment);
+        return ret;
+    },
+
+    findByName : function(fragment, name) {
+        this._assertStdParams(fragment, name, "findByName", ["fragment", "name"]);
+
+        var nodeType = fragment.nodeType;
+        if (nodeType != 1 && nodeType != 9 && nodeType != 11) return null;
+
+        var ret = this._Lang.objToArray(fragment.getElementsByName(name));
+        if (fragment.name == name) ret.unshift(fragment);
+        return ret;
+    },
+
+    /**
+     * a filtered findAll for subdom treewalking
+     * (which uses browser optimizations wherever possible)
+     *
+     * @param {|Node|} rootNode the rootNode so start the scan
+     * @param filter filter closure with the syntax {boolean} filter({Node} node)
+     * @param deepScan if set to true or not set at all a deep scan is performed (for form scans it does not make much sense to deeply scan)
+     */
+    findAll : function(rootNode, filter, deepScan) {
+        this._Lang.assertType(filter, "function");
+        deepScan = !!deepScan;
+
+        if (document.createTreeWalker && NodeFilter) {
+            return this._iteratorSearchAll(rootNode, filter, deepScan);
+        } else {
+            //will not be called in dom level3 compliant browsers
+            return this._recursionSearchAll(rootNode, filter, deepScan);
+        }
+    },
+
+    /**
+     * the faster dom iterator based search, works on all newer browsers
+     * except ie8 which already have implemented the dom iterator functions
+     * of html 5 (which is pretty all standard compliant browsers)
+     *
+     * The advantage of this method is a faster tree iteration compared
+     * to the normal recursive tree walking.
+     *
+     * @param rootNode the root node to be iterated over
+     * @param filter the iteration filter
+     * @param deepScan if set to true a deep scan is performed
+     */
+    _iteratorSearchAll: function(rootNode, filter, deepScan) {
+        var retVal = [];
+        //Works on firefox and webkit, opera and ie have to use the slower fallback mechanis
+        //we have a tree walker in place this allows for an optimized deep scan
+        if (filter(rootNode)) {
+
+            retVal.push(rootNode);
+            if (!deepScan) {
+                return retVal;
+            }
+        }
+        //we use the reject mechanism to prevent a deep scan reject means any
+        //child elements will be omitted from the scan
+        var FILTER_ACCEPT = NodeFilter.FILTER_ACCEPT,
+                FILTER_SKIP = NodeFilter.FILTER_SKIP,
+                FILTER_REJECT = NodeFilter.FILTER_REJECT;
+
+        var walkerFilter = function (node) {
+            var retCode = (filter(node)) ? FILTER_ACCEPT : FILTER_SKIP;
+            retCode = (!deepScan && retCode == FILTER_ACCEPT) ? FILTER_REJECT : retCode;
+            if (retCode == FILTER_ACCEPT || retCode == FILTER_REJECT) {
+                retVal.push(node);
+            }
+            return retCode;
+        };
+
+        var treeWalker = document.createTreeWalker(rootNode, NodeFilter.SHOW_ELEMENT, walkerFilter, false);
+        //noinspection StatementWithEmptyBodyJS
+        while (treeWalker.nextNode());
+        return retVal;
+    },
+
+    /**
+     * bugfixing for ie6 which does not cope properly with setAttribute
+     */
+    setAttribute : function(node, attr, val) {
+        this._assertStdParams(node, attr, "setAttribute", ["fragment", "name"]);
+        if (!node.setAttribute) {
+            return;
+        }
+
+        if (attr === 'disabled') {
+            node.disabled = val === 'disabled' || val === 'true';
+        } else if (attr === 'checked') {
+            node.checked = val === 'checked' || val === 'on' || val === 'true';
+        } else if (attr == 'readonly') {
+            node.readOnly = val === 'readonly' || val === 'true';
+        } else {
+            node.setAttribute(attr, val);
+        }
+    },
+
+    /**
+     * fuzzy form detection which tries to determine the form
+     * an item has been detached.
+     *
+     * The problem is some Javascript libraries simply try to
+     * detach controls by reusing the names
+     * of the detached input controls. Most of the times,
+     * the name is unique in a jsf scenario, due to the inherent form mapping.
+     * One way or the other, we will try to fix that by
+     * identifying the proper form over the name
+     *
+     * We do it in several ways, in case of no form null is returned
+     * in case of multiple forms we check all elements with a given name (which we determine
+     * out of a name or id of the detached element) and then iterate over them
+     * to find whether they are in a form or not.
+     *
+     * If only one element within a form and a given identifier found then we can pull out
+     * and move on
+     *
+     * We cannot do much further because in case of two identical named elements
+     * all checks must fail and the first elements form is served.
+     *
+     * Note, this method is only triggered in case of the issuer or an ajax request
+     * is a detached element, otherwise already existing code has served the correct form.
+     *
+     * This method was added because of
+     * https://issues.apache.org/jira/browse/MYFACES-2599
+     * to support the integration of existing ajax libraries which do heavy dom manipulation on the
+     * controls side (Dojos Dijit library for instance).
+     *
+     * @param {Node} elem - element as source, can be detached, undefined or null
+     *
+     * @return either null or a form node if it could be determined
+     *
+     * TODO move this into extended and replace it with a simpler algorithm
+     */
+    fuzzyFormDetection : function(elem) {
+        var forms = document.forms, _Lang = this._Lang;
+
+        if (!forms || !forms.length) {
+            return null;
+        }
+
+        // This will not work well on portlet case, because we cannot be sure
+        // the returned form is right one.
+        //we can cover that case by simply adding one of our config params
+        //the default is the weaker, but more correct portlet code
+        //you can override it with myfaces_config.no_portlet_env = true globally
+        else if (1 == forms.length && this._RT.getGlobalConfig("no_portlet_env", false)) {
+            return forms[0];
+        }
+
+        //before going into the more complicated stuff we try the simple approach
+        var finalElem = this.byId(elem);
+        var fetchForm = _Lang.hitch(this, function(elem) {
+            //element of type form then we are already
+            //at form level for the issuing element
+            //https://issues.apache.org/jira/browse/MYFACES-2793
+
+            return (_Lang.equalsIgnoreCase(elem.tagName, "form")) ? elem :
+                    ( this.html5FormDetection(elem) || this.getParent(elem, "form"));
+        });
+
+        if (finalElem) {
+            var elemForm = fetchForm(finalElem);
+            if (elemForm) return elemForm;
+        }
+
+        /**
+         * name check
+         */
+        var foundElements = [];
+        var name = (_Lang.isString(elem)) ? elem : elem.name;
+        //id detection did not work
+        if (!name) return null;
+        /**
+         * the lesser chance is the elements which have the same name
+         * (which is the more likely case in case of a brute dom replacement)
+         */
+        var nameElems = document.getElementsByName(name);
+        if (nameElems) {
+            for (var cnt = 0; cnt < nameElems.length && foundElements.length < 2; cnt++) {
+                // we already have covered the identifier case hence we only can deal with names,
+                var foundForm = fetchForm(nameElems[cnt]);
+                if (foundForm) {
+                    foundElements.push(foundForm);
+                }
+            }
+        }
+
+        return (1 == foundElements.length ) ? foundElements[0] : null;
+    },
+
+    html5FormDetection: function(/*item*/) {
+        return null;
+    },
+
+
+    /**
+     * gets a parent of an item with a given tagname
+     * @param {Node} item - child element
+     * @param {String} tagName - TagName of parent element
+     */
+    getParent : function(item, tagName) {
+
+        if (!item) {
+            throw this._Lang.makeException(new Error(), null, null, this._nameSpace, "getParent",
+                    this._Lang.getMessage("ERR_MUST_BE_PROVIDED1", null, "_Dom.getParent", "item {DomNode}"));
+        }
+
+        var _Lang = this._Lang;
+        var searchClosure = function(parentItem) {
+            return parentItem && parentItem.tagName
+                    && _Lang.equalsIgnoreCase(parentItem.tagName, tagName);
+        };
+        try {
+            return this.getFilteredParent(item, searchClosure);
+        } finally {
+            searchClosure = null;
+            _Lang = null;
+        }
+    },
+
+    /**
+     * A parent walker which uses
+     * a filter closure for filtering
+     *
+     * @param {Node} item the root item to ascend from
+     * @param {function} filter the filter closure
+     */
+    getFilteredParent : function(item, filter) {
+        this._assertStdParams(item, filter, "getFilteredParent", ["item", "filter"]);
+
+        //search parent tag parentName
+        var parentItem = (item.parentNode) ? item.parentNode : null;
+
+        while (parentItem && !filter(parentItem)) {
+            parentItem = parentItem.parentNode;
+        }
+        return (parentItem) ? parentItem : null;
+    },
+
+    /**
+     * cross ported from dojo
+     * fetches an attribute from a node
+     *
+     * @param {String} node the node
+     * @param {String} attr the attribute
+     * @return the attributes value or null
+     */
+    getAttribute : function(/* HTMLElement */node, /* string */attr) {
+        return node.getAttribute(attr);
+    },
+
+    /**
+     * checks whether the given node has an attribute attached
+     *
+     * @param {String|Object} node the node to search for
+     * @param {String} attr the attribute to search for
+     * @true if the attribute was found
+     */
+    hasAttribute : function(/* HTMLElement */node, /* string */attr) {
+        //	summary
+        //	Determines whether or not the specified node carries a value for the attribute in question.
+        return this.getAttribute(node, attr) ? true : false;	//	boolean
+    },
+
+    /**
+     * concatenation routine which concats all childnodes of a node which
+     * contains a set of CDATA blocks to one big string
+     * @param {Node} node the node to concat its blocks for
+     */
+    concatCDATABlocks : function(/*Node*/ node) {
+        var cDataBlock = [];
+        // response may contain several blocks
+        for (var i = 0; i < node.childNodes.length; i++) {
+            cDataBlock.push(node.childNodes[i].data);
+        }
+        return cDataBlock.join('');
+    },
+
+    //all modern browsers evaluate the scripts
+    //manually this is a w3d recommendation
+    isManualScriptEval: function() {
+        return true;
+    },
+
+    /**
+     * jsf2.2
+     * checks if there is a fileupload element within
+     * the executes list
+     *
+     * @param executes the executes list
+     * @return {Boolean} true if there is a fileupload element
+     */
+    isMultipartCandidate:function (executes) {
+        if (this._Lang.isString(executes)) {
+            executes = this._Lang.strToArray(executes, /\s+/);
+        }
+
+        for (var cnt = 0, len = executes.length; cnt < len ; cnt ++) {
+            var element = this.byId(executes[cnt]);
+            var inputs = this.findByTagName(element, "input", true);
+            for (var cnt2 = 0, len2 = inputs.length; cnt2 < len2 ; cnt2++) {
+                if (this.getAttribute(inputs[cnt2], "type") == "file") return true;
+            }
+        }
+        return false;
+    },
+
+    insertFirst: function(newNode) {
+        var body = document.body;
+        if (body.childNodes.length > 0) {
+            body.insertBefore(newNode, body.firstChild);
+        } else {
+            body.appendChild(newNode);
+        }
+    },
+
+    byId: function(id) {
+        return this._Lang.byId(id);
+    },
+
+    getDummyPlaceHolder: function() {
+        this._dummyPlaceHolder = this._dummyPlaceHolder ||this.createElement("div");
+        return this._dummyPlaceHolder;
+    },
+
+    getNamedElementFromForm: function(form, elementId) {
+        return form[elementId];
+    }
+});
+
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+if (_MF_SINGLTN) {
+    _MF_SINGLTN(_PFX_UTIL + "_DomExperimental", myfaces._impl._util._Dom, /** @lends myfaces._impl._util._Dom.prototype */ {
+        constructor_:function () {
+            this._callSuper("constructor_");
+            myfaces._impl._util._Dom = this;
+        },
+
+       html5FormDetection:function (item) {
+            var browser = this._RT.browser;
+            //ie shortcut, not really needed but speeds things up
+            if (browser.isIEMobile && browser.isIEMobile <= 8) {
+                return null;
+            }
+            var elemForm = this.getAttribute(item, "form");
+            return (elemForm) ? this.byId(elemForm) : null;
+        },
+
+        getNamedElementFromForm: function(form, elementId) {
+            return form[elementId];
+        }
+    });
+}
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+if (_MF_SINGLTN) {
+    /***
+     Dom.js version for non html5 browsers
+     */
+    _MF_SINGLTN(_PFX_UTIL + "DomQuirks", myfaces._impl._util._Dom, /** @lends myfaces._impl._util._DomQuirks.prototype */ {
+
+        IE_QUIRKS_EVENTS:{
+            "onabort":true,
+            "onload":true,
+            "onunload":true,
+            "onchange":true,
+            "onsubmit":true,
+            "onreset":true,
+            "onselect":true,
+            "onblur":true,
+            "onfocus":true,
+            "onkeydown":true,
+            "onkeypress":true,
+            "onkeyup":true,
+            "onclick":true,
+            "ondblclick":true,
+            "onmousedown":true,
+            "onmousemove":true,
+            "onmouseout":true,
+            "onmouseover":true,
+            "onmouseup":true
+        },
+
+        constructor_:function () {
+
+            var b = myfaces._impl.core._Runtime.browser;
+
+            if (b.isIEMobile && b.isIE <= 6) {
+                //winmobile hates add onLoad, and checks on the construct
+                //it does not eval scripts anyway
+                myfaces.config = myfaces.config || {};
+                myfaces.config._autoeval = false;
+                return;
+            } else {
+                //for whatever reason autoeval is set here on Firefox 3.5 only
+                // could be a firebug problem, by setting setters
+                //and getters no assignment was revealed.
+                if ('undefined' != typeof myfaces.config && 'undefined' != typeof myfaces.config._autoeval) {
+                    delete myfaces.config._autoeval;
+                }
+            }
+            this._callSuper("constructor_");
+            myfaces._impl._util._Dom = this;
+
+            var _Lang = this._Lang;
+            //by w3c spec the script eval is turned off it is only
+            //on on legacy browsers
+            var scriptEval = _Lang.hitch(this, this.isManualScriptEval);
+
+            if (window) {
+                this._RT.addOnLoad(window, scriptEval);
+            }
+            //safety fallback if the window onload handler is overwritten and not chained
+            if (document.body) {
+                this._RT.addOnLoad(document.body, scriptEval);
+            }
+
+            //we register ourselves into the existing classes lazily
+            var _T = this;
+            if (myfaces._impl.core.Impl) {
+                this._RT.iterateClasses(function (proto) {
+                    if (proto._Dom) proto._Dom = _T;
+                });
+            }
+        },
+
+        /**
+         * Checks whether the browser is dom compliant.
+         * Dom compliant means that it performs the basic dom operations safely
+         * without leaking and also is able to perform a native setAttribute
+         * operation without freaking out
+         *
+         *
+         * Not dom compliant browsers are all microsoft browsers in quirks mode
+         * and ie6 and ie7 to some degree in standards mode
+         * and pretty much every browser who cannot create ranges
+         * (older mobile browsers etc...)
+         *
+         * We dont do a full browser detection here because it probably is safer
+         * to test for existing features to make an assumption about the
+         * browsers capabilities
+         */
+        isDomCompliant:function () {
+            if ('undefined' == typeof this._isCompliantBrowser) {
+                this._isCompliantBrowser = !!((window.Range
+                        && typeof Range.prototype.createContextualFragment == 'function')
+                                                            //createContextualFragment hints to a no quirks browser but we need more fallbacks
+                        || document.querySelectoryAll       //query selector all hints to html5 capabilities
+                        || document.createTreeWalker);      //treewalker is either firefox 3.5+ or ie9 standards mode
+            }
+            return this._isCompliantBrowser;
+        },
+
+        /**
+         * now to the evil browsers
+         * of what we are dealing with is various bugs
+         * first a simple replaceElement leaks memory
+         * secondly embedded scripts can be swallowed upon
+         * innerHTML, we probably could also use direct outerHTML
+         * but then we would run into the script swallow bug
+         *
+         * the entire mess is called IE6 and IE7
+         *
+         * @param item
+         * @param markup
+         */
+        _outerHTMLNonCompliant:function (item, markup) {
+
+            var b = this._RT.browser;
+
+            try {
+                //check for a subtable rendering case
+
+                var evalNodes = this._buildEvalNodes(item, markup);
+
+                if (evalNodes.length == 1) {
+                    var ret = evalNodes[0];
+                    this.replaceElement(item, evalNodes[0]);
+                    return ret;
+                } else {
+                    return this.replaceElements(item, evalNodes);
+                }
+
+            } finally {
+
+                var dummyPlaceHolder = this.getDummyPlaceHolder();
+                //now that Microsoft has finally given
+                //ie a working gc in 8 we can skip the costly operation
+                if (b.isIE && b.isIE < 8) {
+                    this._removeChildNodes(dummyPlaceHolder, false);
+                }
+                dummyPlaceHolder.innerHTML = "";
+            }
+
+        },
+
+        replaceElement:function (item, evalNode) {
+
+            var _Browser = this._RT.browser;
+            if (!_Browser.isIE || _Browser.isIE >= 8) {
+                //standards conform no leaking browser
+                item.parentNode.replaceChild(evalNode, item);
+            } else {
+                this._callSuper("replaceElement", item, evalNode);
+            }
+        },
+
+        /**
+         * builds the ie nodes properly in a placeholder
+         * and bypasses a non script insert bug that way
+         * @param markup the marku code
+         */
+        _buildNodesNonCompliant:function (markup) {
+
+            //now to the non w3c compliant browsers
+            //http://blogs.perl.org/users/clinton_gormley/2010/02/forcing-ie-to-accept-script-tags-in-innerhtml.html
+            //we have to cope with deficiencies between ie and its simulations in this case
+            var probe = this.getDummyPlaceHolder();//document.createElement("div");
+
+            probe.innerHTML = "<table><tbody><tr><td><div></div></td></tr></tbody></table>";
+
+            //we have customers using html unit, this has a bug in the table resolution
+            //hence we determine the depth dynamically
+            var depth = this._determineDepth(probe);
+
+            this._removeChildNodes(probe, false);
+            probe.innerHTML = "";
+
+            var dummyPlaceHolder = this.getDummyPlaceHolder();//document.createElement("div");
+
+            //fortunately a table element also works which is less critical than form elements regarding
+            //the inner content
+            dummyPlaceHolder.innerHTML = "<table><tbody><tr><td>" + markup + "</td></tr></tbody></table>";
+            var evalNodes = dummyPlaceHolder;
+
+            for (var cnt = 0; cnt < depth; cnt++) {
+                evalNodes = evalNodes.childNodes[0];
+            }
+            var ret = (evalNodes.parentNode) ? this.detach(evalNodes.parentNode.childNodes) : null;
+
+            if ('undefined' == typeof evalNodes || null == evalNodes) {
+                //fallback for htmlunit which should be good enough
+                //to run the tests, maybe we have to wrap it as well
+                dummyPlaceHolder.innerHTML = "<div>" + markup + "</div>";
+                //note this is triggered only in htmlunit no other browser
+                //so we are save here
+                //TODO Fix this (probaby ret is needed here, check the history)
+                evalNodes = this.detach(dummyPlaceHolder.childNodes[0].childNodes);
+            }
+
+            this._removeChildNodes(dummyPlaceHolder, false);
+            //ie fix any version, ie does not return true javascript arrays so we have to perform
+            //a cross conversion
+            return ret;
+
+        },
+
+        _determineDepth:function (probe) {
+            var depth = 0;
+            var newProbe = probe;
+            for (; newProbe &&
+                           newProbe.childNodes &&
+                           newProbe.childNodes.length &&
+                           newProbe.nodeType == 1; depth++) {
+                newProbe = newProbe.childNodes[0];
+            }
+            return depth;
+        },
+
+        //now to another nasty issue:
+        //for ie we have to walk recursively over all nodes:
+        //http://msdn.microsoft.com/en-us/library/bb250448%28VS.85%29.aspx
+        //http://weblogs.java.net/blog/driscoll/archive/2009/11/13/ie-memory-management-and-you
+        //http://home.orange.nl/jsrosman/
+        //http://www.quirksmode.org/blog/archives/2005/10/memory_leaks_li.html
+        //http://www.josh-davis.org/node/7
+        _removeNode:function (node, breakEventsOpen) {
+            if (!node) return;
+            var b = this._RT.browser;
+            if (this.isDomCompliant()) {
+                //recursive descension only needed for old ie versions
+                //all newer browsers cleanup the garbage just fine without it
+                //thank you
+                if ('undefined' != typeof node.parentNode && null != node.parentNode) //if the node has a parent
+                    node.parentNode.removeChild(node);
+                return;
+            }
+
+            //now to the browsers with non working garbage collection
+            this._removeChildNodes(node, breakEventsOpen);
+
+            try {
+                //outer HTML setting is only possible in earlier IE versions all modern browsers throw an exception here
+                //again to speed things up we precheck first
+                if (!this._isTableElement(node)) {
+                    //we do not do a table structure innnerhtml on table elements except td
+                    //htmlunit rightfully complains that we should not do it
+                    node.innerHTML = "";
+                }
+                if (b.isIE && 'undefined' != typeof node.outerHTML) {//ie8+ check done earlier we skip it here
+                    node.outerHTML = '';
+                } else {
+                    node = this.detach(node)[0];
+                }
+                if (!b.isIEMobile) {
+                    delete node;
+                }
+            } catch (e) {
+                //on some elements we might not have covered by our table check on the outerHTML
+                // can fail we skip those in favor of stability
+                try {
+                    // both innerHTML and outerHTML fails when <tr> is the node, but in that case
+                    // we need to force node removal, otherwise it will be on the tree (IE 7 IE 6)
+                    this.detach(node);
+                    if (!b.isIEMobile) {
+                        delete node;
+                    }
+                } catch (e1) {
+                }
+            }
+        },
+
+        /**
+         * recursive delete child nodes
+         * node, this method only makes sense in the context of IE6 + 7 hence
+         * it is not exposed to the public API, modern browsers
+         * can garbage collect the nodes just fine by doing the standard removeNode method
+         * from the dom API!
+         *
+         * @param node  the node from which the childnodes have to be deletd
+         * @param breakEventsOpen if set to true a standard events breaking is performed
+         */
+        _removeChildNodes:function (node, breakEventsOpen) {
+            if (!node) return;
+
+            //node types which cannot be cleared up by normal means
+            var disallowedNodes = this.TABLE_ELEMS;
+
+            //for now we do not enable it due to speed reasons
+            //normally the framework has to do some event detection
+            //which we cannot do yet, I will dig for options
+            //to enable it in a speedly manner
+            //ie7 fixes this area anyway
+            //this.breakEvents(node);
+
+            var b = this._RT.browser;
+            if (breakEventsOpen) {
+                this.breakEvents(node);
+            }
+
+            for (var cnt = node.childNodes.length - 1; cnt >= 0; cnt -= 1) {
+                var childNode = node.childNodes[cnt];
+                //we cannot use our generic recursive tree walking due to the needed head recursion
+                //to clean it up bottom up, the tail recursion we were using in the search either would use more time
+                //because we had to walk and then clean bottom up, so we are going for a direct head recusion here
+                if ('undefined' != typeof childNode.childNodes && node.childNodes.length)
+                    this._removeChildNodes(childNode);
+                try {
+                    var nodeName = (childNode.nodeName || childNode.tagName) ? (childNode.nodeName || childNode.tagName).toLowerCase() : null;
+                    //ie chokes on clearing out table inner elements, this is also covered by our empty
+                    //catch block, but to speed things up it makes more sense to precheck that
+                    if (!disallowedNodes[nodeName]) {
+                        //outer HTML setting is only possible in earlier IE versions all modern browsers throw an exception here
+                        //again to speed things up we precheck first
+                        if (!this._isTableElement(childNode)) {    //table elements cannot be deleted
+                            childNode.innerHTML = "";
+                        }
+                        if (b.isIE && b.isIE < 8 && 'undefined' != typeof childNode.outerHTML) {
+                            childNode.outerHTML = '';
+                        } else {
+                            node.removeChild(childNode);
+                        }
+                        if (!b.isIEMobile) {
+                            delete childNode;
+                        }
+                    }
+                } catch (e) {
+                    //on some elements the outerHTML can fail we skip those in favor
+                    //of stability
+
+                }
+            }
+        },
+        /**
+         * cross ported from dojo
+         * fetches an attribute from a node
+         *
+         * @param {String} node the node
+         * @param {String} attr the attribute
+         * @return the attributes value or null
+         */
+        getAttribute:function (/* HTMLElement */node, /* string */attr) {
+            //	summary
+            //	Returns the value of attribute attr from node.
+            node = this.byId(node);
+            // FIXME: need to add support for attr-specific accessors
+            if ((!node) || (!node.getAttribute)) {
+                // if(attr !== 'nwType'){
+                //	alert("getAttr of '" + attr + "' with bad node");
+                // }
+                return null;
+            }
+            var ta = typeof attr == 'string' ? attr : new String(attr);
+
+            // first try the approach most likely to succeed
+            var v = node.getAttribute(ta.toUpperCase());
+            if ((v) && (typeof v == 'string') && (v != "")) {
+                return v;	//	string
+            }
+
+            // try returning the attributes value, if we couldn't get it as a string
+            if (v && v.value) {
+                return v.value;	//	string
+            }
+
+            // this should work on Opera 7, but it's a little on the crashy side
+            if ((node.getAttributeNode) && (node.getAttributeNode(ta))) {
+                return (node.getAttributeNode(ta)).value;	//	string
+            } else if (node.getAttribute(ta)) {
+                return node.getAttribute(ta);	//	string
+            } else if (node.getAttribute(ta.toLowerCase())) {
+                return node.getAttribute(ta.toLowerCase());	//	string
+            }
+            return null;	//	string
+        },
+
+        /**
+         * bugfixing for ie6 which does not cope properly with setAttribute
+         */
+        setAttribute:function (node, attr, val) {
+
+            this._assertStdParams(node, attr, "setAttribute");
+
+            //quirks mode and ie7 mode has the attributes problems ie8 standards mode behaves like
+            //a good citizen
+            var _Browser = this._RT.browser;
+            //in case of ie > ie7 we have to check for a quirks mode setting
+            if (!_Browser.isIE || _Browser.isIE > 7 && this.isDomCompliant()) {
+                this._callSuper("setAttribute", node, attr, val);
+                return;
+            }
+
+            /*
+             Now to the broken browsers IE6+.... ie7 and ie8 quirks mode
+
+             we deal mainly with three problems here
+             class and for are not handled correctly
+             styles are arrays and cannot be set directly
+             and javascript events cannot be set via setAttribute as well!
+
+             or in original words of quirksmode.org ... this is a mess!
+
+             Btw. thank you Microsoft for providing all necessary tools for free
+             for being able to debug this entire mess in the ie rendering engine out
+             (which is the Microsoft ie vms, developers toolbar, Visual Web Developer 2008 express
+             and the ie8 8 developers toolset!)
+
+             also thank you http://www.quirksmode.org/
+             dojotoolkit.org and   //http://delete.me.uk/2004/09/ieproto.html
+             for additional information on this mess!
+
+             The lowest common denominator tested within this code
+             is IE6, older browsers for now are legacy!
+             */
+            attr = attr.toLowerCase();
+
+            if (attr === "class") {
+                //setAttribute does not work for winmobile browsers
+                //firect calls work
+                node.className = val;
+            } else if (attr === "name") {
+                //the ie debugger fails to assign the name via setAttr
+                //in quirks mode
+                node[attr] = val;
+            } else if (attr === "for") {
+                if (!_Browser.isIEMobile || _Browser.isIEMobile >= 7) {
+                    node.setAttribute("htmlFor", val);
+                } else {
+                    node.htmlFor = val;
+                }
+            } else if (attr === "style") {
+                node.style.cssText = val;
+            } else {
+                //check if the attribute is an event, since this applies only
+                //to quirks mode of ie anyway we can live with the standard html4/xhtml
+                //ie supported events
+                if (this.IE_QUIRKS_EVENTS[attr]) {
+                    if (this._Lang.isString(attr)) {
+                        var c = document.body.appendChild(document.createElement('span'));
+                        try {
+                            c.innerHTML = '<span ' + attr + '="' + val + '"/>';
+                            node[attr] = c.firstChild[attr];
+                        } finally {
+                            document.body.removeChild(c);
+                        }
+                    }
+                } else {
+                    //unknown cases we try to catch them via standard setAttributes
+                    if (!_Browser.isIEMobile || _Browser.isIEMobile >= 7) {
+                        node.setAttribute(attr, val);
+                    } else {
+                        node[attr] = val;
+                    }
+                }
+            }
+        },
+
+        getDummyPlaceHolder:function () {
+            this._callSuper("getDummyPlaceHolder");
+
+            //ieMobile in its 6.1-- incarnation cannot handle innerHTML detached objects so we have
+            //to attach the dummy placeholder, we try to avoid it for
+            //better browsers so that we do not have unecessary dom operations
+            if (this._RT.browser.isIEMobile && created) {
+                this.insertFirst(this._dummyPlaceHolder);
+
+                this.setAttribute(this._dummyPlaceHolder, "style", "display: none");
+
+            }
+
+            return this._dummyPlaceHolder;
+        },
+
+        /**
+         * classical recursive way which definitely will work on all browsers
+         * including the IE6
+         *
+         * @param rootNode the root node
+         * @param filter the filter to be applied to
+         * @param deepScan if set to true a deep scan is performed
+         */
+        _recursionSearchAll:function (rootNode, filter, deepScan) {
+            var ret = [];
+            //fix the value to prevent undefined errors
+
+            if (filter(rootNode)) {
+                ret.push(rootNode);
+                if (!deepScan) return ret;
+            }
+
+            //
+            if (!rootNode.childNodes) {
+                return ret;
+            }
+
+            //subfragment usecases
+
+            var retLen = ret.length;
+            var childLen = rootNode.childNodes.length;
+            for (var cnt = 0; (deepScan || retLen == 0) && cnt < childLen; cnt++) {
+                ret = ret.concat(this._recursionSearchAll(rootNode.childNodes[cnt], filter, deepScan));
+            }
+            return ret;
+        },
+
+        /**
+         * break the standard events from an existing dom node
+         * (note this method is not yet used, but can be used
+         * by framework authors to get rid of ie circular event references)
+         *
+         * another way probably would be to check all attributes of a node
+         * for a function and if one is present break it by nulling it
+         * I have to do some further investigation on this.
+         *
+         * The final fix is to move away from ie6 at all which is the root cause of
+         * this.
+         *
+         * @param node the node which has to be broken off its events
+         */
+        breakEvents:function (node) {
+            if (!node) return;
+            var evtArr = this.IE_QUIRKS_EVENTS;
+            for (var key in evtArr) {
+                if (!evtArr.hasOwnProperty(key)) continue;
+                if (key != "onunload" && node[key]) {
+                    node[key] = null;
+                }
+            }
+        },
+
+        isManualScriptEval:function () {
+
+            if (!this._Lang.exists(myfaces, "config._autoeval")) {
+
+                //now we rely on the document being processed if called for the first time
+                var evalDiv = document.createElement("div");
+                this._Lang.reserveNamespace("myfaces.config._autoeval");
+                //null not swallowed
+                myfaces.config._autoeval = false;
+
+                var markup = "<script type='text/javascript'> myfaces.config._autoeval = true; </script>";
+                //now we rely on the same replacement mechanisms as outerhtml because
+                //some browsers have different behavior of embedded scripts in the contextualfragment
+                //or innerhtml case (opera for instance), this way we make sure the
+                //eval detection is covered correctly
+                this.setAttribute(evalDiv, "style", "display:none");
+
+                //it is less critical in some browsers (old ie versions)
+                //to append as first element than as last
+                //it should not make any difference layoutwise since we are on display none anyway.
+                this.insertFirst(evalDiv);
+
+                //we remap it into a real boolean value
+                if (this.isDomCompliant()) {
+                    this._outerHTMLCompliant(evalDiv, markup);
+                } else {
+                    //will not be called placeholder for quirks class
+                    this._outerHTMLNonCompliant(evalDiv, markup);
+                }
+
+
+            }
+
+            return  !myfaces.config._autoeval;
+        },
+
+        getNamedElementFromForm:function (form, elementName) {
+			var browser = this._RT.browser;
+            if(browser.isIE && browser.isIE < 8) {
+                if(!form.elements) return null;
+                for(var cnt = 0, l = form.elements.length; cnt < l; cnt ++) {
+                    var element = form.elements[cnt];
+                    if(element.name == elementName) {
+                        return element;
+                    }
+                }
+                return null;
+            } else {
+                return form[elementName];
+            }
+        }
+
+    });
+
+}
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name _HtmlStripper
+ * @memberOf myfaces._impl._util
+ * @extends myfaces._impl.core._Runtime
+ * @description
+ *  Fallback routine if the browser embedded xml parser fails on the document
+ *  This fallback is not failsafe but should give enough cover to handle all cases
+ */
+
+/** @namespace myfaces._impl._util._HtmlStripper */
+_MF_CLS(_PFX_UTIL + "_HtmlStripper", _MF_OBJECT, /** @lends myfaces._impl._util._HtmlStripper.prototype */ {
+
+    /**
+     * main parse routine parses the document for a given tag name
+     *
+     *
+     * @param theString  the markup string to be parsed
+     * @param tagNameStart the tag name to be parsed for
+     */
+    parse : function(theString, tagNameStart) {
+
+        var BEGIN_TAG = "html",
+                _tagStart = -1,
+                _tagEnd = -1,
+                _contentStart = -1,
+                _contentEnd = -1,
+                _tokenPos = 0,
+                _tokenForward = 1,
+                tagNameStart = (!tagNameStart) ? BEGIN_TAG : tagNameStart;
+
+        var proposedTagStartPos = theString.indexOf("<" + tagNameStart);
+        var _T = this;
+
+        //we use closures instead of private methods to improve the compressability
+
+        var isValidPositionCombination = function(pos1, pos2, pos3, pos4) {
+            return pos1 <= pos2 && pos3 <= pos4;
+        };
+
+        /**
+         * trace for a forward comment
+         *
+         * @param theStr the string to be checked
+         * @param tagPos the tag position from which the check onwards has to be perfomed
+         * @return true in case a comment is found
+         */
+        var checkForwardForComment = function(theStr, tagPos) {
+            var toCheck = theStr.substring(tagPos),
+                    indexOf = _T._Lang.hitch(toCheck, toCheck.indexOf),
+                    firstBeginComment = indexOf("<!--"),
+                    firstEndComment = indexOf("-->"),
+
+                    firstBeginCDATA = indexOf("<[CDATA["),
+                    firstEndCDATA = indexOf("]]>");
+
+            if (isValidPositionCombination(firstBeginComment, firstEndComment, firstBeginCDATA, firstEndCDATA)) {
+                return true;
+            }
+
+            return firstBeginComment <= firstEndComment && firstBeginCDATA <= firstEndCDATA;
+        };
+
+        /**
+         * check backwards for a comment
+         *
+         * @param theStr the check string
+         * @param tagPos the tag position from which the check should be performed
+         * @return true in case a comment is found
+         */
+        var checkBackForComment = function(theStr, tagPos) {
+            var toCheck = theStr.substring(tagPos),
+                    indexOf = _T._Lang.hitch(toCheck, toCheck.indexOf),
+                    lastBeginComment = indexOf("<!--"),
+                    lastEndComment = indexOf("-->"),
+                    lastBeginCDATA = indexOf("<[CDATA["),
+                    lastEndCDATA = indexOf("]]>");
+
+            if (isValidPositionCombination(lastBeginComment, lastEndComment, lastBeginCDATA, lastEndCDATA)) {
+                //TODO we have to handle the embedded cases, for now we leave them out
+                return true;
+            }
+        };
+
+        //no need for ll parsing a handful of indexofs instead of slower regepx suffices
+        var theSubStr = this._Lang.hitch(theString, theString.substring);
+        while (_contentStart == -1 && proposedTagStartPos != -1) {
+            if (checkBackForComment(theString, proposedTagStartPos)) {
+                _tagStart = proposedTagStartPos;
+                _contentStart = proposedTagStartPos + theSubStr(proposedTagStartPos).indexOf(">") + 1;
+            }
+            proposedTagStartPos = theSubStr(proposedTagStartPos + tagNameStart.length + 2).indexOf("<" + tagNameStart);
+        }
+
+        var proposedEndTagPos = theString.lastIndexOf("</" + tagNameStart);
+        while (_contentEnd == -1 && proposedEndTagPos > 0) {
+            if (checkForwardForComment(theString, proposedEndTagPos)) {
+                _tagEnd = proposedEndTagPos;
+                _contentEnd = proposedEndTagPos;
+            }
+            proposedTagStartPos = theSubStr(proposedTagStartPos - tagNameStart.length - 2).lastIndexOf("</" + tagNameStart);
+        }
+        if (_contentStart != -1 && _contentEnd != -1) {
+            return theSubStr(_contentStart, _contentEnd);
+        }
+        return null;
+    }
+});
+
+
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * legacy code to enable various aspects
+ * of myfaces, used to be rendered inline
+ * for jsf 2.0 we can externalized it into its own custom resource
+ */
+
+(!window.myfaces) ? window.myfaces = {} : null;
+if (!myfaces.oam) {
+    myfaces.oam = new function() {
+
+        /**
+         * sets a hidden input field
+         * @param formname the formName
+         * @param name the hidden field
+         * @param value the value to be rendered
+         */
+        this.setHiddenInput = function(formname, name, value) {
+            var form = document.forms[formname];
+            if (typeof form == 'undefined') {
+                form = document.getElementById(formname);
+            }
+
+            if (typeof form.elements[name] != 'undefined' && (form.elements[name].nodeName == 'INPUT' || form.elements[name].nodeName == 'input')) {
+                form.elements[name].value = value;
+            }
+            else {
+                var newInput = document.createElement('input');
+                newInput.setAttribute('type', 'hidden');
+                newInput.setAttribute('id', name);
+                newInput.setAttribute('name', name);
+                newInput.setAttribute('value', value);
+                form.appendChild(newInput);
+            }
+        };
+
+        /**
+         * clears a hidden input field
+         *
+         * @param formname formName for the input
+         * @param name the name of the input field
+         * @param value the value to be cleared
+         */
+        this.clearHiddenInput = function(formname, name, value) {
+            var form = document.forms[formname];
+
+            if (typeof form == 'undefined') {
+                form = document.getElementById(formname);
+            }
+
+            var hInput = form.elements[name];
+            if (typeof hInput != 'undefined') {
+                form.removeChild(hInput);
+            }
+        };
+
+        /**
+         * does special form submit remapping
+         * remaps the issuing command link into something
+         * the decode of the command link on the server can understand
+         *
+         * @param formName
+         * @param linkId
+         * @param target
+         * @param params
+         */
+        this.submitForm = function(formName, linkId, target, params) {
+
+            var clearFn = 'clearFormHiddenParams_' + formName.replace(/-/g, '\$:').replace(/:/g, '_');
+            if (typeof window[clearFn] == 'function') {
+                window[clearFn](formName);
+            }
+
+            var form = document.forms[formName];
+            if (typeof form == 'undefined') {
+                form = document.getElementById(formName);
+            }
+
+            //autoscroll code
+            if (myfaces.core.config.autoScroll && typeof window.getScrolling != 'undefined') {
+                myfaces.oam.setHiddenInput(formName, 'autoScroll', getScrolling());
+            }
+
+            if (myfaces.core.config.ieAutoSave) {
+                var agentString = navigator.userAgent.toLowerCase();
+                var version = navigator.appVersion;
+                if (agentString.indexOf('msie') != -1) {
+                    if (!(agentString.indexOf('ppc') != -1 && agentString.indexOf('windows ce') != -1 && version >= 4.0)) {
+                        window.external.AutoCompleteSaveForm(form);
+                    }
+                }
+            }
+
+            var oldTarget = form.target;
+            if (target != null) {
+                form.target = target;
+            }
+            if ((typeof params != 'undefined') && params != null) {
+                for (var i = 0, param; (param = params[i]); i++) {
+                    myfaces.oam.setHiddenInput(formName, param[0], param[1]);
+                }
+
+            }
+
+            myfaces.oam.setHiddenInput(formName, formName + ':' + '_idcl', linkId);
+
+            if (form.onsubmit) {
+                var result = form.onsubmit();
+                if ((typeof result == 'undefined') || result) {
+                    try {
+                        form.submit();
+                    }
+                    catch(e) {
+                    }
+                }
+
+            }
+            else {
+                try {
+                    form.submit();
+                }
+                catch(e) {
+                }
+            }
+
+            form.target = oldTarget;
+            if ((typeof params != 'undefined') && params != null) {
+
+                for (var i = 0, param; (param = params[i]); i++) {
+                    myfaces.oam.clearHiddenInput(formName, param[0], param[1]);
+                }
+
+            }
+
+            myfaces.oam.clearHiddenInput(formName, formName + ':' + '_idcl', linkId);
+            return false;
+        };
+    }
+}
+
+//reserve a cofig namespace for impl related stuff
+(!myfaces.core) ? myfaces.core = {} : null;
+(!myfaces.core.config) ? myfaces.core.config = {} : null;
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @class
+ * @name _AjaxUtils
+ * @memberOf myfaces._impl.xhrCore
+ * @description
+ *
+ * A set of helper routines which are utilized within our Ajax subsystem and nowhere else
+ *
+ * TODO move this into a singleton, the current structure is
+ * still a j4fry legacy we need to get rid of it in the long run
+ */
+_MF_SINGLTN(_PFX_XHR+"_AjaxUtils", _MF_OBJECT,
+/** @lends myfaces._impl.xhrCore._AjaxUtils.prototype */
+{
+
+
+    /**
+     * determines fields to submit
+     * @param {Object} targetBuf - the target form buffer receiving the data
+     * @param {Node} parentItem - form element item is nested in
+     * @param {Array} partialIds - ids fo PPS
+     */
+    encodeSubmittableFields : function(targetBuf,
+                                       parentItem, partialIds) {
+            if (!parentItem) throw "NO_PARITEM";
+            if (partialIds ) {
+                this.encodePartialSubmit(parentItem, false, partialIds, targetBuf);
+            } else {
+                // add all nodes
+                var eLen = parentItem.elements.length;
+                for (var e = 0; e < eLen; e++) {
+                    this.encodeElement(parentItem.elements[e], targetBuf);
+                } // end of for (formElements)
+            }
+
+    },
+
+     /**
+     * appends the issuing item if not given already
+     * @param item
+     * @param targetBuf
+     */
+    appendIssuingItem: function (item, targetBuf) {
+        // if triggered by a Button send it along
+        if (item && item.type && item.type.toLowerCase() == "submit") {
+            targetBuf.append(item.name, item.value);
+        }
+    },
+
+
+    /**
+     * encodes a single input element for submission
+     *
+     * @param {Node} element - to be encoded
+     * @param {} targetBuf - a target array buffer receiving the encoded strings
+     */
+    encodeElement : function(element, targetBuf) {
+
+        //browser behavior no element name no encoding (normal submit fails in that case)
+        //https://issues.apache.org/jira/browse/MYFACES-2847
+        if (!element.name) {
+            return;
+        }
+
+        var _RT = this._RT;
+        var name = element.name;
+        var tagName = element.tagName.toLowerCase();
+        var elemType = element.type;
+        if (elemType != null) {
+            elemType = elemType.toLowerCase();
+        }
+
+        // routine for all elements
+        // rules:
+        // - process only inputs, textareas and selects
+        // - elements muest have attribute "name"
+        // - elements must not be disabled
+        if (((tagName == "input" || tagName == "textarea" || tagName == "select") &&
+                (name != null && name != "")) && !element.disabled) {
+
+            // routine for select elements
+            // rules:
+            // - if select-one and value-Attribute exist => "name=value"
+            // (also if value empty => "name=")
+            // - if select-one and value-Attribute don't exist =>
+            // "name=DisplayValue"
+            // - if select multi and multple selected => "name=value1&name=value2"
+            // - if select and selectedIndex=-1 don't submit
+            if (tagName == "select") {
+                // selectedIndex must be >= 0 sein to be submittet
+                if (element.selectedIndex >= 0) {
+                    var uLen = element.options.length;
+                    for (var u = 0; u < uLen; u++) {
+                        // find all selected options
+                        //var subBuf = [];
+                        if (element.options[u].selected) {
+                            var elementOption = element.options[u];
+                            targetBuf.append(name, (elementOption.getAttribute("value") != null) ?
+                                    elementOption.value : elementOption.text);
+                        }
+                    }
+                }
+            }
+
+            // routine for remaining elements
+            // rules:
+            // - don't submit no selects (processed above), buttons, reset buttons, submit buttons,
+            // - submit checkboxes and radio inputs only if checked
+            if ((tagName != "select" && elemType != "button"
+                    && elemType != "reset" && elemType != "submit" && elemType != "image")
+                    && ((elemType != "checkbox" && elemType != "radio") || element.checked)) {
+                if ('undefined' != typeof element.files && element.files != null && _RT.getXHRLvl() >= 2 && element.files.length) {
+                    //xhr level2
+                    targetBuf.append(name, element.files[0]);
+                } else {
+                    targetBuf.append(name, element.value);
+                }
+            }
+
+        }
+    }
+});
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/** @namespace myfaces._impl.xhrCore._AjaxRequestQueue */
+_MF_CLS(_PFX_XHR + "_AjaxRequestQueue", myfaces._impl._util._Queue, /** @lends  myfaces._impl.xhrCore._AjaxRequestQueue.prototype */ {
+
+    /**
+     * a pointer towards the currently processed
+     * request in our queue
+     */
+    _curReq : null,
+
+    /**
+     * delay request, then call enqueue
+     * @param {Object} request (myfaces._impl.xhrCore._AjaxRequest) request to send
+     */
+    enqueue : function(request) {
+
+        if (this._curReq == null) {
+            this._curReq = request;
+            this._curReq.send();
+        } else {
+            this._callSuper("enqueue", request);
+            if (request._queueSize != this._size) {
+                this.setQueueSize(request._queueSize);
+            }
+        }
+
+    },
+
+    /**
+     * process queue, send request, if exists
+     */
+    processQueue: function() {
+        this._curReq = this.dequeue();
+        if (this._curReq) {
+            this._curReq.send();
+        }
+    },
+
+    /**
+     * cleanup queue
+     */
+    cleanup: function() {
+        this._curReq = null;
+        this._callSuper("cleanup");
+    }
+});
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @memberOf myfaces._impl.xhrCore
+ * @namespace
+ * @name engine
+ */
+
+/**
+ * @class
+ * @name XhrConst
+ * @memberOf myfaces._impl.xhrCore.engine
+ */
+_MF_SINGLTN(_PFX_XHR+"engine.XhrConst", Object,
+        /** @lends myfaces._impl.xhrCore.engine.XhrConst.prototype */
+        {
+            READY_STATE_UNSENT:     0,
+            READY_STATE_OPENED:     1,
+            READY_STATE_HEADERS_RECEIVED: 2,
+            READY_STATE_LOADING:    3,
+            READY_STATE_DONE:       4,
+
+            STATUS_OK_MINOR:        200,
+            STATUS_OK_MAJOR:        300,
+
+            constructor_: function() {
+            }
+        });
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name FormData
+ * @memberOf myfaces._impl.xhrCore.engine
+ * @description
+ *
+ * html5 formdata object emulation for the iframe
+ */
+_MF_CLS(_PFX_XHR+"engine.FormData", Object,
+        /** @lends myfaces._impl.xhrCore.engine.FormData.prototype */
+        {
+            form: null,
+            viewstate: null,
+            _appendedParams: {},
+
+            constructor_: function(form) {
+                this.form = form;
+            },
+
+            append: function(key, value) {
+                this._appendedParams[key] = true;
+                if (this.form) {
+                    this._appendHiddenValue(key, value);
+                }
+            },
+
+            _finalize: function() {
+                this._removeAppendedParams();
+            },
+
+            _appendHiddenValue: function(key, value) {
+                if ('undefined' == typeof value) {
+                    return;
+                }
+                var _Dom = myfaces._impl._util._Dom;
+                var input = _Dom.createElement("input", {
+                    "type": "hidden", "name": key, "style": "display:none", "value": value
+                });
+
+                this.form.appendChild(input);
+            },
+
+            _removeAppendedParams: function() {
+                if (!this.form) return;
+                for (var cnt = this.form.elements.length - 1; cnt >= 0; cnt--) {
+                    var elem = this.form.elements[cnt];
+                    if (this._appendedParams[elem.name] && elem.type == "hidden") {
+                        elem.parentNode.removeChild(elem);
+                        delete elem;
+                    }
+                }
+                this._appendedParams = {};
+            }
+
+        });
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name BaseRequest
+ * @memberOf myfaces._impl.xhrCore.engine
+ * @extends myfaces._impl.core.Object
+ * @description
+ * Abstract Base for all classes which simulate the xhr level2 object
+ * with a different transport
+ *
+ * <h3>Every class inheriting the interface must expose following methods and attributes</h3>
+ *
+ * <ul>
+ *      <li>open(method, url, async)</li>
+ *      <li>send(formData)</li>
+ *      <li>setRequestHeader(key, value)</li>
+ *      <li>abort()</li>
+ *      <li>onloadstart()</li>
+ *      <li>onprogress()</li>
+ *      <li>onabort()</li>
+ *      <li>onerror()</li>
+ *      <li>onload()</li>
+ *      <li>ontimeout()</li>
+ *      <li>onloadend()</li>
+ *      <li>onreadystatechange()</li>
+ * </ul>
+ * <h3>following attributes are supported</h3>
+ * <ul>
+ *      <li>async</li>
+ *      <li>url</li>
+ *      <li>method</li>
+ *      <li>timeout</li>
+ *      <li>response</li>
+ *      <li>responseText</li>
+ *      <li>responseXML</li>
+ *      <li>status</li>
+ *      <li>statusText</li>
+ * </ul>
+ */
+_MF_CLS(_PFX_XHR + "engine.BaseRequest", _MF_OBJECT, /** @lends myfaces._impl.xhrCore.engine.BaseRequest.prototype */ {
+    /*standard attributes*/
+
+    /**
+     * timeout attribute with a timeout for the request in miliseconds
+     */
+    timeout:0,
+    /**
+     * readonly ready stte attribute
+     */
+    readyState:0,
+    /**
+     * send method, allowed values POST and GET
+     */
+    method:"POST",
+    /**
+     * the url for the call
+     */
+    url:null,
+    /**
+     * asynchronous request, if set to true then the request happens
+     * asynchronously, if possible.
+     */
+    async:true,
+    /**
+     * read only response object, containing the response as json/dom representation
+     */
+    response:null,
+    /**
+     * read only plain text representation of the response
+     */
+    responseText:null,
+    /**
+     * xml dom readonly representation of the response
+     */
+    responseXML:null,
+    /**
+     * readonly status code of the response
+     */
+    status:null,
+    /**
+     * readonly status text of the response
+     */
+    statusText:null,
+
+    constructor_:function (params) {
+        this._callSuper("constructor_", params);
+        this._initDefaultFinalizableFields();
+
+        this._XHRConst = myfaces._impl.xhrCore.engine.XhrConst;
+        this._Lang.applyArgs(this, params);
+    },
+
+    //open send, abort etc... abstract
+    /**
+     * opens the transport element
+     * @param {String} method transport method allowed values <i>POST</i> and <i>GET</i>
+     * @param {String} url optional url
+     * @param {Boolean} async optional param asynchronous transmission if set to true
+     */
+    open:function (method, url, async) {
+        this._implementThis();
+    },
+    /**
+     * send method
+     * @param {Object} formData data to be posted within the request
+     */
+    send:function (formData) {
+        this._implementThis();
+    },
+    /**
+     * appends a key value pair to the request header if possible
+     * @param {String} key the key of the request header entry
+     * @param {String} value  the value for the key
+     */
+    setRequestHeader:function (key, value) {
+        this._implementThis();
+    },
+    /**
+     * aborts the transmission
+     */
+    abort:function () {
+        this._implementThis();
+    },
+
+    //empty implementations for the callback handlers
+    /**
+     * callback once the transmission has started
+     * @param evt
+     */
+    onloadstart:function (evt) {
+    },
+    onprogress:function (evt) {
+    },
+    onabort:function (evt) {
+    },
+    onerror:function (evt) {
+    },
+    onload:function (evt) {
+    },
+    ontimeout:function (evt) {
+    },
+    onloadend:function (evt) {
+    },
+    onreadystatechange:function (evt) {
+    },
+
+    _implementThis:function () {
+        throw Error("the function needs to be implemented");
+    }
+});
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * @class
+ * @name Xhr1
+ * @memberOf myfaces._impl.xhrCore.engine
+ * @extends myfaces._impl.xhrCore.engine.BaseRequest
+ * @description
+ *
+ * wrapper for an xhr level1 object with all its differences
+ * it emulates the xhr level2 api which is way simpler than the level1 api
+ */
+
+_MF_CLS(_PFX_XHR + "engine.Xhr1", myfaces._impl.xhrCore.engine.BaseRequest, /** @lends myfaces._impl.xhrCore.engine.Xhr1.prototype */ {
+
+    _xhrObject: null,
+    _timeoutTimer: null,
+
+    constructor_: function(params) {
+        //the constructor is empty due to the original xhr object not having anything
+
+        this._callSuper("constructor_", params);
+        this._initDefaultFinalizableFields();
+
+        this._XHRConst = myfaces._impl.xhrCore.engine.XhrConst;
+        this._Lang.applyArgs(this, params);
+    },
+
+    // void open(DOMString method, DOMString url, boolean async);
+    open: function(method, url, async) {
+
+        var xhr = this._xhrObject;
+        xhr.onreadystatechange = this._Lang.hitch(this, this.onreadystatechange);
+        this.method = method || this.method;
+        this.url = url || this.url;
+        this.async = ('undefined' != typeof async) ? async : this.async;
+        xhr.open(this.method, this.url, this.async);
+    },
+
+    send: function(formData) {
+
+        var myevt = {};
+
+        this._addProgressAttributes(myevt, 20, 100);
+        this.onloadstart(myevt);
+        this.onprogress(myevt);
+        this._startTimeout();
+        this._xhrObject.send(formData);
+    },
+
+    setRequestHeader: function(key, value) {
+        this._xhrObject.setRequestHeader(key, value);
+    },
+
+    abort: function() {
+
+        this._xhrObject.abort();
+        this.onabort({});
+    },
+
+    _addProgressAttributes: function(evt, percent, total) {
+        //http://www.w3.org/TR/progress-events/#progressevent
+        evt.lengthComputable = true;
+        evt.loaded = percent;
+        evt.total = total;
+
+    },
+
+    onreadystatechange: function(evt) {
+        var myevt = evt || {};
+        //we have to simulate the attributes as well
+        var xhr = this._xhrObject;
+        var XHRConst = this._XHRConst;
+        try {
+        this.readyState = xhr.readyState;
+        this.status = ""+xhr.status;
+        } catch(e) {
+            //IE 6 has an internal error
+        }
+
+        switch (this.readyState) {
+
+            case  XHRConst.READY_STATE_OPENED:
+                this._addProgressAttributes(myevt, 10, 100);
+
+                this.onprogress(myevt);
+                break;
+
+            case XHRConst.READY_STATE_HEADERS_RECEIVED:
+                this._addProgressAttributes(myevt, 25, 100);
+
+                this.onprogress(myevt);
+                break;
+
+            case XHRConst.READY_STATE_LOADING:
+                if (this._loadingCalled) break;
+                this._loadingCalled = true;
+                this._addProgressAttributes(myevt, 50, 100);
+
+                this.onprogress(myevt);
+                break;
+
+            case XHRConst.READY_STATE_DONE:
+                this._addProgressAttributes(myevt, 100, 100);
+                //xhr level1 does not have timeout handler
+                if (this._timeoutTimer) {
+                    //normally the timeout should not cause anything anymore
+                    //but just to make sure
+                    window.clearTimeout(this._timeoutTimer);
+                    this._timeoutTimer = null;
+                }
+                this._transferRequestValues();
+                this.onprogress(myevt);
+                try {
+                    var status = xhr.status;
+                    if (status >= XHRConst.STATUS_OK_MINOR && status < XHRConst.STATUS_OK_MAJOR) {
+                        this.onload(myevt);
+                    } else {
+                        myevt.type = "error";
+                        this.onerror(myevt);
+                    }
+                } finally {
+					//remove for xhr level2 support
+                    this.onloadend(myevt);
+                }
+        }
+    },
+
+    _transferRequestValues: function() {
+        //this._Lang.mixMaps(this, this._xhrObject, true, null,
+        //        {responseText:1,responseXML:1,status:1,statusText:1,response:1});
+        var UDEF = "undefined";
+        var xhr = this._xhrObject;
+
+        this.responseText = (UDEF != typeof xhr.responseText)?xhr.responseText: null;
+        this.responseXML = (UDEF != typeof xhr.responseXML)?xhr.responseXML: null;
+        this.status = (UDEF != typeof xhr.status)?xhr.status: null;
+        this.statusText = (UDEF != typeof xhr.statusText)?xhr.statusText: null;
+        this.response = (UDEF != typeof xhr.response)?xhr.response: null;
+    },
+
+    _startTimeout: function() {
+        if (this.timeout == 0) return;
+
+        var xhr = this._xhrObject;
+        //some browsers have timeouts in their xhr level 1.x objects implemented
+        //we leverage them whenever they exist
+        try {
+            if ('undefined' != typeof xhr.timeout) {
+                xhr.timeout = this.timeout;
+                xhr.ontimeout = this.ontimeout;
+                return;
+            }
+        } catch (e) {
+            //firefox 12 has a bug here
+        }
+
+
+        this._timeoutTimer = setTimeout(this._Lang.hitch(this, function() {
+            if (xhr.readyState != this._XHRConst.READY_STATE_DONE) {
+
+                xhr.onreadystatechange = function() {
+                };
+                clearTimeout(this._timeoutTimer);
+                xhr.abort();
+                this.ontimeout({});
+            }
+        }), this.timeout);
+    },
+
+    getXHRObject: function() {
+        return this._xhrObject;
+    }
+
+
+});
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name IFrame
+ * @memberOf myfaces._impl.xhrCore.engine
+ * @extends myfaces._impl.xhrCore.engine.BaseRequest
+ * @description
+ *
+ * wrapper for an iframe transport object with all its differences
+ * it emulates the xhr level2 api
+ */
+_MF_CLS(_PFX_XHR + "engine.IFrame", myfaces._impl.xhrCore.engine.BaseRequest,
+        /** @lends myfaces._impl.xhrCore.engine.IFrame.prototype */
+        {
+
+            _finalized: false,
+
+            /*the target frame responsible for the communication*/
+            _frame: null,
+            //_requestHeader: null,
+            _aborted: false,
+
+            CLS_NAME: "myfaces._impl.xhrCore._IFrameRequest",
+            _FRAME_ID: "_mf_comm_frm",
+
+            /**
+             * constructor which shifts the arguments
+             * to the protected properties of this clas
+             *
+             * @param args
+             */
+            /* TOBAGO-JSF-JS: rename "arguments" with "args", because the compressor would fail */
+            constructor_: function (args) {
+                //we fetch in the standard arguments
+
+                this._callSuper("constructor", args);
+
+                this._initDefaultFinalizableFields();
+                //this._requestHeader = {};
+
+                this._XHRConst = myfaces._impl.xhrCore.engine.XhrConst;
+
+                this._Lang.applyArgs(this, args);
+                this.readyState = this._XHRConst.READY_STATE_UNSENT;
+                this._startTimeout();
+            },
+
+            setRequestHeader: function (key, value) {
+                //this._requestHeader[key] = value;
+            },
+
+            open: function (method, url, async) {
+
+                this.readyState = this._XHRConst.READY_STATE_OPENED;
+
+                var _RT = myfaces._impl.core._Runtime;
+                var _Lang = this._Lang;
+
+                this._frame = this._createTransportFrame();
+
+                //we append an onload handler to the frame
+                //to cover the starting and loading events,
+                //timeouts cannot be covered in a cross browser way
+
+                //we point our onload handler to the frame, we do not use addOnLoad
+                //because the frame should not have other onload handlers in place
+                if (!_RT.browser.isIE || this._Dom.isDomCompliant()) {
+                    this._frame.onload = _Lang.hitch(this, this._callback);
+                } else {
+                    //ie has a bug, onload is not settable outside of innerHTML on iframes
+                    this._frame.onload_IE = _Lang.hitch(this, this._callback);
+                }
+
+                this.method = method || this.method;
+                this.url = url || this.url;
+                this.async = ('undefined' != typeof async) ? async : this.async;
+
+                var myevt = {};
+                this._addProgressAttributes(myevt, 10, 100);
+                this.onprogress(myevt);
+            },
+
+            send: function (formData) {
+
+                var myevt = {};
+                this._addProgressAttributes(myevt, 20, 100);
+                this.onloadstart(myevt);
+                this.onprogress(myevt);
+
+                var formDataForm = formData.form,
+                        oldTarget = formDataForm.target,
+                        oldMethod = formDataForm.method,
+                        oldAction = formDataForm.action;
+
+                try {
+                    //_t._initAjaxParams();
+                    //for (var key in this._requestHeader) {
+                    //    formData.append(key, this._requestHeader[key]);
+                    //}
+
+                    formDataForm.target = this._frame.name;
+                    formDataForm.method = this.method;
+                    if (this.url) {
+                        formDataForm.action = this.url;
+                    }
+                    this.readyState = this._XHRConst.READY_STATE_LOADING;
+                    this.onreadystatechange(myevt);
+                    formDataForm.submit();
+                } finally {
+                    formDataForm.action = oldAction;
+                    formDataForm.target = oldTarget;
+                    formDataForm.method = oldMethod;
+
+                    formData._finalize();
+                    //alert("finalizing");
+                    this._finalized = true;
+                }
+            },
+
+            /*we can implement it, but it will work only on browsers
+             * which have asynchronous iframe loading*/
+            abort: function () {
+                this._aborted = true;
+                this.onabort({});
+            },
+
+            _addProgressAttributes: function (evt, percent, total) {
+                //http://www.w3.org/TR/progress-events/#progressevent
+                evt.lengthComputable = true;
+                evt.loaded = percent;
+                evt.total = total;
+
+            },
+
+            _callback: function () {
+                //------------------------------------
+                // we are asynchronous which means we
+                // have to check wether our code
+                // is finalized or not
+                //------------------------------------
+                if (this._aborted) return;
+                if (this._timeoutTimer) {
+                    clearTimeout(this._timeoutTimer);
+                }
+                if (!this._finalized) {
+                    setTimeout(this._Lang.hitch(this, this._callback), 10);
+                    return;
+                }
+                //aborted no further processing
+
+                try {
+                    var myevt = {};
+
+                    this._addProgressAttributes(myevt, 100, 100);
+                    //this.readyState = this._XHRConst.READY_STATE_DONE;
+                    //this.onreadystatechange(myevt);
+
+                    this.responseText = this._getFrameText();
+                    this.responseXML = this._getFrameXml();
+                    this.readyState = this._XHRConst.READY_STATE_DONE;
+
+                    //TODO status and statusText
+
+                    this.onreadystatechange(myevt);
+                    this.onloadend();
+
+                    if (!this._Lang.isXMLParseError(this.responseXML)) {
+                        this.status = 201;
+                        this.onload();
+                    } else {
+                        this.status = 0;
+                        //we simulate the request for our xhr call
+                        this.onerror();
+                    }
+
+                } finally {
+                    this._frame = null;
+                }
+            },
+
+            /**
+             * returns the frame text in a browser independend manner
+             */
+            _getFrameDocument: function () {
+
+                //we cover various browsers here, because almost all browsers keep the document in a different
+                //position
+                return this._frame.contentWindow.document || this._frame.contentDocument || this._frame.document;
+            },
+
+            _getFrameText: function () {
+                var framedoc = this._getFrameDocument();
+                //also ie keeps the body in framedoc.body the rest in documentElement
+                var body = framedoc.body || framedoc.documentElement;
+                return  body.innerHTML;
+            },
+
+            _clearFrame: function () {
+
+                var framedoc = this._getFrameDocument();
+                var body = framedoc.documentElement || framedoc.body;
+                //ie8 in 7 mode chokes on the innerHTML method
+                //direct dom removal is less flakey and works
+                //over all browsers, but is slower
+                if (myfaces._impl.core._Runtime.browser.isIE) {
+                    this._Dom._removeChildNodes(body, false);
+                } else {
+                    body.innerHTML = "";
+                }
+            },
+
+            /**
+             * returns the processed xml from the frame
+             */
+            _getFrameXml: function () {
+                var framedoc = this._getFrameDocument();
+                //same situation here, the xml is hosted either in xmlDocument or
+                //is located directly under the frame document
+                return  framedoc.XMLDocument || framedoc;
+            },
+
+            _createTransportFrame: function () {
+
+                var _FRM_ID = this._FRAME_ID;
+                var frame = document.getElementById(_FRM_ID);
+                if (frame) return frame;
+                //normally this code should not be called
+                //but just to be sure
+
+                if (this._Dom.isDomCompliant()) {
+                    frame = this._Dom.createElement('iframe', {
+                        "src": "about:blank",
+                        "id": _FRM_ID,
+                        "name": _FRM_ID,
+                        "type": "content",
+                        "collapsed": "true",
+                        "style": "display:none"
+                    });
+
+                    //probably the ie method would work on all browsers
+                    //but this code is the safe bet it works on all standards
+                    //compliant browsers in a clean manner
+
+                    document.body.appendChild(frame);
+                } else { //Now to the non compliant browsers
+                    var node = this._Dom.createElement("div", {
+                        "style": "display:none"
+                    });
+
+                    //we are dealing with two well known iframe ie bugs here
+                    //first the iframe has to be set via innerHTML to be present
+                    //secondly the onload handler is immutable on ie, we have to
+                    //use a dummy onload handler in this case and call this one
+                    //from the onload handler
+                    node.innerHTML = "<iframe id='" + _FRM_ID + "' name='" + _FRM_ID + "' style='display:none;' src='about:blank' type='content' onload='this.onload_IE();'  ></iframe>";
+
+                    //avoid the ie open tag problem
+                    var body = document.body;
+                    if (body.firstChild) {
+                        body.insertBefore(node, document.body.firstChild);
+                    } else {
+                        body.appendChild(node);
+                    }
+                }
+
+                //helps to for the onload handlers and innerhtml to be in sync again
+                return document.getElementById(_FRM_ID);
+            },
+
+            _startTimeout: function () {
+
+                if (this.timeout == 0) return;
+                this._timeoutTimer = setTimeout(this._Lang.hitch(this, function () {
+                    if (this._xhrObject.readyState != this._XHRConst.READY_STATE_DONE) {
+
+                        this._aborted = true;
+                        clearTimeout(this._timeoutTimer);
+                        //we cannot abort an iframe request
+                        this.ontimeout({});
+                        this._timeoutTimer = null;
+                    }
+                }), this.timeout);
+            }
+        });
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * An implementation of an xhr request object
+ * with partial page submit functionality, and jsf
+ * ppr request and timeout handling capabilities
+ *
+ * Author: Werner Punz (latest modification by $Author: ganeshpuri $)
+ * Version: $Revision: 1.4 $ $Date: 2009/05/31 09:16:44 $
+ */
+
+/**
+ * @class
+ * @name _AjaxRequest
+ * @memberOf myfaces._impl.xhrCore
+ * @extends myfaces._impl.core.Object
+ */
+_MF_CLS(_PFX_XHR + "_AjaxRequest", _MF_OBJECT, /** @lends myfaces._impl.xhrCore._AjaxRequest.prototype */ {
+
+    _contentType:"application/x-www-form-urlencoded",
+    /** source element issuing the request */
+    _source:null,
+    /** context passed down from the caller */
+    _context:null,
+    /** source form issuing the request */
+    _sourceForm:null,
+    /** passthrough parameters */
+    _passThrough:null,
+
+    /** queue control */
+    _timeout:null,
+    /** enqueuing delay */
+    //_delay:null,
+    /** queue size */
+    _queueSize:-1,
+
+    /**
+     back reference to the xhr queue,
+     only set if the object really is queued
+     */
+    _xhrQueue:null,
+
+    /** pps an array of identifiers which should be part of the submit, the form is ignored */
+    _partialIdsArray:null,
+
+    /** xhr object, internal param */
+    _xhr:null,
+
+    /** predefined method */
+    _ajaxType:"POST",
+
+    //CONSTANTS
+    ENCODED_URL:"javax.faces.encodedURL",
+    /*
+     * constants used internally
+     */
+    _CONTENT_TYPE:"Content-Type",
+    _HEAD_FACES_REQ:"Faces-Request",
+    _VAL_AJAX:"partial/ajax",
+    _XHR_CONST:myfaces._impl.xhrCore.engine.XhrConst,
+
+    // _exception: null,
+    // _requestParameters: null,
+    /**
+     * Constructor
+     * <p />
+     * note there is a load of common properties
+     * inherited by the base class which define the corner
+     * parameters and the general internal behavior
+     * like _onError etc...
+     * @param {Object} args an arguments map which an override any of the given protected
+     * instance variables, by a simple name value pair combination
+     */
+    constructor_:function (args) {
+
+        try {
+            this._callSuper("constructor_", args);
+
+            this._initDefaultFinalizableFields();
+            delete this._resettableContent["_xhrQueue"];
+
+            this.applyArgs(args);
+
+            /*namespace remapping for readability*/
+            //we fetch in the standard arguments
+            //and apply them to our protected attributes
+            //we do not gc the entry hence it is not defined on top
+            var xhrCore = myfaces._impl.xhrCore;
+            this._AJAXUTIL = xhrCore._AjaxUtils;
+
+        } catch (e) {
+            //_onError
+            this._stdErrorHandler(this._xhr, this._context, e);
+        }
+    },
+
+    /**
+     * Sends an Ajax request
+     */
+    send:function () {
+
+        var _Lang = this._Lang;
+        var _RT = this._RT;
+        var _Dom = this._Dom;
+        try {
+
+            var scopeThis = _Lang.hitch(this, function (functionName) {
+                return _Lang.hitch(this, this[functionName]);
+            });
+            this._xhr = _Lang.mixMaps(this._getTransport(), {
+                onprogress:scopeThis("onprogress"),
+                ontimeout:scopeThis("ontimeout"),
+                //remove for xhr level2 support (chrome has problems with it)
+                //for chrome we have to emulate the onloadend by calling it explicitely
+                //and leave the onload out
+                //onloadend:  scopeThis("ondone"),
+                onload:scopeThis("onsuccess"),
+                onerror:scopeThis("onerror")
+
+            }, true);
+
+            this._applyClientWindowId();
+            var xhr = this._xhr,
+                    sourceForm = this._sourceForm,
+                    targetURL = (typeof sourceForm.elements[this.ENCODED_URL] == 'undefined') ?
+                            sourceForm.action :
+                            sourceForm.elements[this.ENCODED_URL].value,
+                    formData = this.getFormData();
+
+            for (var key in this._passThrough) {
+                if (!this._passThrough.hasOwnProperty(key)) continue;
+                formData.append(key, this._passThrough[key]);
+            }
+
+            xhr.open(this._ajaxType, targetURL +
+                    ((this._ajaxType == "GET") ? "?" + this._formDataToURI(formData) : "")
+                    , true);
+
+            xhr.timeout = this._timeout || 0;
+
+            this._applyContentType(xhr);
+            xhr.setRequestHeader(this._HEAD_FACES_REQ, this._VAL_AJAX);
+
+            //some webkit based mobile browsers do not follow the w3c spec of
+            // setting the accept headers automatically
+            if (this._RT.browser.isWebKit) {
+                xhr.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
+            }
+            this._sendEvent("BEGIN");
+            //Check if it is a custom form data object
+            //if yes we use makefinal for the final handling
+            if (formData && formData.makeFinal) {
+                formData = formData.makeFinal()
+            }
+            xhr.send((this._ajaxType != "GET") ? formData : null);
+
+        } catch (e) {
+            //_onError//_onError
+            e = (e._mfInternal) ? e : this._Lang.makeException(new Error(), "sendError", "sendError", this._nameSpace, "send", e.message);
+            this._stdErrorHandler(this._xhr, this._context, e);
+        } finally {
+            //no finally possible since the iframe uses real asynchronousity
+        }
+    },
+
+    _applyClientWindowId:function () {
+        var clientWindow = this._Dom.getNamedElementFromForm(this._sourceForm, "javax.faces.ClientWindow");
+        //pass through if exists already set by _Impl
+        if ('undefined' != typeof this._context._mfInternal._clientWindow) {
+            this._context._mfInternal._clientWindowOld = clientWindow.value;
+            clientWindow.value = this._context._mfInternal._clientWindow;
+        } else {
+            if(clientWindow) {
+                this._context._mfInternal._clientWindowDisabled = !! clientWindow.disabled;
+                clientWindow.disabled = true;
+            }
+        }
+    },
+
+    _restoreClientWindowId:function () {
+        //we have to reset the client window back to its original state
+
+        var clientWindow = this._Dom.getNamedElementFromForm(this._sourceForm, "javax.faces.ClientWindow");
+        if(!clientWindow) {
+            return;
+        }
+        if ('undefined' != typeof this._context._mfInternal._clientWindowOld) {
+            clientWindow.value =  this._context._mfInternal._clientWindow;
+        }
+        if('undefined' != typeof this._context._mfInternal._clientWindowDisabled) {
+            //we reset it to the old value
+            clientWindow.disabled = this._context._mfInternal._clientWindowDisabled;
+        }
+    },
+
+    /**
+     * applies the content type, this needs to be done only for xhr
+     * level1
+     * @param xhr
+     * @private
+     */
+    _applyContentType:function (xhr) {
+        var contentType = this._contentType + "; charset=utf-8";
+        xhr.setRequestHeader(this._CONTENT_TYPE, contentType);
+    },
+
+    ondone:function () {
+        this._requestDone();
+    },
+
+    onsuccess:function (/*evt*/) {
+        this._restoreClientWindowId();
+        var context = this._context;
+        var xhr = this._xhr;
+        try {
+            this._sendEvent("COMPLETE");
+            //now we have to reroute into our official api
+            //because users might want to decorate it, we will split it apart afterwards
+
+            context._mfInternal = context._mfInternal || {};
+            jsf.ajax.response((xhr.getXHRObject) ? xhr.getXHRObject() : xhr, context);
+
+        } catch (e) {
+            this._stdErrorHandler(this._xhr, this._context, e);
+
+            //add for xhr level2 support
+        } finally {
+            //W3C spec onloadend must be called no matter if success or not
+            this.ondone();
+        }
+    },
+
+    onerror:function (/*evt*/) {
+        this._restoreClientWindowId();
+        //TODO improve the error code detection here regarding server errors etc...
+        //and push it into our general error handling subframework
+        var context = this._context;
+        var xhr = this._xhr;
+        var _Lang = this._Lang;
+
+        var errorText = "";
+        this._sendEvent("COMPLETE");
+        try {
+            var UNKNOWN = _Lang.getMessage("UNKNOWN");
+            //status can be 0 and statusText can be ""
+            var status = ('undefined' != xhr.status && null != xhr.status) ? xhr.status : UNKNOWN;
+            var statusText = ('undefined' != xhr.statusText && null != xhr.statusText) ? xhr.statusText : UNKNOWN;
+            errorText = _Lang.getMessage("ERR_REQU_FAILED", null, status, statusText);
+
+        } catch (e) {
+            errorText = _Lang.getMessage("ERR_REQ_FAILED_UNKNOWN", null);
+        } finally {
+            try {
+                var _Impl = this.attr("impl");
+                _Impl.sendError(xhr, context, _Impl.HTTPERROR,
+                        _Impl.HTTPERROR, errorText, "", "myfaces._impl.xhrCore._AjaxRequest", "onerror");
+            } finally {
+                //add for xhr level2 support
+                //since chrome does not call properly the onloadend we have to do it manually
+                //to eliminate xhr level1 for the compile profile modern
+                //W3C spec onloadend must be called no matter if success or not
+                this.ondone();
+            }
+        }
+        //_onError
+    },
+
+    onprogress:function (/*evt*/) {
+        //do nothing for now
+    },
+
+    ontimeout:function (/*evt*/) {
+        try {
+            this._restoreClientWindowId();
+            //we issue an event not an error here before killing the xhr process
+            this._sendEvent("TIMEOUT_EVENT");
+            //timeout done we process the next in the queue
+        } finally {
+            this._requestDone();
+        }
+    },
+
+    _formDataToURI:function (formData) {
+        if (formData && formData.makeFinal) {
+            formData = formData.makeFinal()
+        }
+        return formData;
+    },
+
+    _getTransport:function () {
+
+        var xhr = this._RT.getXHRObject();
+        //the current xhr level2 timeout w3c spec is not implemented by the browsers yet
+        //we have to do a fallback to our custom routines
+
+        //add for xhr level2 support
+        //Chrome fails in the current builds, on our loadend, we disable the xhr
+        //level2 optimisations for now
+        if (/*('undefined' == typeof this._timeout || null == this._timeout) &&*/ this._RT.getXHRLvl() >= 2) {
+            //no timeout we can skip the emulation layer
+            return xhr;
+        }
+        return new myfaces._impl.xhrCore.engine.Xhr1({xhrObject:xhr});
+    },
+
+    //----------------- backported from the base request --------------------------------
+    //non abstract ones
+    /**
+     * Spec. 13.3.1
+     * Collect and encode input elements.
+     * Additionally the hidden element javax.faces.ViewState
+     *
+     *
+     * @return  an element of formDataWrapper
+     * which keeps the final Send Representation of the
+     */
+    getFormData:function () {
+        var _AJAXUTIL = this._AJAXUTIL, myfacesOptions = this._context.myfaces;
+        return this._Lang.createFormDataDecorator(jsf.getViewState(this._sourceForm));
+    },
+
+    /**
+     * Client error handlers which also in the long run route into our error queue
+     * but also are able to deliver more meaningful messages
+     * note, in case of an error all subsequent xhr requests are dropped
+     * to get a clean state on things
+     *
+     * @param request the xhr request object
+     * @param context the context holding all values for further processing
+     * @param exception the embedded exception
+     */
+    _stdErrorHandler:function (request, context, exception) {
+        var xhrQueue = this._xhrQueue;
+        try {
+            this.attr("impl").stdErrorHandler(request, context, exception);
+        } finally {
+            if (xhrQueue) {
+                xhrQueue.cleanup();
+            }
+        }
+    },
+
+    _sendEvent:function (evtType) {
+        var _Impl = this.attr("impl");
+        _Impl.sendEvent(this._xhr, this._context, _Impl[evtType]);
+    },
+
+    _requestDone:function () {
+        var queue = this._xhrQueue;
+        if (queue) {
+            queue.processQueue();
+        }
+        //ie6 helper cleanup
+        delete this._context.source;
+        this._finalize();
+    },
+
+    //cleanup
+    _finalize:function () {
+        if (this._xhr.readyState == this._XHR_CONST.READY_STATE_DONE) {
+            this._callSuper("_finalize");
+        }
+    }
+});
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * this method is used only for pure multipart form parts
+ * otherwise the normal method is used
+ * IT is a specialized request which uses the form data
+ * element for the handling of forms
+ */
+_MF_CLS(_PFX_XHR + "_MultipartAjaxRequestLevel2", myfaces._impl.xhrCore._AjaxRequest, {
+
+    _sourceForm:null,
+
+    /* TOBAGO-JSF-JS: rename "arguments" with "args", because the compressor would fail */
+    constructor_:function (args) {
+        this._callSuper("constructor_", args);
+        //TODO xhr level2 can deal with real props
+
+    },
+
+    getFormData:function () {
+        var ret;
+        //in case of a multipart form post we savely can use the FormData object
+        if (this._context._mfInternal.xhrOp === "multipartQueuedPost") {
+            ret = new FormData(this._sourceForm);
+            this._AJAXUTIL.appendIssuingItem(this._source, ret);
+        } else {
+            //we switch back to the encode submittable fields system
+            this._AJAXUTIL.encodeSubmittableFields(ret, this._sourceForm, null);
+            this._AJAXUTIL.appendIssuingItem(this._source, ret);
+        }
+        return ret;
+    },
+
+    /**
+     * applies the content type, this needs to be done only for xhr
+     * level1
+     * @param xhr
+     * @private
+     */
+    _applyContentType:function (xhr) {
+        //content type is not set in case of xhr level2 because
+        //the form data object does it itself
+    },
+
+    _formDataToURI:function (formData) {
+        //in xhr level2 form data takes care of the http get parametrisation
+        return "";
+    },
+
+    _getTransport:function () {
+        return new XMLHttpRequest();
+    }
+});
+
+/**
+ * for normal requests we basically use
+ * only the xhr level2 object but
+ */
+_MF_CLS(_PFX_XHR + "_AjaxRequestLevel2", myfaces._impl.xhrCore._AjaxRequest, {
+
+    _sourceForm:null,
+
+    /* TOBAGO-JSF-JS: rename "arguments" with "args", because the compressor would fail */
+    constructor_:function (args) {
+        this._callSuper("constructor_", args);
+        //TODO xhr level2 can deal with real props
+
+    },
+
+    _getTransport:function () {
+        return new XMLHttpRequest();
+    }
+});
+
+
+
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+/**
+ * @class
+ * @name _IFrameRequest
+ * @memberOf myfaces._impl.xhrCore
+ * @extends myfaces._impl.xhrCore._AjaxRequest
+ * @description specialized implementation of the jsf js ajax request class
+ * which utilizes an iframe transport for communications to the server
+ */
+_MF_CLS(_PFX_XHR+"_IFrameRequest", myfaces._impl.xhrCore._AjaxRequest,
+        /** @lends myfaces._impl.xhrCore._IFrameRequest.prototype */
+        {
+
+    /**
+     * @constant
+     * @description request marker that the request is an iframe based request
+     */
+    //JX_PART_IFRAME: "javax.faces.partial.iframe",
+    /**
+     * @constant
+     * @description request marker that the request is an apache myfaces iframe request based request
+     */
+    MF_PART_IFRAME: "javax.faces.transport.iframe",
+
+    MF_PART_FACES_REQUEST: "javax.faces.request",
+
+
+    /* TOBAGO-JSF-JS: rename "arguments" with "args", because the compressor would fail */
+    constructor_: function(args) {
+        this._callSuper("constructor_", args);
+    },
+
+    getFormData: function() {
+        var ret = new myfaces._impl.xhrCore.engine.FormData(this._sourceForm);
+        //marker that this is an ajax iframe request
+        //ret.append(this.JX_PART_IFRAME, "true");
+        ret.append(this.MF_PART_IFRAME, "true");
+        ret.append(this.MF_PART_FACES_REQUEST, "partial/ajax");
+
+        var viewState = decodeURIComponent(jsf.getViewState(this._sourceForm));
+        viewState = viewState.split("&");
+
+        //we append all viewstate values which are not part of the original form
+        //just in case getViewState is decorated
+        for(var cnt = 0, len = viewState.length; cnt < len; cnt++) {
+            var currViewState = viewState[cnt];
+            var keyVal = currViewState.split("=");
+            var name = keyVal[0];
+            if(!this._Dom.getNamedElementFromForm(this._sourceForm, name)) {
+                ret.append(name, keyVal[1]);
+            }
+        }
+
+        return ret;
+    },
+
+    _formDataToURI: function(/*formData*/) {
+        //http get alwyays sends the form data
+        return "";
+    },
+
+    _getTransport: function() {
+        return new myfaces._impl.xhrCore.engine.IFrame();
+    }
+
+});
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name _AjaxResponse
+ * @memberOf myfaces._impl.xhrCore
+ * @extends myfaces._impl.core.Object
+ * @description
+ * This singleton is responsible for handling the standardized xml ajax response
+ * Note: since the semantic processing can be handled about 90% in a functional
+ * style we make this class stateless. Every state information is stored
+ * temporarily in the context.
+ *
+ * The singleton approach also improves performance
+ * due to less object gc compared to the old instance approach.
+ *
+ */
+_MF_SINGLTN(_PFX_XHR + "_AjaxResponse", _MF_OBJECT, /** @lends myfaces._impl.xhrCore._AjaxResponse.prototype */ {
+
+    /*partial response types*/
+    RESP_PARTIAL:"partial-response",
+    RESP_TYPE_ERROR:"error",
+    RESP_TYPE_REDIRECT:"redirect",
+    RESP_TYPE_CHANGES:"changes",
+
+    /*partial commands*/
+    CMD_CHANGES:"changes",
+    CMD_UPDATE:"update",
+    CMD_DELETE:"delete",
+    CMD_INSERT:"insert",
+    CMD_EVAL:"eval",
+    CMD_ERROR:"error",
+    CMD_ATTRIBUTES:"attributes",
+    CMD_EXTENSION:"extension",
+    CMD_REDIRECT:"redirect",
+
+    /*other constants*/
+    P_VIEWSTATE:"javax.faces.ViewState",
+    P_CLIENTWINDOW: "javax.faces.ClientWindow",
+    P_VIEWROOT:"javax.faces.ViewRoot",
+    P_VIEWHEAD:"javax.faces.ViewHead",
+    P_VIEWBODY:"javax.faces.ViewBody",
+
+    /**
+     * uses response to start Html element replacement
+     *
+     * @param {Object} request (xhrRequest) - xhr request object
+     * @param {Object} context (Map) - AJAX context
+     *
+     * A special handling has to be added to the update cycle
+     * according to the JSDoc specs if the CDATA block contains html tags the outer rim must be stripped
+     * if the CDATA block contains a head section the document head must be replaced
+     * and if the CDATA block contains a body section the document body must be replaced!
+     *
+     */
+    processResponse:function (request, context) {
+        //mfinternal handling, note, the mfinternal is only optional
+        //according to the spec
+        context._mfInternal = context._mfInternal || {};
+        var mfInternal = context._mfInternal;
+
+        //the temporary data is hosted here
+        mfInternal._updateElems = [];
+        mfInternal._updateForms = [];
+        mfInternal.appliedViewState = null;
+        mfInternal.appliedClientWindow = null;
+
+        try {
+            var _Impl = this.attr("impl"), _Lang = this._Lang;
+            // TODO:
+            // Solution from
+            // http://www.codingforums.com/archive/index.php/t-47018.html
+            // to solve IE error 1072896658 when a Java server sends iso88591
+            // istead of ISO-8859-1
+
+            if (!request || !_Lang.exists(request, "responseXML")) {
+                throw this.makeException(new Error(), _Impl.EMPTY_RESPONSE, _Impl.EMPTY_RESPONSE, this._nameSpace, "processResponse", "");
+            }
+            //check for a parseError under certain browsers
+
+            var xmlContent = request.responseXML;
+            //ie6+ keeps the parsing response under xmlContent.parserError
+            //while the rest of the world keeps it as element under the first node
+            var xmlErr = _Lang.fetchXMLErrorMessage(request.responseText || request.response, xmlContent)
+            if (xmlErr) {
+                throw this._raiseError(new Error(), xmlErr.errorMessage + "\n" + xmlErr.sourceText + "\n" + xmlErr.visualError + "\n", "processResponse");
+            }
+            var partials = xmlContent.childNodes[0];
+            if ('undefined' == typeof partials || partials == null) {
+                throw this._raiseError(new Error(), "No child nodes for response", "processResponse");
+
+            } else {
+                if (partials.tagName != this.RESP_PARTIAL) {
+                    // IE 8 sees XML Header as first sibling ...
+                    partials = partials.nextSibling;
+                    if (!partials || partials.tagName != this.RESP_PARTIAL) {
+                        throw this._raiseError(new Error(), "Partial response not set", "processResponse");
+                    }
+                }
+            }
+
+            var childNodesLength = partials.childNodes.length;
+
+            for (var loop = 0; loop < childNodesLength; loop++) {
+                var childNode = partials.childNodes[loop];
+                var tagName = childNode.tagName;
+                /**
+                 * <eval>
+                 *      <![CDATA[javascript]]>
+                 * </eval>
+                 */
+
+                //this ought to be enough for eval
+                //however the run scripts still makes sense
+                //in the update and insert area for components
+                //which do not use the response writer properly
+                //we might add this one as custom option in update and
+                //insert!
+                if (tagName == this.CMD_ERROR) {
+                    this.processError(request, context, childNode);
+                } else if (tagName == this.CMD_REDIRECT) {
+                    this.processRedirect(request, context, childNode);
+                } else if (tagName == this.CMD_CHANGES) {
+                    this.processChanges(request, context, childNode);
+                }
+            }
+
+            //fixup missing viewStates due to spec deficiencies
+            if(mfInternal.appliedViewState) {
+                this.fixViewStates(context);
+            }
+            if(mfInternal.appliedClientWindow) {
+                this.fixClientWindows(context);
+            }
+
+            //spec jsdoc, the success event must be sent from response
+            _Impl.sendEvent(request, context, _Impl["SUCCESS"]);
+
+        } finally {
+            delete mfInternal._updateElems;
+            delete mfInternal._updateForms;
+            delete mfInternal.appliedViewState;
+            delete mfInternal.appliedClientWindow;
+        }
+    },
+
+    /**
+     * fixes the viewstates in the current page
+     *
+     * @param context
+     */
+    fixViewStates:function (context) {
+        var _Lang = this._Lang;
+        var mfInternal = context._mfInternal;
+
+        if (null == mfInternal.appliedViewState) {
+            return;
+        }
+
+        //if we set our no portlet env we safely can update all forms with
+        //the new viewstate
+        if (this._RT.getLocalOrGlobalConfig(context, "no_portlet_env", false)) {
+            for (var cnt = document.forms.length - 1; cnt >= 0; cnt--) {
+                this._setVSTCWForm(context, document.forms[cnt], mfInternal.appliedViewState, this.P_VIEWSTATE);
+            }
+            return;
+        }
+
+        // Now update the forms that were not replaced but forced to be updated, because contains child ajax tags
+        // we should only update forms with view state hidden field. If by some reason, the form was set to be
+        // updated but the form was replaced, it does not have hidden view state, so later in changeTrace processing the
+        // view state is updated.
+
+        //set the viewstates of all outer forms parents of our updated elements
+
+        _Lang.arrForEach(mfInternal._updateForms, function (elem) {
+            this._setVSTCWForm(context, elem, mfInternal.appliedViewState, this.P_VIEWSTATE);
+        }, 0, this);
+
+        //set the viewstate of all forms within our updated elements
+        _Lang.arrForEach(mfInternal._updateElems, function (elem) {
+            this._setVSTCWInnerForms(context, elem, mfInternal.appliedViewState, this.P_VIEWSTATE);
+        }, 0, this);
+    },
+
+    fixClientWindows:function (context, theForm) {
+        var _Lang = this._Lang;
+        var mfInternal = context._mfInternal;
+
+        if (null == mfInternal.appliedClientWindow) {
+            return;
+        }
+         //if we set our no portlet env we safely can update all forms with
+        //the new viewstate
+        if (this._RT.getLocalOrGlobalConfig(context, "no_portlet_env", false)) {
+            for (var cnt = document.forms.length - 1; cnt >= 0; cnt--) {
+                this._setVSTCWForm(context, document.forms[cnt], mfInternal.appliedClientWindow, this.P_CLIENTWINDOW);
+            }
+            return;
+        }
+        //set the client window of all outer form of updated elements
+
+        _Lang.arrForEach(mfInternal._updateForms, function (elem) {
+            this._setVSTCWForm(context, elem, mfInternal.appliedClientWindow, this.P_CLIENTWINDOW);
+        }, 0, this);
+
+        //set the client window of all forms within our updated elements
+        _Lang.arrForEach(mfInternal._updateElems, function (elem) {
+            this._setVSTCWInnerForms(context, elem, mfInternal.appliedClientWindow, this.P_CLIENTWINDOW);
+        }, 0, this);
+    },
+
+    /**
+     * sets the viewstate element in a given form
+     *
+     * @param theForm the form to which the element has to be set to
+     * @param context the current request context
+     */
+    _setVSTCWForm:function (context, theForm, value, identifier) {
+        theForm = this._Lang.byId(theForm);
+        var mfInternal = context._mfInternal;
+
+        if (!theForm) return;
+
+        //in IE7 looking up form elements with complex names (such as 'javax.faces.ViewState') fails in certain cases
+        //iterate through the form elements to find the element, instead
+        var fieldToApply = this._Dom.getNamedElementFromForm(theForm, identifier);
+
+        if (fieldToApply) {
+            this._Dom.setAttribute(fieldToApply, "value", value);
+        } else if (!fieldToApply) {
+            var element = this._Dom.getDummyPlaceHolder();
+            //spec error, two elements with the same id should not be there, TODO recheck the space if the name does not suffice alone
+            element.innerHTML = ["<input type='hidden'", "id='", identifier+jsf.separatorchar+Math.random() , "' name='", identifier , "' value='" , value , "' />"].join("");
+            //now we go to proper dom handling after having to deal with another ie screwup
+            try {
+                theForm.appendChild(element.childNodes[0]);
+            } finally {
+                element.innerHTML = "";
+            }
+        }
+    },
+
+    _setVSTCWInnerForms:function (context, elem, value, identifier) {
+
+        var _Lang = this._Lang, _Dom = this._Dom;
+        elem = _Dom.byIdOrName(elem);
+        //elem not found for whatever reason
+        //https://issues.apache.org/jira/browse/MYFACES-3544
+        if (!elem) return;
+
+        var replacedForms = _Dom.findByTagName(elem, "form", false);
+
+        var applyVST = _Lang.hitch(this, function (elem) {
+            this._setVSTCWForm(context, elem, value, identifier);
+        });
+
+        try {
+            _Lang.arrForEach(replacedForms, applyVST, 0, this);
+        } finally {
+            applyVST = null;
+        }
+    },
+
+    /**
+     * processes an incoming error from the response
+     * which is hosted under the &lt;error&gt; tag
+     * @param request the current request
+     * @param context the contect object
+     * @param node the node in the xml hosting the error message
+     */
+    processError:function (request, context, node) {
+        /**
+         * <error>
+         *      <error-name>String</error-name>
+         *      <error-message><![CDATA[message]]></error-message>
+         * <error>
+         */
+        var errorName = node.firstChild.textContent || node.firstChild.text || "",
+                errorMessage = node.childNodes[1].firstChild.data || "";
+
+        this.attr("impl").sendError(request, context, this.attr("impl").SERVER_ERROR, errorName, errorMessage, "myfaces._impl.xhrCore._AjaxResponse", "processError");
+    },
+
+    /**
+     * processes an incoming xml redirect directive from the ajax response
+     * @param request the request object
+     * @param context the context
+     * @param node the node hosting the redirect data
+     */
+    processRedirect:function (request, context, node) {
+        /**
+         * <redirect url="url to redirect" />
+         */
+        var _Lang = this._Lang;
+        var redirectUrl = node.getAttribute("url");
+        if (!redirectUrl) {
+            throw this._raiseError(new Error(), _Lang.getMessage("ERR_RED_URL", null, "_AjaxResponse.processRedirect"), "processRedirect");
+        }
+        redirectUrl = _Lang.trim(redirectUrl);
+        if (redirectUrl == "") {
+            return false;
+        }
+        window.location = redirectUrl;
+        return true;
+    },
+
+    /**
+     * main entry point for processing the changes
+     * it deals with the &lt;changes&gt; node of the
+     * response
+     *
+     * @param request the xhr request object
+     * @param context the context map
+     * @param node the changes node to be processed
+     */
+    processChanges:function (request, context, node) {
+        var changes = node.childNodes;
+        var _Lang = this._Lang;
+        //note we need to trace the changes which could affect our insert update or delete
+        //se that we can realign our ViewStates afterwards
+        //the realignment must happen post change processing
+
+        for (var i = 0; i < changes.length; i++) {
+
+            switch (changes[i].tagName) {
+
+                case this.CMD_UPDATE:
+                    this.processUpdate(request, context, changes[i]);
+                    break;
+                case this.CMD_EVAL:
+                    _Lang.globalEval(changes[i].firstChild.data);
+                    break;
+                case this.CMD_INSERT:
+                    this.processInsert(request, context, changes[i]);
+                    break;
+                case this.CMD_DELETE:
+                    this.processDelete(request, context, changes[i]);
+                    break;
+                case this.CMD_ATTRIBUTES:
+                    this.processAttributes(request, context, changes[i]);
+                    break;
+                case this.CMD_EXTENSION:
+                    break;
+                default:
+                    throw this._raiseError(new Error(), "_AjaxResponse.processChanges: Illegal Command Issued", "processChanges");
+            }
+        }
+
+        return true;
+    },
+
+    /**
+     * First sub-step process a pending update tag
+     *
+     * @param request the xhr request object
+     * @param context the context map
+     * @param node the changes node to be processed
+     */
+    processUpdate:function (request, context, node) {
+        if ( (node.getAttribute('id').indexOf(this.P_VIEWSTATE) != -1) || (node.getAttribute('id').indexOf(this.P_CLIENTWINDOW) != -1) ) {
+            //update the submitting forms viewstate to the new value
+            // The source form has to be pulled out of the CURRENT document first because the context object
+            // may refer to an invalid document if an update of the entire body has occurred before this point.
+            var mfInternal = context._mfInternal,
+                    fuzzyFormDetection = this._Lang.hitch(this._Dom, this._Dom.fuzzyFormDetection);
+            var elemId = (mfInternal._mfSourceControlId) ? mfInternal._mfSourceControlId :
+                    ((context.source) ? context.source.id : null);
+
+            //theoretically a source of null can be given, then our form detection fails for
+            //the source element case and hence updateviewstate is skipped for the source
+            //form, but still render targets still can get the viewstate
+            var sourceForm = (mfInternal && mfInternal["_mfSourceFormId"] &&
+                    document.forms[mfInternal["_mfSourceFormId"]]) ?
+                    document.forms[mfInternal["_mfSourceFormId"]] : ((elemId) ? fuzzyFormDetection(elemId) : null);
+
+            if(node.getAttribute('id').indexOf(this.P_VIEWSTATE) != -1) {
+                mfInternal.appliedViewState = this._Dom.concatCDATABlocks(node);//node.firstChild.nodeValue;
+            } else if(node.getAttribute('id').indexOf(this.P_CLIENTWINDOW) != -1) {
+                mfInternal.appliedClientWindow = node.firstChild.nodeValue;
+            }
+            //source form could not be determined either over the form identifer or the element
+            //we now skip this phase and just add everything we need for the fixup code
+
+            if (!sourceForm) {
+                //no source form found is not an error because
+                //we might be able to recover one way or the other
+                return true;
+            }
+
+            mfInternal._updateForms.push(sourceForm.id);
+
+        }
+        else {
+            // response may contain several blocks
+            var cDataBlock = this._Dom.concatCDATABlocks(node),
+                    resultNode = null,
+                    pushOpRes = this._Lang.hitch(this, this._pushOperationResult);
+
+            switch (node.getAttribute('id')) {
+                case this.P_VIEWROOT:
+
+                    cDataBlock = cDataBlock.substring(cDataBlock.indexOf("<html"));
+
+                    var parsedData = this._replaceHead(request, context, cDataBlock);
+
+                    resultNode = ('undefined' != typeof parsedData && null != parsedData) ? this._replaceBody(request, context, cDataBlock, parsedData) : this._replaceBody(request, context, cDataBlock);
+                    if (resultNode) {
+                        pushOpRes(context, resultNode);
+                    }
+                    break;
+                case this.P_VIEWHEAD:
+                    //we cannot replace the head, almost no browser allows this, some of them throw errors
+                    //others simply ignore it or replace it and destroy the dom that way!
+                    this._replaceHead(request, context, cDataBlock);
+
+                    break;
+                case this.P_VIEWBODY:
+                    //we assume the cdata block is our body including the tag
+                    resultNode = this._replaceBody(request, context, cDataBlock);
+                    if (resultNode) {
+                        pushOpRes(context, resultNode);
+                    }
+                    break;
+
+                default:
+                    resultNode = this.replaceHtmlItem(request, context, node.getAttribute('id'), cDataBlock);
+                    if (resultNode) {
+                        pushOpRes(context, resultNode);
+                    }
+                    break;
+            }
+        }
+
+        return true;
+    },
+
+    _pushOperationResult:function (context, resultNode) {
+        var mfInternal = context._mfInternal;
+        var pushSubnode = this._Lang.hitch(this, function (currNode) {
+            var parentForm = this._Dom.getParent(currNode, "form");
+            //if possible we work over the ids
+            //so that elements later replaced are referenced
+            //at the latest possibility
+            if (null != parentForm) {
+                mfInternal._updateForms.push(parentForm.id || parentForm);
+            }
+            else {
+                mfInternal._updateElems.push(currNode.id || currNode);
+            }
+        });
+        var isArr = 'undefined' != typeof resultNode.length && 'undefined' == typeof resultNode.nodeType;
+        if (isArr && resultNode.length) {
+            for (var cnt = 0; cnt < resultNode.length; cnt++) {
+                pushSubnode(resultNode[cnt]);
+            }
+        } else if (!isArr) {
+            pushSubnode(resultNode);
+        }
+
+    },
+
+    /**
+     * replaces a current head theoretically,
+     * pratically only the scripts are evaled anew since nothing else
+     * can be changed.
+     *
+     * @param request the current request
+     * @param context the ajax context
+     * @param newData the data to be processed
+     *
+     * @return an xml representation of the page for further processing if possible
+     */
+    _replaceHead:function (request, context, newData) {
+
+        var _Lang = this._Lang,
+                _Dom = this._Dom,
+                isWebkit = this._RT.browser.isWebKit,
+        //we have to work around an xml parsing bug in Webkit
+        //see https://issues.apache.org/jira/browse/MYFACES-3061
+                doc = (!isWebkit) ? _Lang.parseXML(newData) : null,
+                newHead = null;
+
+        if (!isWebkit && _Lang.isXMLParseError(doc)) {
+            doc = _Lang.parseXML(newData.replace(/<!\-\-[\s\n]*<!\-\-/g, "<!--").replace(/\/\/-->[\s\n]*\/\/-->/g, "//-->"));
+        }
+
+        if (isWebkit || _Lang.isXMLParseError(doc)) {
+            //the standard xml parser failed we retry with the stripper
+            var parser = new (this._RT.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
+            var headData = parser.parse(newData, "head");
+            //We cannot avoid it here, but we have reduced the parsing now down to the bare minimum
+            //for further processing
+            newHead = _Lang.parseXML("<head>" + headData + "</head>");
+            //last and slowest option create a new head element and let the browser
+            //do its slow job
+            if (_Lang.isXMLParseError(newHead)) {
+                try {
+                    newHead = _Dom.createElement("head");
+                    newHead.innerHTML = headData;
+                } catch (e) {
+                    //we give up no further fallbacks
+                    throw this._raiseError(new Error(), "Error head replacement failed reason:" + e.toString(), "_replaceHead");
+                }
+            }
+        } else {
+            //parser worked we go on
+            newHead = doc.getElementsByTagName("head")[0];
+        }
+
+        var oldTags = _Dom.findByTagNames(document.getElementsByTagName("head")[0], {"link":true, "style":true});
+        _Dom.runCss(newHead, true);
+        _Dom.deleteItems(oldTags);
+
+        //var oldTags = _Dom.findByTagNames(document.getElementsByTagName("head")[0], {"script": true});
+        //_Dom.deleteScripts(oldTags);
+        _Dom.runScripts(newHead, true);
+
+        return doc;
+    },
+
+    /**
+     * special method to handle the body dom manipulation,
+     * replacing the entire body does not work fully by simply adding a second body
+     * and by creating a range instead we have to work around that by dom creating a second
+     * body and then filling it properly!
+     *
+     * @param {Object} request our request object
+     * @param {Object} context (Map) the response context
+     * @param {String} newData the markup which replaces the old dom node!
+     * @param {Node} parsedData (optional) preparsed XML representation data of the current document
+     */
+    _replaceBody:function (request, context, newData /*varargs*/) {
+        var _RT = this._RT,
+                _Dom = this._Dom,
+                _Lang = this._Lang,
+
+                oldBody = document.getElementsByTagName("body")[0],
+                placeHolder = document.createElement("div"),
+                isWebkit = _RT.browser.isWebKit;
+
+        placeHolder.id = "myfaces_bodyplaceholder";
+
+        _Dom._removeChildNodes(oldBody);
+        oldBody.innerHTML = "";
+        oldBody.appendChild(placeHolder);
+
+        var bodyData, doc = null, parser;
+
+        //we have to work around an xml parsing bug in Webkit
+        //see https://issues.apache.org/jira/browse/MYFACES-3061
+        if (!isWebkit) {
+            doc = (arguments.length > 3) ? arguments[3] : _Lang.parseXML(newData);
+        }
+
+        if (!isWebkit && _Lang.isXMLParseError(doc)) {
+            doc = _Lang.parseXML(newData.replace(/<!\-\-[\s\n]*<!\-\-/g, "<!--").replace(/\/\/-->[\s\n]*\/\/-->/g, "//-->"));
+        }
+
+        if (isWebkit || _Lang.isXMLParseError(doc)) {
+            //the standard xml parser failed we retry with the stripper
+
+            parser = new (_RT.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
+
+            bodyData = parser.parse(newData, "body");
+        } else {
+            //parser worked we go on
+            var newBodyData = doc.getElementsByTagName("body")[0];
+
+            //speedwise we serialize back into the code
+            //for code reduction, speedwise we will take a small hit
+            //there which we will clean up in the future, but for now
+            //this is ok, I guess, since replace body only is a small subcase
+            //bodyData = _Lang.serializeChilds(newBodyData);
+            var browser = _RT.browser;
+            if (!browser.isIEMobile || browser.isIEMobile >= 7) {
+                //TODO check what is failing there
+                for (var cnt = 0; cnt < newBodyData.attributes.length; cnt++) {
+                    var value = newBodyData.attributes[cnt].value;
+                    if (value)
+                        _Dom.setAttribute(oldBody, newBodyData.attributes[cnt].name, value);
+                }
+            }
+        }
+        //we cannot serialize here, due to escape problems
+        //we must parse, this is somewhat unsafe but should be safe enough
+        parser = new (_RT.getGlobalConfig("updateParser", myfaces._impl._util._HtmlStripper))();
+        bodyData = parser.parse(newData, "body");
+
+        var returnedElement = this.replaceHtmlItem(request, context, placeHolder, bodyData);
+
+        if (returnedElement) {
+            this._pushOperationResult(context, returnedElement);
+        }
+        return returnedElement;
+    },
+
+    /**
+     * Replaces HTML elements through others and handle errors if the occur in the replacement part
+     *
+     * @param {Object} request (xhrRequest)
+     * @param {Object} context (Map)
+     * @param {Object} itemIdToReplace (String|Node) - ID of the element to replace
+     * @param {String} markup - the new tag
+     */
+    replaceHtmlItem:function (request, context, itemIdToReplace, markup) {
+        var _Lang = this._Lang, _Dom = this._Dom;
+
+        var item = (!_Lang.isString(itemIdToReplace)) ? itemIdToReplace :
+                _Dom.byIdOrName(itemIdToReplace);
+
+        if (!item) {
+            throw this._raiseError(new Error(), _Lang.getMessage("ERR_ITEM_ID_NOTFOUND", null, "_AjaxResponse.replaceHtmlItem", (itemIdToReplace) ? itemIdToReplace.toString() : "undefined"), "replaceHtmlItem");
+        }
+        return _Dom.outerHTML(item, markup, this._RT.getLocalOrGlobalConfig(context, "preserveFocus", false));
+    },
+
+    /**
+     * xml insert command handler
+     *
+     * @param request the ajax request element
+     * @param context the context element holding the data
+     * @param node the xml node holding the insert data
+     * @return true upon successful completion, false otherwise
+     *
+     **/
+    processInsert:function (request, context, node) {
+        /*remapping global namespaces for speed and readability reasons*/
+        var _Dom = this._Dom,
+                _Lang = this._Lang,
+        //determine which path to go:
+                insertData = this._parseInsertData(request, context, node);
+
+        if (!insertData) return false;
+
+        var opNode = _Dom.byIdOrName(insertData.opId);
+        if (!opNode) {
+            throw this._raiseError(new Error(), _Lang.getMessage("ERR_PPR_INSERTBEFID_1", null, "_AjaxResponse.processInsert", insertData.opId), "processInsert");
+        }
+
+        //call insertBefore or insertAfter in our dom routines
+        var replacementFragment = _Dom[insertData.insertType](opNode, insertData.cDataBlock);
+        if (replacementFragment) {
+            this._pushOperationResult(context, replacementFragment);
+        }
+        return true;
+    },
+
+    /**
+     * determines the corner data from the insert tag parsing process
+     *
+     *
+     * @param request request
+     * @param context context
+     * @param node the current node pointing to the insert tag
+     * @return false if the parsing failed, otherwise a map with follwing attributes
+     * <ul>
+     *     <li>inserType - a ponter to a constant which maps the direct function name for the insert operation </li>
+     *     <li>opId - the before or after id </li>
+     *     <li>cDataBlock - the html cdata block which needs replacement </li>
+     * </ul>
+     *
+     * TODO we have to find a mechanism to replace the direct sendError calls with a javascript exception
+     * which we then can use for cleaner error code handling
+     */
+    _parseInsertData:function (request, context, node) {
+        var _Lang = this._Lang,
+                _Dom = this._Dom,
+                concatCDATA = _Dom.concatCDATABlocks,
+
+                INSERT_TYPE_BEFORE = "insertBefore",
+                INSERT_TYPE_AFTER = "insertAfter",
+
+                id = node.getAttribute("id"),
+                beforeId = node.getAttribute("before"),
+                afterId = node.getAttribute("after"),
+                ret = {};
+
+        //now we have to make a distinction between two different parsing paths
+        //due to a spec malalignment
+        //a <insert id="... beforeId|AfterId ="...
+        //b <insert><before id="..., <insert> <after id="....
+        //see https://issues.apache.org/jira/browse/MYFACES-3318
+        //simple id, case1
+        if (id && beforeId && !afterId) {
+            ret.insertType = INSERT_TYPE_BEFORE;
+            ret.opId = beforeId;
+            ret.cDataBlock = concatCDATA(node);
+
+            //<insert id=".. afterId="..
+        } else if (id && !beforeId && afterId) {
+            ret.insertType = INSERT_TYPE_AFTER;
+            ret.opId = afterId;
+            ret.cDataBlock = concatCDATA(node);
+
+            //<insert><before id="... <insert><after id="...
+        } else if (!id) {
+            var opType = node.childNodes[0].tagName;
+
+            if (opType != "before" && opType != "after") {
+                throw this._raiseError(new Error(), _Lang.getMessage("ERR_PPR_INSERTBEFID"), "_parseInsertData");
+            }
+            opType = opType.toLowerCase();
+            var beforeAfterId = node.childNodes[0].getAttribute("id");
+            ret.insertType = (opType == "before") ? INSERT_TYPE_BEFORE : INSERT_TYPE_AFTER;
+            ret.opId = beforeAfterId;
+            ret.cDataBlock = concatCDATA(node.childNodes[0]);
+        } else {
+            throw this._raiseError(new Error(), [_Lang.getMessage("ERR_PPR_IDREQ"),
+                                                 "\n ",
+                                                 _Lang.getMessage("ERR_PPR_INSERTBEFID")].join(""), "_parseInsertData");
+        }
+        ret.opId = _Lang.trim(ret.opId);
+        return ret;
+    },
+
+    processDelete:function (request, context, node) {
+
+        var _Lang = this._Lang,
+                _Dom = this._Dom,
+                deleteId = node.getAttribute('id');
+
+        if (!deleteId) {
+            throw this._raiseError(new Error(), _Lang.getMessage("ERR_PPR_UNKNOWNCID", null, "_AjaxResponse.processDelete", ""), "processDelete");
+        }
+
+        var item = _Dom.byIdOrName(deleteId);
+        if (!item) {
+            throw this._raiseError(new Error(), _Lang.getMessage("ERR_PPR_UNKNOWNCID", null, "_AjaxResponse.processDelete", deleteId), "processDelete");
+        }
+
+        var parentForm = this._Dom.getParent(item, "form");
+        if (null != parentForm) {
+            context._mfInternal._updateForms.push(parentForm);
+        }
+        _Dom.deleteItem(item);
+
+        return true;
+    },
+
+    processAttributes:function (request, context, node) {
+        //we now route into our attributes function to bypass
+        //IE quirks mode incompatibilities to the biggest possible extent
+        //most browsers just have to do a setAttributes but IE
+        //behaves as usual not like the official standard
+        //myfaces._impl._util.this._Dom.setAttribute(domNode, attribute, value;
+
+        var _Lang = this._Lang,
+        //<attributes id="id of element"> <attribute name="attribute name" value="attribute value" />* </attributes>
+                elemId = node.getAttribute('id');
+
+        if (!elemId) {
+            throw this._raiseError(new Error(), "Error in attributes, id not in xml markup", "processAttributes");
+        }
+        var childNodes = node.childNodes;
+
+        if (!childNodes) {
+            return false;
+        }
+        for (var loop2 = 0; loop2 < childNodes.length; loop2++) {
+            var attributesNode = childNodes[loop2],
+                    attrName = attributesNode.getAttribute("name"),
+                    attrValue = attributesNode.getAttribute("value");
+
+            if (!attrName) {
+                continue;
+            }
+
+            attrName = _Lang.trim(attrName);
+            /*no value means reset*/
+            //value can be of boolean value hence full check
+            if ('undefined' == typeof attrValue || null == attrValue) {
+                attrValue = "";
+            }
+
+            switch (elemId) {
+                case this.P_VIEWROOT:
+                    throw  this._raiseError(new Error(), _Lang.getMessage("ERR_NO_VIEWROOTATTR", null, "_AjaxResponse.processAttributes"), "processAttributes");
+
+                case this.P_VIEWHEAD:
+                    throw  this._raiseError(new Error(), _Lang.getMessage("ERR_NO_HEADATTR", null, "_AjaxResponse.processAttributes"), "processAttributes");
+
+                case this.P_VIEWBODY:
+                    var element = document.getElementsByTagName("body")[0];
+                    this._Dom.setAttribute(element, attrName, attrValue);
+                    break;
+
+                default:
+                    this._Dom.setAttribute(document.getElementById(elemId), attrName, attrValue);
+                    break;
+            }
+        }
+        return true;
+    },
+
+    /**
+     * internal helper which raises an error in the
+     * format we need for further processing
+     *
+     * @param message the message
+     * @param title the title of the error (optional)
+     * @param name the name of the error (optional)
+     */
+    _raiseError:function (error, message, caller, title, name) {
+        var _Impl = this.attr("impl");
+        var finalTitle = title || _Impl.MALFORMEDXML;
+        var finalName = name || _Impl.MALFORMEDXML;
+        var finalMessage = message || "";
+
+        return this._Lang.makeException(error, finalTitle, finalName, this._nameSpace, caller || ( (arguments.caller) ? arguments.caller.toString() : "_raiseError"), finalMessage);
+    }
+});
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name _Transports
+ * @memberOf myfaces._impl.xhrCore
+ * @description
+ *
+ * The xhr core adapter
+ * which provides the transport mechanisms to the calling
+ * objects, and controls the queue behavior, the error handling
+ * and partial page submit functionality among other things
+ * <p />
+ * The idea behind this is to make the ajax request object as barebones
+ * as possible and shift the extra functionality like queuing
+ * parameter handling etc... to this class so that our transports become more easily
+ * pluggable. This should keep the path open to iframe submits and other transport layers
+ * <p />
+ * the call to the corresponding transport just should be a
+ * transport.xhrQueuedPost <br />
+ * or transport.xhrPost,transport.xhrGet  etc... in the future
+ * <p />
+ * Note we have taken a pattern lesson or two from the dojo toolkit and its excellent handling
+ * of transports by our patterns here (which is mainly a centralized transport singleton which routes
+ * to different transport implementations and the auto passing of parameters into their
+ * corresponding protected attributes on class level in the transports themselves)
+ */
+_MF_SINGLTN(_PFX_XHR + "_Transports", _MF_OBJECT,
+        /** @lends myfaces._impl.xhrCore._Transports.prototype */ {
+
+    _PAR_ERRORLEVEL:"errorlevel",
+    _PAR_QUEUESIZE:"queuesize",
+    _PAR_PPS:"pps",
+    _PAR_TIMEOUT:"timeout",
+    _PAR_DELAY:"delay",
+
+
+    /**
+     * a singleton queue
+     * note the structure of our inheritance
+     * is that that _queue is attached to prototype
+     * and hence the pointer to the request qeue
+     * is shared over all instances
+     *
+     * if you need to have it per instance for complex objects
+     * you have to initialize in the constructor
+     *
+     * (This is the same limitation dojo class inheritance
+     * where our inheritance pattern is derived from has)
+     */
+    _q: new myfaces._impl.xhrCore._AjaxRequestQueue(),
+
+    /**
+     * xhr post with enqueuing as defined by the jsf 2.0 specification
+     *
+     * mapped options already have the exec and view properly in place
+     * myfaces specifics can be found under mappedOptions.myFaces
+     * @param {Node} source the source of this call
+     * @param {Node} sourceForm the html form which is the source of this call
+     * @param {Object} context (Map) the internal pass through context
+     * @param {Object} passThrgh (Map) values to be passed through
+     **/
+    xhrQueuedPost : function(source, sourceForm, context, passThrgh) {
+        context._mfInternal.xhrOp = "xhrQueuedPost";
+        this._q.enqueue(
+                new (this._getAjaxReqClass(context))(this._getArguments(source, sourceForm, context, passThrgh)));
+    },
+
+    /**
+      * iframe queued post
+      *
+      * mapped options already have the exec and view properly in place
+      * myfaces specifics can be found under mappedOptions.myFaces
+      * @param {Node} source the source of this call
+      * @param {Node} sourceForm the html form which is the source of this call
+      * @param {Object} context (Map) the internal pass through context
+      * @param {Object} passThrgh (Map) values to be passed through
+      **/
+     multipartQueuedPost : function(source, sourceForm, context, passThrgh) {
+         context._mfInternal.xhrOp = "multipartQueuedPost";
+         var args = this._getArguments(source, sourceForm, context, passThrgh);
+         // note in get the timeout is not working delay however is and queue size as well
+         // since there are no cross browser ways to resolve a timeout on xhr level
+         this._q.enqueue(
+                 new (this._getMultipartReqClass(context))(args));
+     },
+
+
+    /**
+     * creates the arguments map and
+     * fetches the config params in a proper way in to
+     * deal with them in a flat way (from the nested context way)
+     *
+     * @param source the source of the request
+     * @param sourceForm the sourceform
+     * @param context   the context holding all values
+     * @param passThrgh the passThrough values to be blended into the response
+     */
+    _getArguments: function(source, sourceForm, context, passThrgh) {
+        var _RT = myfaces._impl.core._Runtime,
+        /** @ignore */
+             _Lang = myfaces._impl._util._Lang,
+             applyCfg = _Lang.hitch(this, this._applyConfig),
+            //RT does not have this references, hence no hitch needed
+             getCfg = _RT.getLocalOrGlobalConfig,
+
+
+            ret = {
+                "source": source,
+                "sourceForm": sourceForm,
+                "context": context,
+                "passThrough": passThrgh,
+                "xhrQueue": this._q
+            };
+
+        //we now mix in the config settings which might either be set globally
+        //or pushed in under the context myfaces.<contextValue> into the current request
+        applyCfg(ret, context, "alarmThreshold", this._PAR_ERRORLEVEL);
+        applyCfg(ret, context, "queueSize", this._PAR_QUEUESIZE);
+        //TODO timeout probably not needed anymore
+        applyCfg(ret, context, "timeout", this._PAR_TIMEOUT);
+        //applyCfg(ret, context, "delay", this._PAR_DELAY);
+
+        //now partial page submit needs a different treatment
+        //since pps == execute strings
+        if (getCfg(context, this._PAR_PPS, false)
+                && _Lang.exists(passThrgh, myfaces._impl.core.Impl.P_EXECUTE)
+                && passThrgh[myfaces._impl.core.Impl.P_EXECUTE].length > 0) {
+            ret['partialIdsArray'] = passThrgh[myfaces._impl.core.Impl.P_EXECUTE].split(" ");
+        }
+        return ret;
+    },
+
+    /**
+     * helper method to apply a config setting to our varargs param list
+     *
+     * @param destination the destination map to receive the setting
+     * @param context the current context
+     * @param destParm the destination param of the destination map
+     * @param srcParm the source param which is the key to our config setting
+     */
+    _applyConfig: function(destination, context, destParm, srcParm) {
+        var _RT = myfaces._impl.core._Runtime;
+        /** @ignore */
+        var _getConfig = _RT.getLocalOrGlobalConfig;
+        if (_getConfig(context, srcParm, null) != null) {
+            destination[destParm] = _getConfig(context, srcParm, null);
+        }
+    },
+
+    /**
+     * centralized transport switching helper
+     * for the multipart submit case
+     *
+     * @param context the context which is passed down
+     */
+    _getMultipartReqClass: function(context) {
+       if (this._RT.getXHRLvl() >= 2) {
+            return myfaces._impl.xhrCore._MultipartAjaxRequestLevel2;
+       } else {
+            return myfaces._impl.xhrCore._IFrameRequest;
+       }
+    },
+
+
+    _getAjaxReqClass: function(context) {
+        // var _RT = myfaces._impl.core._Runtime;
+        if(this._RT.getXHRLvl() < 2) {
+           return myfaces._impl.xhrCore._AjaxRequest;
+        } else {
+           return myfaces._impl.xhrCore._AjaxRequestLevel2;
+        }
+    }
+
+});
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name _Transports
+ * @memberOf myfaces._impl.xhrCore
+ * @description
+ *
+ * The xhr core adapter
+ * which provides the transport mechanisms to the calling
+ * objects, and controls the queue behavior, the error handling
+ * and partial page submit functionality among other things
+ * <p />
+ * The idea behind this is to make the ajax request object as barebones
+ * as possible and shift the extra functionality like queuing
+ * parameter handling etc... to this class so that our transports become more easily
+ * pluggable. This should keep the path open to iframe submits and other transport layers
+ * <p />
+ * the call to the corresponding transport just should be a
+ * transport.xhrQueuedPost <br />
+ * or transport.xhrPost,transport.xhrGet  etc... in the future
+ * <p />
+ * Note we have taken a pattern lesson or two from the dojo toolkit and its excellent handling
+ * of transports by our patterns here (which is mainly a centralized transport singleton which routes
+ * to different transport implementations and the auto passing of parameters into their
+ * corresponding protected attributes on class level in the transports themselves)
+ */
+_MF_SINGLTN(_PFX_XHR+"_ExtTransports" , myfaces._impl.xhrCore._Transports,
+     /** @lends myfaces._impl.xhrCore._Transports.prototype */ {
+
+
+    constructor_: function() {
+        this._callSuper("constructor_");
+        myfaces._impl.xhrCore._Transports = this;
+        //we change the transport to our new implementation
+        this.updateSingletons("transport", this);
+    },
+
+    /**
+     * a simple not enqueued xhr post
+     *
+     * mapped options already have the exec and view properly in place
+     * myfaces specifics can be found under mappedOptions.myFaces
+     * @param {Node} source the source of this call
+     * @param {Node} sourceForm the html form which is the source of this call
+     * @param {Object} context (Map) the internal pass through context
+     * @param {Object} passThrgh (Map) values to be passed through
+     **/
+    xhrPost : function(source, sourceForm, context, passThrgh) {
+        context._mfInternal.xhrOp = "xhrPost";
+        var args = this._getArguments(source, sourceForm, context, passThrgh);
+         delete args.xhrQueue;
+        (new (this._getAjaxReqClass(context))(args)).send();
+    },
+
+
+    /**
+     * xhr get without enqueuing
+     *
+     * mapped options already have the exec and view properly in place
+     * myfaces specifics can be found under mappedOptions.myFaces
+     * @param {Node} source the source of this call
+     * @param {Node} sourceForm the html form which is the source of this call
+     * @param {Object} context (Map) the internal pass through context
+     * @param {Object} passThrgh (Map) values to be passed through
+     **/
+    xhrGet : function(source, sourceForm, context, passThrgh) {
+        context._mfInternal.xhrOp = "xhrGet";
+        var args = this._getArguments(source, sourceForm, context, passThrgh);
+        // note in get the timeout is not working delay however is and queue size as well
+        // since there are no cross browser ways to resolve a timeout on xhr level
+        // we have to live with it
+        args.ajaxType = "GET";
+        delete args.xhrQueue;
+        (new (this._getAjaxReqClass(context))(args)).send();
+    },
+
+    /**
+     * xhr get which takes the existing queue into consideration to by synchronized
+     * to previous queued post requests
+     *
+     * mapped options already have the exec and view properly in place
+     * myfaces specifics can be found under mappedOptions.myFaces
+     * @param {Node} source the source of this call
+     * @param {Node} sourceForm the html form which is the source of this call
+     * @param {Object} context (Map) the internal pass through context
+     * @param {Object} passThrgh (Map) values to be passed through
+     **/
+    xhrQueuedGet : function(source, sourceForm, context, passThrgh) {
+        context._mfInternal.xhrOp = "xhrQueuedGet";
+        var args = this._getArguments(source, sourceForm, context, passThrgh);
+        // note in get the timeout is not working delay however is and queue size as well
+        // since there are no cross browser ways to resolve a timeout on xhr level
+        // we have to live with it
+        args.ajaxType = "GET";
+        this._q.enqueue(
+                new (this._getAjaxReqClass(context))(args));
+    },
+
+
+    /**
+     * iframe post without queueing
+     *
+     * mapped options already have the exec and view properly in place
+     * myfaces specifics can be found under mappedOptions.myFaces
+     * @param {Node} source the source of this call
+     * @param {Node} sourceForm the html form which is the source of this call
+     * @param {Object} context (Map) the internal pass through context
+     * @param {Object} passThrgh (Map) values to be passed through
+     **/
+    multipartPost : function(source, sourceForm, context, passThrgh) {
+        context._mfInternal.xhrOp = "multipartPost";
+        var args = this._getArguments(source, sourceForm, context, passThrgh);
+        // note in get the timeout is not working delay however is and queue size as well
+        // since there are no cross browser ways to resolve a timeout on xhr level
+        // we have to live with it
+        delete args.xhrQueue;
+        (new (this._getMultipartReqClass(context))(args)).send();
+    },
+
+
+    /**
+     * iframe get without queueing
+     *
+     * mapped options already have the exec and view properly in place
+     * myfaces specifics can be found under mappedOptions.myFaces
+     * @param {Node} source the source of this call
+     * @param {Node} sourceForm the html form which is the source of this call
+     * @param {Object} context (Map) the internal pass through context
+     * @param {Object} passThrgh (Map) values to be passed through
+     **/
+    multipartGet : function(source, sourceForm, context, passThrgh) {
+        context._mfInternal.xhrOp = "multiPartGet";
+        var args = this._getArguments(source, sourceForm, context, passThrgh);
+        // note in get the timeout is not working delay however is and queue size as well
+        // since there are no cross browser ways to resolve a timeout on xhr level
+        // we have to live with it
+        args.ajaxType = "GET";
+        delete args.xhrQueue;
+        (new (this._getMultipartReqClass(context))(args)).send();
+    },
+
+    /**
+     * iframe queued http get
+     *
+     * mapped options already have the exec and view properly in place
+     * myfaces specifics can be found under mappedOptions.myFaces
+     * @param {Node} source the source of this call
+     * @param {Node} sourceForm the html form which is the source of this call
+     * @param {Object} context (Map) the internal pass through context
+     * @param {Object} passThrgh (Map) values to be passed through
+     **/
+    multipartQueuedGet : function(source, sourceForm, context, passThrgh) {
+        context._mfInternal.xhrOp = "multipartQueuedGet";
+        var args = this._getArguments(source, sourceForm, context, passThrgh);
+        // note in get the timeout is not working delay however is and queue size as well
+        // since there are no cross browser ways to resolve a timeout on xhr level
+        args.ajaxType = "GET";
+        this._q.enqueue(
+                new (this._getMultipartReqClass(context))(args));
+    }
+});
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @class
+ * @name Impl
+ * @memberOf myfaces._impl.core
+ * @description Implementation singleton which implements all interface method
+ * defined by our jsf.js API
+ * */
+_MF_SINGLTN(_PFX_CORE + "Impl", _MF_OBJECT, /**  @lends myfaces._impl.core.Impl.prototype */ {
+
+    //third option myfaces._impl.xhrCoreAjax which will be the new core impl for now
+    _transport:myfaces._impl.core._Runtime.getGlobalConfig("transport", myfaces._impl.xhrCore._Transports),
+
+    /**
+     * external event listener queue!
+     */
+    _evtListeners:new (myfaces._impl.core._Runtime.getGlobalConfig("eventListenerQueue", myfaces._impl._util._ListenerQueue))(),
+
+    /**
+     * external error listener queue!
+     */
+    _errListeners:new (myfaces._impl.core._Runtime.getGlobalConfig("errorListenerQueue", myfaces._impl._util._ListenerQueue))(),
+
+    /*CONSTANTS*/
+
+    /*internal identifiers for options*/
+    IDENT_ALL:"@all",
+    IDENT_NONE:"@none",
+    IDENT_THIS:"@this",
+    IDENT_FORM:"@form",
+
+    /*
+     * [STATIC] constants
+     */
+
+    P_PARTIAL_SOURCE:"javax.faces.source",
+    P_VIEWSTATE:"javax.faces.ViewState",
+    P_CLIENTWINDOW:"javax.faces.ClientWindow",
+    P_AJAX:"javax.faces.partial.ajax",
+    P_EXECUTE:"javax.faces.partial.execute",
+    P_RENDER:"javax.faces.partial.render",
+    P_EVT:"javax.faces.partial.event",
+    P_WINDOW_ID:"javax.faces.ClientWindow",
+    P_RESET_VALUES:"javax.faces.partial.resetValues",
+
+    /* message types */
+    ERROR:"error",
+    EVENT:"event",
+
+    /* event emitting stages */
+    BEGIN:"begin",
+    COMPLETE:"complete",
+    SUCCESS:"success",
+
+    /*ajax errors spec 14.4.2*/
+    HTTPERROR:"httpError",
+    EMPTY_RESPONSE:"emptyResponse",
+    MALFORMEDXML:"malformedXML",
+    SERVER_ERROR:"serverError",
+    CLIENT_ERROR:"clientError",
+    TIMEOUT_EVENT:"timeout",
+
+    /*error reporting threshold*/
+    _threshold:"ERROR",
+
+    /*blockfilter for the passthrough filtering, the attributes given here
+     * will not be transmitted from the options into the passthrough*/
+    _BLOCKFILTER:{onerror:1, onevent:1, render:1, execute:1, myfaces:1, delay:1, resetValues:1},
+
+    /**
+     * collect and encode data for a given form element (must be of type form)
+     * find the javax.faces.ViewState element and encode its value as well!
+     * return a concatenated string of the encoded values!
+     *
+     * @throws Error in case of the given element not being of type form!
+     * https://issues.apache.org/jira/browse/MYFACES-2110
+     */
+    getViewState:function (form) {
+        /**
+         *  typecheck assert!, we opt for strong typing here
+         *  because it makes it easier to detect bugs
+         */
+        if (form) {
+            form = this._Lang.byId(form);
+        }
+
+        if (!form
+                || !form.nodeName
+                || form.nodeName.toLowerCase() != "form") {
+            throw new Error(this._Lang.getMessage("ERR_VIEWSTATE"));
+        }
+
+        var ajaxUtils = myfaces._impl.xhrCore._AjaxUtils;
+
+        var ret = this._Lang.createFormDataDecorator([]);
+        ajaxUtils.encodeSubmittableFields(ret, form, null);
+
+        return ret.makeFinal();
+    },
+
+    /**
+     * this function has to send the ajax requests
+     *
+     * following request conditions must be met:
+     * <ul>
+     *  <li> the request must be sent asynchronously! </li>
+     *  <li> the request must be a POST!!! request </li>
+     *  <li> the request url must be the form action attribute </li>
+     *  <li> all requests must be queued with a client side request queue to ensure the request ordering!</li>
+     * </ul>
+     *
+     * @param {String|Node} elem any dom element no matter being it html or jsf, from which the event is emitted
+     * @param {|Event|} event any javascript event supported by that object
+     * @param {|Object|} options  map of options being pushed into the ajax cycle
+     *
+     *
+     * a) transformArguments out of the function
+     * b) passThrough handling with a map copy with a filter map block map
+     */
+    request:function (elem, event, options) {
+        if (this._delayTimeout) {
+            clearTimeout(this._delayTimeout);
+            delete this._delayTimeout;
+        }
+        /*namespace remap for our local function context we mix the entire function namespace into
+         *a local function variable so that we do not have to write the entire namespace
+         *all the time
+         **/
+        var _Lang = this._Lang,
+                _Dom = this._Dom;
+        /*assert if the onerror is set and once if it is set it must be of type function*/
+        _Lang.assertType(options.onerror, "function");
+        /*assert if the onevent is set and once if it is set it must be of type function*/
+        _Lang.assertType(options.onevent, "function");
+
+        //options not set we define a default one with nothing
+        options = options || {};
+
+        /**
+         * we cross reference statically hence the mapping here
+         * the entire mapping between the functions is stateless
+         */
+        //null definitely means no event passed down so we skip the ie specific checks
+        if ('undefined' == typeof event) {
+            event = window.event || null;
+        }
+
+        //improve the error messages if an empty elem is passed
+        if (!elem) {
+            throw _Lang.makeException(new Error(), "ArgNotSet", null, this._nameSpace, "request", _Lang.getMessage("ERR_MUST_BE_PROVIDED1", "{0}: source  must be provided", "jsf.ajax.request", "source element id"));
+        }
+        var oldElem = elem;
+        elem = _Dom.byIdOrName(elem);
+        if (!elem) {
+            throw _Lang.makeException(new Error(), "Notfound", null, this._nameSpace, "request", _Lang.getMessage("ERR_PPR_UNKNOWNCID", "{0}: Node with id {1} could not be found from source", this._nameSpace + ".request", oldElem));
+        }
+
+        var elementId = _Dom.nodeIdOrName(elem);
+
+        /*
+         * We make a copy of our options because
+         * we should not touch the incoming params!
+         * this copy is also the pass through parameters
+         * which are sent down our request
+         */
+        var passThrgh = _Lang.mixMaps({}, options, true, this._BLOCKFILTER);
+
+        if (event) {
+            passThrgh[this.P_EVT] = event.type;
+        }
+
+        /**
+         * ajax pass through context with the source
+         * onevent and onerror
+         */
+        var context = {
+            source:elem,
+            onevent:options.onevent,
+            onerror:options.onerror,
+
+            //TODO move the myfaces part into the _mfInternal part
+            myfaces:options.myfaces,
+            _mfInternal:{}
+        };
+        //additional meta information to speed things up, note internal non jsf
+        //pass through options are stored under _mfInternal in the context
+        var mfInternal = context._mfInternal;
+
+        /**
+         * fetch the parent form
+         *
+         * note we also add an override possibility here
+         * so that people can use dummy forms and work
+         * with detached objects
+         */
+        var form = (options.myfaces && options.myfaces.form) ?
+                _Lang.byId(options.myfaces.form) :
+                this._getForm(elem, event);
+
+        /**
+         * JSF2.2 client window must be part of the issuing form so it is encoded
+         * automatically in the request
+         */
+        //we set the client window before encoding by a call to jsf.getClientWindow
+        var clientWindow = jsf.getClientWindow(form);
+        //in case someone decorates the getClientWindow we reset the value from
+        //what we are getting
+        if ('undefined' != typeof clientWindow && null != clientWindow) {
+            var formElem = _Dom.getNamedElementFromForm(form, this.P_CLIENTWINDOW);
+            if (formElem) {
+                //we store the value for later processing during the ajax phase
+                //job so that we do not get double values
+                context._mfInternal._clientWindow = jsf.getClientWindow(form);
+            } else {
+                passThrgh[this.P_CLIENTWINDOW] = jsf.getClientWindow(form);
+            }
+        } /*  spec proposal
+        else {
+            var formElem = _Dom.getNamedElementFromForm(form, this.P_CLIENTWINDOW);
+            if (formElem) {
+                context._mfInternal._clientWindow = "undefined";
+            } else {
+                passThrgh[this.P_CLIENTWINDOW] = "undefined";
+            }
+        }
+        */
+
+        /**
+         * binding contract the javax.faces.source must be set
+         */
+        passThrgh[this.P_PARTIAL_SOURCE] = elementId;
+
+        /**
+         * javax.faces.partial.ajax must be set to true
+         */
+        passThrgh[this.P_AJAX] = true;
+
+        /**
+         * if resetValues is set to true
+         * then we have to set javax.faces.resetValues as well
+         * as pass through parameter
+         * the value has to be explicitly true, according to
+         * the specs jsdoc
+         */
+        if(options.resetValues === true) {
+            passThrgh[this.P_RESET_VALUES] = true;
+        }
+
+        if (options.execute) {
+            /*the options must be a blank delimited list of strings*/
+            /*compliance with Mojarra which automatically adds @this to an execute
+             * the spec rev 2.0a however states, if none is issued nothing at all should be sent down
+             */
+            options.execute = (options.execute.indexOf("@this") == -1) ? options.execute : options.execute;
+
+            this._transformList(passThrgh, this.P_EXECUTE, options.execute, form, elementId);
+        } else {
+            passThrgh[this.P_EXECUTE] = elementId;
+        }
+
+        if (options.render) {
+            this._transformList(passThrgh, this.P_RENDER, options.render, form, elementId);
+        }
+
+        /**
+         * multiple transports upcoming jsf 2.x feature currently allowed
+         * default (no value) xhrQueuedPost
+         *
+         * xhrQueuedPost
+         * xhrPost
+         * xhrGet
+         * xhrQueuedGet
+         * iframePost
+         * iframeQueuedPost
+         *
+         */
+        var transportType = this._getTransportType(context, passThrgh, form);
+
+        mfInternal["_mfSourceFormId"] = form.id;
+        mfInternal["_mfSourceControlId"] = elementId;
+        mfInternal["_mfTransportType"] = transportType;
+
+        //mojarra compatibility, mojarra is sending the form id as well
+        //this is not documented behavior but can be determined by running
+        //mojarra under blackbox conditions
+        //i assume it does the same as our formId_submit=1 so leaving it out
+        //wont hurt but for the sake of compatibility we are going to add it
+        passThrgh[form.id] = form.id;
+
+        /* jsf2.2 only: options.delay || */
+        var delayTimeout = options.delay || this._RT.getLocalOrGlobalConfig(context, "delay", false);
+        if (delayTimeout) {
+            if (this._delayTimeout) {
+                clearTimeout(this._delayTimeout);
+            }
+            this._delayTimeout = setTimeout(_Lang.hitch(this, function () {
+                this._transport[transportType](elem, form, context, passThrgh);
+                this._delayTimeout = null;
+            }), parseInt(delayTimeout));
+        } else {
+            this._transport[transportType](elem, form, context, passThrgh);
+        }
+    },
+
+    /**
+     * fetches the form in an unprecise manner depending
+     * on an element or event target
+     *
+     * @param elem
+     * @param event
+     */
+    _getForm:function (elem, event) {
+        var _Dom = this._Dom;
+        var _Lang = this._Lang;
+        var form = _Dom.fuzzyFormDetection(elem);
+
+        if (!form && event) {
+            //in case of no form is given we retry over the issuing event
+            form = _Dom.fuzzyFormDetection(_Lang.getEventTarget(event));
+            if (!form) {
+                throw _Lang.makeException(new Error(), null, null, this._nameSpace, "_getForm", _Lang.getMessage("ERR_FORM"));
+            }
+        } else if (!form) {
+            throw _Lang.makeException(new Error(), null, null, this._nameSpace, "_getForm", _Lang.getMessage("ERR_FORM"));
+
+        }
+        return form;
+    },
+
+    /**
+     * determines the transport type to be called
+     * for the ajax call
+     *
+     * @param context the context
+     * @param passThrgh  pass through values
+     * @param form the form which issues the request
+     */
+    _getTransportType:function (context, passThrgh, form) {
+        /**
+         * if execute or render exist
+         * we have to pass them down as a blank delimited string representation
+         * of an array of ids!
+         */
+        //for now we turn off the transport auto selection, to enable 2.0 backwards compatibility
+        //on protocol level, the file upload only can be turned on if the auto selection is set to true
+        var getConfig = this._RT.getLocalOrGlobalConfig,
+                _Lang = this._Lang,
+                _Dom = this._Dom;
+
+        var transportAutoSelection = getConfig(context, "transportAutoSelection", true);
+        /*var isMultipart = (transportAutoSelection && _Dom.getAttribute(form, "enctype") == "multipart/form-data") ?
+         _Dom.isMultipartCandidate((!getConfig(context, "pps",false))? form : passThrgh[this.P_EXECUTE]) :
+         false;
+         **/
+        if (!transportAutoSelection) {
+            return getConfig(context, "transportType", "xhrQueuedPost");
+        }
+        var multiPartCandidate = _Dom.isMultipartCandidate((!getConfig(context, "pps", false)) ?
+                form : passThrgh[this.P_EXECUTE]);
+        var multipartForm = (_Dom.getAttribute(form, "enctype") || "").toLowerCase() == "multipart/form-data";
+        //spec section jsdoc, if we have a multipart candidate in our execute (aka fileupload)
+        //and the form is not multipart then we have to raise an error
+        if (multiPartCandidate && !multipartForm) {
+            throw _Lang.makeException(new Error(), null, null, this._nameSpace, "_getTransportType", _Lang.getMessage("ERR_NO_MULTIPART_FORM", "No Multipart form", form.id));
+        }
+        var isMultipart = multiPartCandidate && multipartForm;
+        /**
+         * multiple transports upcoming jsf 2.2 feature currently allowed
+         * default (no value) xhrQueuedPost
+         *
+         * xhrQueuedPost
+         * xhrPost
+         * xhrGet
+         * xhrQueuedGet
+         * iframePost
+         * iframeQueuedPost
+         *
+         */
+        var transportType = (!isMultipart) ?
+                getConfig(context, "transportType", "xhrQueuedPost") :
+                getConfig(context, "transportType", "multipartQueuedPost");
+        if (!this._transport[transportType]) {
+            //throw new Error("Transport type " + transportType + " does not exist");
+            throw new Error(_Lang.getMessage("ERR_TRANSPORT", null, transportType));
+        }
+        return transportType;
+
+    },
+
+    /**
+     * transforms the list to the expected one
+     * with the proper none all form and this handling
+     * (note we also could use a simple string replace but then
+     * we would have had double entries under some circumstances)
+     *
+     * @param passThrgh
+     * @param target
+     * @param srcStr
+     * @param form
+     * @param elementId
+     */
+    _transformList:function (passThrgh, target, srcStr, form, elementId) {
+        var _Lang = this._Lang;
+        //this is probably the fastest transformation method
+        //it uses an array and an index to position all elements correctly
+        //the offset variable is there to prevent 0 which results in a javascript
+        //false
+        srcStr = this._Lang.trim(srcStr);
+        var offset = 1,
+                vals = (srcStr) ? srcStr.split(/\s+/) : [],
+                idIdx = (vals.length) ? _Lang.arrToMap(vals, offset) : {},
+
+        //helpers to improve speed and compression
+                none = idIdx[this.IDENT_NONE],
+                all = idIdx[this.IDENT_ALL],
+                theThis = idIdx[this.IDENT_THIS],
+                theForm = idIdx[this.IDENT_FORM];
+
+        if (none) {
+            //in case of none nothing is returned
+            if ('undefined' != typeof passThrgh.target) {
+                delete passThrgh.target;
+            }
+            return passThrgh;
+        }
+        if (all) {
+            //in case of all only one value is returned
+            passThrgh[target] = this.IDENT_ALL;
+            return passThrgh;
+        }
+
+        if (theForm) {
+            //the form is replaced with the proper id but the other
+            //values are not touched
+            vals[theForm - offset] = form.id;
+        }
+        if (theThis && !idIdx[elementId]) {
+            //in case of this, the element id is set
+            vals[theThis - offset] = elementId;
+        }
+
+        //the final list must be blank separated
+        passThrgh[target] = vals.join(" ");
+        return passThrgh;
+    },
+
+    addOnError:function (/*function*/errorListener) {
+        /*error handling already done in the assert of the queue*/
+        this._errListeners.enqueue(errorListener);
+    },
+
+    addOnEvent:function (/*function*/eventListener) {
+        /*error handling already done in the assert of the queue*/
+        this._evtListeners.enqueue(eventListener);
+    },
+
+    /**
+     * implementation triggering the error chain
+     *
+     * @param {Object} request the request object which comes from the xhr cycle
+     * @param {Object} context (Map) the context object being pushed over the xhr cycle keeping additional metadata
+     * @param {String} name the error name
+     * @param {String} serverErrorName the server error name in case of a server error
+     * @param {String} serverErrorMessage the server error message in case of a server error
+     * @param {String} caller optional caller reference for extended error messages
+     * @param {String} callFunc optional caller Function reference for extended error messages
+     *
+     *  handles the errors, in case of an onError exists within the context the onError is called as local error handler
+     *  the registered error handlers in the queue receiv an error message to be dealt with
+     *  and if the projectStage is at development an alert box is displayed
+     *
+     *  note: we have additional functionality here, via the global config myfaces.config.defaultErrorOutput a function can be provided
+     *  which changes the default output behavior from alert to something else
+     *
+     *
+     */
+    sendError:function sendError(/*Object*/request, /*Object*/ context, /*String*/ name, /*String*/ serverErrorName, /*String*/ serverErrorMessage, caller, callFunc) {
+        var _Lang = myfaces._impl._util._Lang;
+        var UNKNOWN = _Lang.getMessage("UNKNOWN");
+
+        var eventData = {};
+        //we keep this in a closure because we might reuse it for our serverErrorMessage
+        var malFormedMessage = function () {
+            return (name && name === myfaces._impl.core.Impl.MALFORMEDXML) ? _Lang.getMessage("ERR_MALFORMEDXML") : "";
+        };
+
+        //by setting unknown values to unknown we can handle cases
+        //better where a simulated context is pushed into the system
+        eventData.type = this.ERROR;
+
+        eventData.status = name || UNKNOWN;
+        eventData.serverErrorName = serverErrorName || UNKNOWN;
+        eventData.serverErrorMessage = serverErrorMessage || UNKNOWN;
+
+        try {
+            eventData.source = context.source || UNKNOWN;
+            eventData.responseCode = request.status || UNKNOWN;
+            eventData.responseText = request.responseText || UNKNOWN;
+            eventData.responseXML = request.responseXML || UNKNOWN;
+        } catch (e) {
+            // silently ignore: user can find out by examining the event data
+        }
+        //extended error message only in dev mode
+        if (jsf.getProjectStage() === "Development") {
+            eventData.serverErrorMessage = eventData.serverErrorMessage || "";
+            eventData.serverErrorMessage = (caller) ? eventData.serverErrorMessage + "\nCalling class: " + caller : eventData.serverErrorMessage;
+            eventData.serverErrorMessage = (callFunc) ? eventData.serverErrorMessage + "\n Calling function: " + callFunc : eventData.serverErrorMessage;
+        }
+
+        /**/
+        if (context["onerror"]) {
+            context.onerror(eventData);
+        }
+
+        /*now we serve the queue as well*/
+        this._errListeners.broadcastEvent(eventData);
+
+        if (jsf.getProjectStage() === "Development" && this._errListeners.length() == 0 && !context["onerror"]) {
+            var DIVIDER = "--------------------------------------------------------",
+                    defaultErrorOutput = myfaces._impl.core._Runtime.getGlobalConfig("defaultErrorOutput", alert),
+                    finalMessage = [],
+            //we remap the function to achieve a better compressability
+                    pushMsg = _Lang.hitch(finalMessage, finalMessage.push);
+
+            (serverErrorMessage) ? pushMsg(_Lang.getMessage("MSG_ERROR_MESSAGE") + " " + serverErrorMessage + "\n") : null;
+
+            pushMsg(DIVIDER);
+
+            (caller) ? pushMsg("Calling class:" + caller) : null;
+            (callFunc) ? pushMsg("Calling function:" + callFunc) : null;
+            (name) ? pushMsg(_Lang.getMessage("MSG_ERROR_NAME") + " " + name) : null;
+            (serverErrorName && name != serverErrorName) ? pushMsg("Server error name: " + serverErrorName) : null;
+
+            pushMsg(malFormedMessage());
+            pushMsg(DIVIDER);
+            pushMsg(_Lang.getMessage("MSG_DEV_MODE"));
+            defaultErrorOutput(finalMessage.join("\n"));
+        }
+    },
+
+    /**
+     * sends an event
+     */
+    sendEvent:function sendEvent(/*Object*/request, /*Object*/ context, /*event name*/ name) {
+        var _Lang = myfaces._impl._util._Lang;
+        var eventData = {};
+        var UNKNOWN = _Lang.getMessage("UNKNOWN");
+
+        eventData.type = this.EVENT;
+
+        eventData.status = name;
+        eventData.source = context.source;
+
+        if (name !== this.BEGIN) {
+
+            try {
+                //we bypass a problem with ie here, ie throws an exception if no status is given on the xhr object instead of just passing a value
+                var getValue = function (value, key) {
+                    try {
+                        return value[key]
+                    } catch (e) {
+                        return UNKNOWN;
+                    }
+                };
+
+                eventData.responseCode = getValue(request, "status");
+                eventData.responseText = getValue(request, "responseText");
+                eventData.responseXML = getValue(request, "responseXML");
+
+            } catch (e) {
+                var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+                impl.sendError(request, context, this.CLIENT_ERROR, "ErrorRetrievingResponse",
+                        _Lang.getMessage("ERR_CONSTRUCT", e.toString()));
+
+                //client errors are not swallowed
+                throw e;
+            }
+
+        }
+
+        /**/
+        if (context.onevent) {
+            /*calling null to preserve the original scope*/
+            context.onevent.call(null, eventData);
+        }
+
+        /*now we serve the queue as well*/
+        this._evtListeners.broadcastEvent(eventData);
+    },
+
+    /**
+     * Spec. 13.3.3
+     * Examining the response markup and updating the DOM tree
+     * @param {XMLHttpRequest} request - the ajax request
+     * @param {Object} context - the ajax context
+     */
+    response:function (request, context) {
+        this._RT.getLocalOrGlobalConfig(context, "responseHandler", myfaces._impl.xhrCore._AjaxResponse).processResponse(request, context);
+    },
+
+    /**
+     * fetches the separator char from the given script tags
+     *
+     * @return {char} the separator char for the given script tags
+     */
+    getSeparatorChar:function () {
+        if (this._separator) {
+            return this.separatorchar;
+        }
+        var SEPARATOR_CHAR = "separatorchar",
+                found = false,
+                getConfig = myfaces._impl.core._Runtime.getGlobalConfig,
+                scriptTags = document.getElementsByTagName("script");
+        for (var i = 0; i < scriptTags.length && !found; i++) {
+            if (scriptTags[i].src.search(/\/javax\.faces\.resource.*\/jsf\.js.*separator/) != -1) {
+                found = true;
+                var result = scriptTags[i].src.match(/separator=([^&;]*)/);
+                this._separator = decodeURIComponent(result[1]);
+            }
+        }
+        this._separator = getConfig(SEPARATOR_CHAR, this._separator || ":");
+        return this._separator;
+    },
+
+    /**
+     * @return the project stage also emitted by the server:
+     * it cannot be cached and must be delivered over the server
+     * The value for it comes from the request parameter of the jsf.js script called "stage".
+     */
+    getProjectStage:function () {
+        //since impl is a singleton we only have to do it once at first access
+
+        if (!this._projectStage) {
+            var PRJ_STAGE = "projectStage",
+                    STG_PROD = "Production",
+
+                    scriptTags = document.getElementsByTagName("script"),
+                    getConfig = myfaces._impl.core._Runtime.getGlobalConfig,
+                    projectStage = null,
+                    found = false,
+                    allowedProjectStages = {STG_PROD:1, "Development":1, "SystemTest":1, "UnitTest":1};
+
+            /* run through all script tags and try to find the one that includes jsf.js */
+            for (var i = 0; i < scriptTags.length && !found; i++) {
+                if (scriptTags[i].src.search(/\/javax\.faces\.resource\/jsf\.js.*ln=javax\.faces/) != -1) {
+                    var result = scriptTags[i].src.match(/stage=([^&;]*)/);
+                    found = true;
+                    if (result) {
+                        // we found stage=XXX
+                        // return only valid values of ProjectStage
+                        projectStage = (allowedProjectStages[result[1]]) ? result[1] : null;
+
+                    }
+                    else {
+                        //we found the script, but there was no stage parameter -- Production
+                        //(we also add an override here for testing purposes, the default, however is Production)
+                        projectStage = getConfig(PRJ_STAGE, STG_PROD);
+                    }
+                }
+            }
+            /* we could not find anything valid --> return the default value */
+            this._projectStage = getConfig(PRJ_STAGE, projectStage || STG_PROD);
+        }
+        return this._projectStage;
+    },
+
+    /**
+     * implementation of the external chain function
+     * moved into the impl
+     *
+     *  @param {Object} source the source which also becomes
+     * the scope for the calling function (unspecified side behavior)
+     * the spec states here that the source can be any arbitrary code block.
+     * Which means it either is a javascript function directly passed or a code block
+     * which has to be evaluated separately.
+     *
+     * After revisiting the code additional testing against components showed that
+     * the this parameter is only targeted at the component triggering the eval
+     * (event) if a string code block is passed. This is behavior we have to resemble
+     * in our function here as well, I guess.
+     *
+     * @param {Event} event the event object being passed down into the the chain as event origin
+     *   the spec is contradicting here, it on one hand defines event, and on the other
+     *   it says it is optional, after asking, it meant that event must be passed down
+     *   but can be undefined
+     */
+    chain:function (source, event) {
+        var len = arguments.length;
+        var _Lang = this._Lang;
+        var throwErr = function (msgKey) {
+            throw Error("jsf.util.chain: " + _Lang.getMessage(msgKey));
+        };
+        /**
+         * generic error condition checker which raises
+         * an exception if the condition is met
+         * @param assertion
+         * @param message
+         */
+        var errorCondition = function (assertion, message) {
+            if (assertion === true) throwErr(message);
+        };
+        var FUNC = 'function';
+        var ISSTR = _Lang.isString;
+
+        //the spec is contradicting here, it on one hand defines event, and on the other
+        //it says it is optional, I have cleared this up now
+        //the spec meant the param must be passed down, but can be 'undefined'
+
+        errorCondition(len < 2, "ERR_EV_OR_UNKNOWN");
+        errorCondition(len < 3 && (FUNC == typeof event || ISSTR(event)), "ERR_EVT_PASS");
+        if (len < 3) {
+            //nothing to be done here, move along
+            return true;
+        }
+        //now we fetch from what is given from the parameter list
+        //we cannot work with splice here in any performant way so we do it the hard way
+        //arguments only are give if not set to undefined even null values!
+
+        //assertions source either null or set as dom element:
+        errorCondition('undefined' == typeof source, "ERR_SOURCE_DEF_NULL");
+        errorCondition(FUNC == typeof source, "ERR_SOURCE_FUNC");
+        errorCondition(ISSTR(source), "ERR_SOURCE_NOSTR");
+
+        //assertion if event is a function or a string we already are in our function elements
+        //since event either is undefined, null or a valid event object
+        errorCondition(FUNC == typeof event || ISSTR(event), "ERR_EV_OR_UNKNOWN");
+
+        for (var cnt = 2; cnt < len; cnt++) {
+            //we do not change the scope of the incoming functions
+            //but we reuse the argument array capabilities of apply
+            var ret;
+
+            if (FUNC == typeof arguments[cnt]) {
+                ret = arguments[cnt].call(source, event);
+            } else {
+                //either a function or a string can be passed in case of a string we have to wrap it into another function
+                ret = new Function("event", arguments[cnt]).call(source, event);
+            }
+            //now if one function returns false in between we stop the execution of the cycle
+            //here, note we do a strong comparison here to avoid constructs like 'false' or null triggering
+            if (ret === false /*undefined check implicitly done here by using a strong compare*/) {
+                return false;
+            }
+        }
+        return true;
+    },
+
+    /**
+     * error handler behavior called internally
+     * and only into the impl it takes care of the
+     * internal message transformation to a myfaces internal error
+     * and then uses the standard send error mechanisms
+     * also a double error logging prevention is done as well
+     *
+     * @param request the request currently being processed
+     * @param context the context affected by this error
+     * @param exception the exception being thrown
+     */
+    stdErrorHandler:function (request, context, exception) {
+        //newer browsers do not allow to hold additional values on native objects like exceptions
+        //we hence capsule it into the request, which is gced automatically
+        //on ie as well, since the stdErrorHandler usually is called between requests
+        //this is a valid approach
+        if (this._threshold == "ERROR") {
+            var mfInternal = exception._mfInternal || {};
+
+            var finalMsg = [];
+            finalMsg.push(exception.message);
+            this.sendError(request, context,
+                    mfInternal.title || this.CLIENT_ERROR, mfInternal.name || exception.name, finalMsg.join("\n"), mfInternal.caller, mfInternal.callFunc);
+        }
+    },
+
+    /**
+     * @return the client window id of the current window, if one is given
+     */
+    getClientWindow:function (node) {
+        var fetchWindowIdFromForms = this._Lang.hitch(this, function (forms) {
+            var result_idx = {};
+            var result;
+            var foundCnt = 0;
+            for (var cnt = forms.length - 1; cnt >= 0; cnt--) {
+
+                var currentForm = forms[cnt];
+                var winIdElement = this._Dom.getNamedElementFromForm(currentForm, this.P_WINDOW_ID);
+                var windowId = (winIdElement) ? winIdElement.value : null;
+
+                if (windowId) {
+                    if (foundCnt > 0 && "undefined" == typeof result_idx[windowId]) throw Error("Multiple different windowIds found in document");
+                    result = windowId;
+                    result_idx[windowId] = true;
+                    foundCnt++;
+                }
+            }
+            return result;
+        });
+
+        var fetchWindowIdFromURL = function () {
+            var href = window.location.href, windowId = "jfwid";
+            var regex = new RegExp("[\\?&]" + windowId + "=([^&#\\;]*)");
+            var results = regex.exec(href);
+            //initial trial over the url and a regexp
+            if (results != null) return results[1];
+            return null;
+        };
+
+        //byId ($)
+        var finalNode = (node) ? this._Dom.byId(node) : document.body;
+
+        var forms = this._Dom.findByTagName(finalNode, "form");
+        var result = fetchWindowIdFromForms(forms);
+        return (null != result) ? result : fetchWindowIdFromURL();
+    }
+});
+
+
+
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*last file loaded, must restore the state of affairs*/
+(function() {
+    //some mobile browsers do not have a window object
+    var target = window || document;
+
+    var resetAbbreviation = function (name) {
+        var _temp = target.myfaces._implTemp;
+        (!!_temp[name]) ?
+                target[name] = _temp[name] : null;
+    },
+            resetArr = ["_MF_CLS",
+                        "_MF_SINGLTN",
+                        "_MF_OBJECT",
+                        "_PFX_UTIL",
+                        "_PFX_XHR",
+                        "_PFX_CORE",
+                        "_PFX_I18N"];
+    for (var cnt = resetArr.length - 1; cnt >= 0; cnt--) {
+        resetAbbreviation(resetArr[cnt]);
+    }
+})();
+
+
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+*/
+
+/**
+ *MyFaces core javascripting libraries
+ *
+ *  Those are the central public API functions in the JSF2
+ *  Ajax API! They handle the entire form submit and ajax send
+ *  and resolve cycle!
+ */
+
+/**
+ * reserve the root namespace
+ */
+if ('undefined' != typeof OpenAjax && ('undefined' == typeof jsf || null == typeof jsf)) {
+    OpenAjax.hub.registerLibrary("jsf", "www.sun.com", "1.0", null);
+}
+//just in case openajax has failed (testing environment)
+/**
+* @ignore
+*/
+if (!window.jsf) {
+	/**
+	* @namespace jsf
+	*/
+    var jsf = new function() {
+        /*
+         * Version of the implementation for the jsf.js.
+         * <p />
+         * as specified within the jsf specifications jsf.html:
+         * <ul>
+         * <li>left two digits major release number</li>
+         * <li>middle two digits minor spec release number</li>
+         * <li>right two digits bug release number</li>
+         * </ul>
+		 * @constant
+         */
+        this.specversion = 220000;
+        /**
+         * Implementation version as specified within the jsf specification.
+         * <p />
+         * A number increased with every implementation version
+         * and reset by moving to a new spec release number
+         *
+		 * @constant
+         */
+        this.implversion = 0;
+
+        /**
+         * SeparatorChar as defined by UINamingContainer.getNamingContainerSeparatorChar()
+         * @type {Char}
+         */
+        this.separatorchar = getSeparatorChar();
+
+        /**
+         * This method is responsible for the return of a given project stage as defined
+         * by the jsf specification.
+         * <p/>
+         * Valid return values are:
+         * <ul>
+         *     <li>&quot;Production&quot;</li>
+         *     <li>&quot;Development&quot;</li>
+         *     <li>&quot;SystemTest&quot;</li>
+         *     <li>&quot;UnitTest&quot;</li>
+         * </li>
+         *
+         * @return {String} the current project state emitted by the server side method:
+         * <i>javax.faces.application.Application.getProjectStage()</i>
+         */
+        this.getProjectStage = function() {
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.getProjectStage();
+        };
+
+        /**
+         * collect and encode data for a given form element (must be of type form)
+         * find the javax.faces.ViewState element and encode its value as well!
+         * return a concatenated string of the encoded values!
+         *
+         * @throws an exception in case of the given element not being of type form!
+         * https://issues.apache.org/jira/browse/MYFACES-2110
+         */
+        this.getViewState = function(formElement) {
+            /*we are not allowed to add the impl on a global scope so we have to inline the code*/
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.getViewState(formElement);
+        };
+
+        /**
+         * returns the window identifier for the given node / window
+         * @param {optional String | DomNode}  the node for which the client identifier has to be determined
+         * @return the window identifier or null if none is found
+         */
+        this.getClientWindow = function() {
+            /*we are not allowed to add the impl on a global scope so we have to inline the code*/
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return (arguments.length)? impl.getClientWindow(arguments[0]) : impl.getClientWindow();
+        }
+
+        //private helper functions
+        function getSeparatorChar() {
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.getSeparatorChar();
+        }
+
+    };
+	//jsdoc helper to avoid warnings, we map later
+	window.jsf = jsf;
+}
+
+/**
+ * just to make sure no questions arise, I simply prefer here a weak
+ * typeless comparison just in case some frameworks try to interfere
+ * by overriding null or fiddeling around with undefined or typeof in some ways
+ * it is safer in this case than the standard way of doing a strong comparison
+ **/
+if (!jsf.ajax) {
+	/**
+	* @namespace jsf.ajax
+	*/
+    jsf.ajax = new function() {
+
+
+        /**
+         * this function has to send the ajax requests
+         *
+         * following request conditions must be met:
+         * <ul>
+         *  <li> the request must be sent asynchronously! </li>
+         *  <li> the request must be a POST!!! request </li>
+         *  <li> the request url must be the form action attribute </li>
+         *  <li> all requests must be queued with a client side request queue to ensure the request ordering!</li>
+         * </ul>
+         *
+         * @param {String|Node} element: any dom element no matter being it html or jsf, from which the event is emitted
+         * @param {EVENT} event: any javascript event supported by that object
+         * @param {Map} options : map of options being pushed into the ajax cycle
+         */
+        this.request = function(element, event, options) {
+            if (!options) {
+                options = {};
+            }
+            /*we are not allowed to add the impl on a global scope so we have to inline the code*/
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.request(element, event, options);
+        };
+
+		/**
+		* Adds an error handler to our global error queue.
+		* the error handler must be of the format <i>function errorListener(&lt;errorData&gt;)</i>
+		* with errorData being of following format:
+		* <ul>
+         *     <li> errorData.type : &quot;error&quot;</li>
+         *     <li> errorData.status : the error status message</li>
+         *     <li> errorData.serverErrorName : the server error name in case of a server error</li>
+         *     <li> errorData.serverErrorMessage : the server error message in case of a server error</li>
+         *     <li> errorData.source  : the issuing source element which triggered the request </li>
+         *     <li> eventData.responseCode: the response code (aka http request response code, 401 etc...) </li>
+         *     <li> eventData.responseText: the request response text </li>
+         *     <li> eventData.responseXML: the request response xml </li>
+        * </ul>
+         *
+         * @param {function} errorListener error handler must be of the format <i>function errorListener(&lt;errorData&gt;)</i>
+		*/
+        this.addOnError = function(/*function*/errorListener) {
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.addOnError(errorListener);
+        };
+
+        /**
+         * Adds a global event listener to the ajax event queue. The event listener must be a function
+         * of following format: <i>function eventListener(&lt;eventData&gt;)</i>
+         *
+         * @param {function} eventListener event must be of the format <i>function eventListener(&lt;eventData&gt;)</i>
+         */
+        this.addOnEvent = function(/*function*/eventListener) {
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.addOnEvent(eventListener);
+        };
+
+        /**
+         * processes the ajax response if the ajax request completes successfully
+         * @param request the ajax request!
+         * @param context the ajax context!
+         */
+        this.response = function(/*xhr request object*/request, context) {
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.response(request, context);
+        };
+    }
+}
+
+if (!jsf.util) {
+	/**
+	* @namespace jsf.util
+	*/
+    jsf.util = new function() {
+
+        /**
+         * varargs function which executes a chain of code (functions or any other code)
+         *
+         * if any of the code returns false, the execution
+         * is terminated prematurely skipping the rest of the code!
+         *
+         * @param {DomNode} source, the callee object
+         * @param {Event} event, the event object of the callee event triggering this function
+         * @param {optional} functions to be chained, if any of those return false the chain is broken
+         */
+        this.chain = function(source, event) {
+            var impl = myfaces._impl.core._Runtime.getGlobalConfig("jsfAjaxImpl", myfaces._impl.core.Impl);
+            return impl.chain.apply(impl, arguments);
+        };
+    }
+}
+
+
+
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-layout.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-layout.js
new file mode 100644
index 0000000..e711f5d
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-layout.js
@@ -0,0 +1,269 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Layout = {};
+
+Tobago.Layout.Orientation = {
+  HORIZONTAL: true,
+  VERTICAL: false
+};
+
+function init(table) {
+
+  var elements = table.children("tbody").children("tr").children("td").children();
+  elements.each(function () {
+    var element = jQuery(this);
+    var data = element.data("tobago-layout");
+    if (data !== undefined) {
+      var width = data.width;
+      if (width == null && element.prop("tagName") == "img") {
+        width = element.outerWidth();
+      }
+      if (width != null) {
+        element.css("width", width + "px");
+      }
+
+      var height = data.height;
+      if (height == null && element.prop("tagName") == "img") {
+        height = element.outerHeight();
+      }
+      if (height != null) {
+        element.css("height", height + "px");
+      }
+    }
+  });
+}
+
+function layoutGrid(table, orientation) {
+  var cells;
+  var banks;
+  var tokens;
+  var css;
+  var desired;
+
+  var tobagoLayout = table.data("tobago-layout");
+  if (! tobagoLayout) {
+    return;
+  }
+
+  if (orientation == Tobago.Layout.Orientation.HORIZONTAL) {
+//    cells = table.find("tr:first>td");
+    banks = table.children("colgroup").children("col");
+    tokens = tobagoLayout.columns;
+    css = "width";
+    desired = table.outerWidth();
+//    desired = table.parent().data("tobago-style").width.replace("px", ""); // todo: data("tobago-layout") wohl doch nicht so gut...? der wert wurde ja schon berechnet...
+  } else { // Tobago.Layout.Orientation.VERTICAL
+//    cells = table.find("tr");
+    banks = table.children("tbody").children("tr");
+    tokens = tobagoLayout.rows;
+    css = "height";
+    desired = table.outerHeight();
+//    desired = table.parent().data("tobago-style").height.replace("px", ""); // todo: data("tobago-layout")
+  }
+
+  if (tokens) {
+    table.css(css, "0px");
+    var i;
+    var cell;
+    var sumRelative = 0;
+    var sumUsed = 0;
+    for (i = 0; i < tokens.length; i++) {
+//      cell = cells.eq(i);
+      cell = banks.eq(i);
+      switch (typeof tokens[i]) {
+        case "number":
+          // a relative value
+          sumRelative += tokens[i];
+          break;
+        case "string":
+          // a string, currently only "auto" is supported
+          if ("auto" == tokens[i]) {
+            // nothing to do
+            sumUsed += orientation == Tobago.Layout.Orientation.HORIZONTAL ? cell.outerWidth() : cell.outerHeight();
+          } else {
+            console.warn("currently only 'auto' is supported, but found: '" + tokens[i] + "'");  // @DEV_ONLY
+          }
+          break;
+        case "object":
+          var m = tokens[i].measure;
+          if (m) {
+            setLength(table, banks, i, css, m);
+            if (/^\d+px$/.test(m)) {
+              sumUsed += m.substr(0, m.length - 2);
+            }
+          } else {
+            console.warn("can't find  measure in object: '" + tokens[i] + "'");  // @DEV_ONLY
+          }
+          break;
+        default:
+          console.warn("unsupported type of: '" + tokens[i] + "'");  // @DEV_ONLY
+          break;
+      }
+    }
+
+    table.css(css, "");
+    var rest = desired - sumUsed;
+    if (rest > 0 && sumRelative > 0) {
+      for (i = 0; i < tokens.length; i++) {
+        if (typeof tokens[i] == "number") {
+          setLength(table, banks, i, css, rest * tokens[i] / sumRelative + "px");
+        }
+      }
+    }
+  }
+}
+
+function setLength(table, banks, i, css, length) {
+  banks.eq(i).css(css, length);
+  /*
+   if (css == "width") {
+   var trs = table.children("tbody").children("tr");
+   trs.each(function () {
+   jQuery(this).children("td").eq(i).children().css(css, length);
+   });
+   } else {
+   var tr = table.children("tbody").children("tr").eq(i);
+   tr.children("td").children().css(css, length);
+   }
+   */
+}
+
+function setLength2(banks, i, css, length) {
+  banks.eq(i).css(css, length);
+}
+
+function layoutFlex(container, orientation) {
+
+  // todo: modernizr
+  // if (!Modernizr.flexbox && !Modernizr.flexboxtweener) ... do other
+
+  var cells;
+  var banks;
+  var tokens;
+  var css;
+
+  var tobagoLayout = container.data("tobago-layout");
+  if (! tobagoLayout) {
+    return;
+  }
+
+  if (orientation == Tobago.Layout.Orientation.HORIZONTAL) {
+    banks = container.children();
+    tokens = tobagoLayout.columns;
+    css = "width";
+  } else { // Tobago.Layout.Orientation.VERTICAL
+    banks = container.children();
+    tokens = tobagoLayout.rows;
+    css = "height";
+  }
+
+  if (tokens) {
+    var i;
+    var cell;
+    for (i = 0; i < tokens.length; i++) {
+      cell = banks.eq(i);
+      switch (typeof tokens[i]) {
+        case "number":
+          // a relative value
+          // todo: check for "any other" (non-layout) elements
+          var flex = "flex";
+          if (Tobago.browser.isMsie678910) { // todo: modernizr
+            flex = "-ms-flex";
+          }
+          // using "0px" and not "0", because IE11 needs the "px"
+          //container.children().eq(i).css(Modernizr.prefixed("flex"), tokens[i] + " 0 0px");  // todo: modernizr
+
+          var child = container.children().eq(i);
+          if (typeof child != 'undefined' && child.hasClass('tobago-box')
+              && orientation == Tobago.Layout.Orientation.VERTICAL) {
+            container.children().eq(i).css(flex, tokens[i] + " 0 auto");
+          } else {
+            container.children().eq(i).css(flex, tokens[i] + " 0 0px");
+          }
+          break;
+        case "string":
+          // a string, currently only "auto" is supported
+          break;
+        case "object":
+          if (tokens[i].measure) {
+            setLength2(banks, i, css, tokens[i].measure);
+          } else {
+            console.warn("can't find measure in object: '" + tokens[i] + "'");  // @DEV_ONLY
+          }
+          break;
+        default:
+          console.warn("unsupported type of: '" + tokens[i] + "'");  // @DEV_ONLY
+          break;
+      }
+    }
+  }
+}
+
+Tobago.Layout.init = function (elements) {
+
+  var gridLayouts = Tobago.Utils.selectWithJQuery(elements, ".tobago-gridLayout");
+
+  gridLayouts.each(function () {
+    var table = jQuery(this);
+    init(table);
+  });
+
+  gridLayouts.each(function () {
+    var table = jQuery(this);
+    layoutGrid(table, Tobago.Layout.Orientation.HORIZONTAL);
+    layoutGrid(table, Tobago.Layout.Orientation.VERTICAL);
+  });
+
+  //////////////////////////////////////////////
+
+  // the flex stuff.
+
+  var flexLayouts = Tobago.Utils.selectWithJQuery(elements, ".tobago-flexLayout");
+
+  flexLayouts.each(function () {
+    var container = jQuery(this);
+    layoutFlex(container, Tobago.Layout.Orientation.HORIZONTAL);
+    layoutFlex(container, Tobago.Layout.Orientation.VERTICAL);
+  });
+
+  //////////////////////////////////////////////
+
+  // fixing fixed header/footer: content should not scroll behind the footer
+  // XXX Is there a CSS solution?
+  // TODO: this might be reevaluated after a "resize"
+
+  var header = Tobago.Utils.selectWithJQuery(elements, ".navbar-fixed-top");
+  header.each(function () {
+    var content = header.next();
+    content.css({
+      marginTop: (parseInt(content.css("margin-top").replace("px", "")) + header.outerHeight(true)) + "px"
+    });
+  });
+
+  var footer = Tobago.Utils.selectWithJQuery(elements, ".navbar-fixed-bottom");
+  footer.each(function () {
+    var content = footer.prev();
+    content.css({
+      marginBottom: (parseInt(content.css("margin-bottom").replace("px", "")) + footer.outerHeight(true)) + "px"
+    });
+  });
+
+};
+
+Tobago.registerListener(Tobago.Layout.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Layout.init, Tobago.Phase.AFTER_UPDATE);
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-overlay.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-overlay.js
new file mode 100644
index 0000000..b502289
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-overlay.js
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Create a overlay barrier and animate it.
+ */
+
+Tobago.Config.set("Tobago", "waitOverlayDelay", 1000);
+Tobago.Config.set("Ajax", "waitOverlayDelay", 1000);
+
+(function ($) {
+
+  $.widget("tobago.overlay", {
+
+    options: {
+      /**
+       * This boolean indicates, if the overlay is "error" or "wait".
+       */
+      error: false,
+      /**
+       * Is this overlay for an AJAX request, or an normal submit?
+       * We need this information, because AJAX need to clone the animated image, but for a normal submit
+       * we must not clone it, because the animation stops in some browsers.
+       */
+      ajax: false,
+      /**
+       * The delay for the wait overlay. If not set the default delay is read from Tobago.Config.
+       */
+      waitOverlayDelay: undefined
+    },
+
+    overlay: null,
+
+    _create: function () {
+
+      // create the overlay
+
+      this.overlay = jQuery("<div>").addClass("tobago-page-overlay");
+      if (this.options.error) {
+        this.overlay.addClass("tobago-page-overlay-markup-error");
+      } else {
+        this.overlay.addClass("tobago-page-overlay-markup-wait");
+      }
+
+      var overlayOffset = {top: 0, left: 0};
+      if (this.element.is("body")) {
+        this.overlay.css({
+          position: "fixed",
+          zIndex: 1500 // greater than the bootstrap navbar
+        });
+      } else {
+        overlayOffset = this.element.offset();
+        this.overlay.outerWidth(this.element.outerWidth());
+        this.overlay.outerHeight(this.element.outerHeight());
+        this.overlay.css({
+          position: "absolute" // XXX is set via class, but seams to be overridden in IE11?
+        });
+      }
+
+      jQuery("body").append(this.overlay);
+
+      var wait = jQuery("<div>").addClass("tobago-page-overlayCenter");
+      this.overlay.append(wait);
+
+      var image = jQuery("<i>");
+      if (this.options.error) {
+        image.addClass("fa fa-flash fa-3x");
+        wait.addClass("alert-danger");
+      } else {
+        image.addClass("fa fa-refresh fa-3x fa-spin").css({opacity: 0.4});
+      }
+      wait.append(image);
+      wait.show();
+
+      var waitOverlayDelay = this.options.waitOverlayDelay
+          ? this.options.waitOverlayDelay
+          : Tobago.Config.get(this.options.ajax ? "Ajax" : "Tobago", "waitOverlayDelay");
+
+      if (Tobago.browser.isMsie678) {
+        this.overlay.css({filter: 'alpha(opacity=80)'});
+      }
+
+      this.overlay.css({
+        backgroundColor: jQuery('.tobago-page').css("background-color"),
+        opacity: 0})
+          .show()
+          .offset(overlayOffset)
+          .delay(this.options.error ? 0 : waitOverlayDelay)
+          .animate({opacity: '0.8'}, this.options.error ? 0 : 250, "linear");
+    },
+
+    _setOption: function (key, value) {
+
+      switch (key) {
+        case "error":
+          // If the error property has been changed, recreate the overlay.
+          var changed = key == 'error' && value != this.options.error;
+          if (changed) {
+            this.options.error = value;
+            this._destroy();
+            this._create();
+          }
+          break;
+        case "ajax":
+          // Changing of the ajax property seems not to make sense and is not supported.
+          break;
+      }
+
+      this._super("_setOption", key, value);
+
+    },
+
+    _destroy: function () {
+      this.overlay.remove();
+      this.overlay = null;
+    }
+
+  });
+
+}(jQuery));
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-popup.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-popup.js
new file mode 100644
index 0000000..b5783e1
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-popup.js
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Popup = {};
+
+/**
+ * Init popup for bootstrap
+ */
+Tobago.Popup.init = function (elements) {
+
+  var popups = Tobago.Utils.selectWithJQuery(elements, ".modal");
+  popups.each(function () {
+    var $popup = jQuery(this);
+    var $hidden = Tobago.Collapse.findHidden($popup);
+    if ($hidden.val() == "false") {
+      // XXX hack: this is needed for popups open by AJAX.
+      // XXX currently the DOM replacement done by Tobago doesn't remove the modal-backdrop
+      jQuery(".modal-backdrop").remove();
+
+      jQuery(this).modal("show"); // inits and opens the popup
+    } else {
+      jQuery(this).modal("hide"); // inits and hides the popup
+    }
+  });
+};
+
+Tobago.Popup.close = function (button) {
+  jQuery(button).parents('.modal:first').modal("hide");
+
+};
+
+Tobago.registerListener(Tobago.Popup.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Popup.init, Tobago.Phase.AFTER_UPDATE);
+
+Tobago.Collapse = {};
+
+Tobago.Collapse.findHidden = function ($element) {
+  return jQuery(Tobago.Utils.escapeClientId($element.attr("id") + "::collapse"));
+};
+
+Tobago.Collapse.execute = function (collapse) {
+  var transition = collapse.transition;
+  var $for = jQuery(Tobago.Utils.escapeClientId(collapse.forId));
+  var $hidden = Tobago.Collapse.findHidden($for);
+  var isPopup = $for.hasClass("tobago-popup");
+  var newCollapsed;
+  switch (transition) {
+    case "hide":
+      newCollapsed = true;
+      break;
+    case "show":
+      newCollapsed = false;
+      break;
+    default:
+      console.error("unknown transition: '" + transition + "'");
+  }
+  if (newCollapsed) {
+    if (isPopup) {
+      $for.modal("hide");
+    } else {
+      $for.addClass("tobago-collapsed");
+    }
+  } else {
+    if (isPopup) {
+      $for.modal("show");
+    } else {
+      $for.removeClass("tobago-collapsed");
+    }
+  }
+  $hidden.val(newCollapsed);
+};
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-sheet.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-sheet.js
new file mode 100644
index 0000000..f4df098
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-sheet.js
@@ -0,0 +1,730 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Sheets = {
+  sheets: {},
+
+  get: function(id) {
+    return this.sheets[id];
+  },
+
+  put: function(sheet) {
+    this.sheets[sheet.id] = sheet;
+  }
+};
+
+Tobago.Sheet = function(
+    sheetId, unused1, unused2, unused3, unused4,
+    clickActionId, clickReloadComponentId, dblClickActionId, dblClickReloadComponentId, behaviorCommands) {
+  console.debug("New Sheet with id " + sheetId); // @DEV_ONLY
+  console.time("[tobago-sheet] constructor"); // @DEV_ONLY
+  this.id = sheetId;
+  Tobago.Sheets.put(this);
+  this.clickActionId = clickActionId;
+  this.clickReloadComponentId = clickReloadComponentId;
+  this.dblClickActionId = dblClickActionId;
+  this.dblClickReloadComponentId = dblClickReloadComponentId;
+  this.behaviorCommands = behaviorCommands;
+
+  this.setup();
+
+  console.timeEnd("[tobago-sheet] constructor"); // @DEV_ONLY
+};
+
+Tobago.Sheet.init = function(elements) {
+  console.time("[tobago-sheet] init"); // @DEV_ONLY
+  var sheets = Tobago.Utils.selectWithJQuery(elements, ".tobago-sheet");
+  sheets.each(function initSheets() {
+    var sheet = jQuery(this);
+    var id = sheet.attr("id");
+    var commands = sheet.data("tobago-row-action");
+    var click = commands ? commands.click : undefined;
+    var dblclick = commands ? commands.dblclick : undefined;
+    new Tobago.Sheet(id, undefined, undefined, undefined, undefined,
+        click != undefined ? click.action  : undefined,
+        click != undefined ? click.partially : undefined, // fixme: partially no longer used
+        dblclick != undefined ? dblclick.action : undefined,
+        dblclick != undefined ? dblclick.partially: undefined, // fixme: partially no longer used
+        sheet.data("tobago-behavior-commands")); // type array
+
+    //////////////////////////////////////////////
+    // XXX bugfix for IE11 (lower than IE11 isn't supported for that feature)
+    // if a max-height is set on the sheet,
+    if (Tobago.browser.isMsie && sheet.css("max-height") != "none") {
+      sheet.css("height", sheet.css("height")); // reset the height to the same value
+    }
+  });
+
+  Tobago.Sheet.setup2(sheets);
+
+  Tobago.Utils.selectWithJQuery(elements, "button[data-tobago-command=sheetSelectAll]").click(function(event) {
+    Tobago.Sheet.selectAll(jQuery(event.target).closest(".tobago-sheet"));
+  });
+  Tobago.Utils.selectWithJQuery(elements, "button[data-tobago-command=sheetDeselectAll]").click(function(event) {
+    Tobago.Sheet.deselectAll(jQuery(event.target).closest(".tobago-sheet"));
+  });
+  Tobago.Utils.selectWithJQuery(elements, "button[data-tobago-command=sheetToggleAll]").click(function(event) {
+    Tobago.Sheet.toggleAll(jQuery(event.target).closest(".tobago-sheet"));
+  });
+
+  console.timeEnd("[tobago-sheet] init"); // @DEV_ONLY
+};
+
+Tobago.registerListener(Tobago.Sheet.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Sheet.init, Tobago.Phase.AFTER_UPDATE);
+
+Tobago.Sheet.prototype.reloadWithAction = function(source, action) {
+    console.debug("reload sheet with action '" + action + "'"); // @DEV_ONLY
+  var executeIds = this.id;
+  var renderIds = this.id;
+  if (this.behaviorCommands && this.behaviorCommands.reload) {
+    if (this.behaviorCommands.reload.execute) {
+      executeIds +=  " " + behaviorCommands.reload.execute;
+    }
+    if (this.behaviorCommands.reload.render) {
+      renderIds +=  " " + this.behaviorCommands.reload.render;
+    }
+  }
+  jsf.ajax.request(
+      action,
+      null,
+      {
+        "javax.faces.behavior.event": "reload",
+        execute: executeIds,
+        render: renderIds
+      });
+};
+
+Tobago.Sheet.setup2 = function (sheets) {
+
+  jQuery(sheets).each(function() {
+    Tobago.Sheet.resetInputFieldSize(jQuery(this));
+  });
+
+  // synchronize column widths
+  jQuery(sheets).each(function() {
+
+    // basic idea: there are two possible sources for the sizes:
+    // 1. the columns attribute of <tc:sheet> like columns="3*;200px;3*", held by data attribute "tobago-layout"
+    // 2. the hidden field which may contain a value like ",300,200,100,"
+    //
+    // The 1st source usually is the default set by the developer.
+    // The 2nd source usually is the value set by the user manipulating the column widths.
+    //
+    // So, if the 2nd is set, we use it, if not set, we use the 1st source.
+    //
+
+    var $sheet = jQuery(this);
+
+    var hidden = Tobago.Sheet.findHiddenWidths($sheet);
+
+    if (hidden.length > 0 && hidden.val()) {
+      // if the hidden has a value, than also the colgroup/col are set correctly
+      var columnWidths = jQuery.parseJSON(hidden.val());
+      console.info("columnWidths: " + columnWidths); // @DEV_ONLY
+    }
+    if (columnWidths != undefined && columnWidths.length == 0) {
+      // otherwise use the layout definition
+      var layout = $sheet.data("tobago-layout");
+      if (layout && layout.columns && layout.columns.length > 0) {
+        var tokens = layout.columns;
+        var rendered = jQuery.parseJSON(Tobago.Sheet.findHiddenRendered($sheet).val());
+
+        var $headerTable = $sheet.children("header").children("table");
+        var $headerCol = $headerTable.children("colgroup").children("col");
+        var $bodyTable = $sheet.children("div").children("table");
+        var $bodyCol = $bodyTable.children("colgroup").children("col");
+
+        console.assert($headerCol.length - 1 == $bodyCol.length, "header and body column number doesn't match");  // @DEV_ONLY
+
+        var i;
+        var intValue;
+        var sumRelative = 0;
+        var widthRelative = $bodyTable.width();
+        for (i = 0; i < tokens.length; i++) {
+          if (rendered[i] == "true") {
+            if (typeof tokens[i] == "number") {
+              sumRelative += tokens[i];
+            } else if (typeof tokens[i] == "object" && tokens[i].measure != undefined) {
+              intValue = parseInt(tokens[i].measure);
+              if (tokens[i].measure.lastIndexOf("px") > 0) {
+                widthRelative -= intValue;
+              } else if (tokens[i].measure.lastIndexOf("%") > 0) {
+                widthRelative -= parseInt($bodyTable.width() / 100 * intValue);
+              }
+            }
+          }
+        }
+        if (widthRelative < 0) {
+          widthRelative = 0;
+        }
+
+        var headerBodyColCount = 0;
+        for (i = 0; i < tokens.length; i++) {
+          var colWidth = 0;
+          if (rendered[i] == "true") {
+            if (typeof tokens[i] == "number") {
+              colWidth = parseInt((tokens[i] * widthRelative) / sumRelative);
+            } else if (typeof tokens[i] == "object" && tokens[i].measure != undefined) {
+              intValue = parseInt(tokens[i].measure);
+              if (tokens[i].measure.lastIndexOf("px") > 0) {
+                colWidth = intValue;
+              } else if (tokens[i].measure.lastIndexOf("%") > 0) {
+                colWidth = parseInt($bodyTable.width() / 100 * intValue);
+              }
+            }
+            $headerCol.eq(headerBodyColCount).attr("width", colWidth);
+            $bodyCol.eq(headerBodyColCount).attr("width", colWidth);
+            headerBodyColCount++;
+          }
+        }
+      }
+    }
+    Tobago.Sheet.addHeaderFillerWidth($sheet);
+  });
+
+  // resize: mouse events
+  jQuery(sheets).find(".tobago-sheet-headerResize").each(function () {
+    jQuery(this).click(function () {
+      return false;
+    });
+    jQuery(this).mousedown(function (event) {
+      // begin resizing
+      console.info("down"); // @DEV_ONLY
+      var columnIndex = jQuery(this).data("tobago-column-index");
+      var body = jQuery("body");
+      var sheet = jQuery(this).closest(".tobago-sheet");
+      var headerTable = sheet.find(".tobago-sheet-headerTable");
+      var bodyTable = sheet.find(".tobago-sheet-bodyTable");
+      var headerColumn = headerTable.children("colgroup").children("col").eq(columnIndex);
+      var bodyColumn = bodyTable.children("colgroup").children("col").eq(columnIndex);
+      var data = {
+        columnIndex: columnIndex,
+        originalClientX: event.clientX,
+        headerColumn: headerColumn,
+        bodyColumn: bodyColumn,
+        originalHeaderColumnWidth: parseInt(headerColumn.attr("width"))
+      };
+
+      // Set width attribute: Avoid scrollBar position flip to 0.
+      headerTable.css("width", headerTable.outerWidth());
+      bodyTable.css("width", bodyTable.outerWidth());
+
+      body.on("mousemove", data, function(event) {
+        console.info("move"); // @DEV_ONLY
+        var delta = event.clientX - event.data.originalClientX;
+        delta = -Math.min(-delta, event.data.originalHeaderColumnWidth - 10);
+        var columnWidth = event.data.originalHeaderColumnWidth + delta;
+        event.data.headerColumn.attr("width", columnWidth);
+        event.data.bodyColumn.attr("width", columnWidth);
+        Tobago.Sheet.resetInputFieldSize(headerColumn.closest("table"));
+        Tobago.clearSelection();
+        return false;
+      });
+      body.one("mouseup", function(event) {
+        // switch off the mouse move listener
+        jQuery("body").off("mousemove");
+        console.info("up"); // @DEV_ONLY
+        // copy the width values from the header to the body, (and build a list of it)
+        var tokens = sheet.data("tobago-layout").columns;
+        var rendered = jQuery.parseJSON(Tobago.Sheet.findHiddenRendered(sheet).val());
+        var hidden = Tobago.Sheet.findHiddenWidths(sheet);
+        var hiddenWidths;
+        if (hidden.length > 0 && hidden.val()) {
+          hiddenWidths = jQuery.parseJSON(hidden.val());
+        }
+        var headerCols = headerTable.find("col");
+        var bodyCols = bodyTable.find("col");
+        var widths = [];
+        var oldWidthList = [];
+        var i;
+        for (i = 0; i < bodyCols.length; i++) {
+          oldWidthList[i] = bodyCols.eq(i).width();
+        }
+        var usedWidth = 0;
+        var headerBodyColCount = 0;
+        for (i = 0; i < rendered.length; i++) {
+          if (rendered[i] == "true") {
+            // last column is the filler column
+            var newWidth = headerCols.eq(headerBodyColCount).width();
+            // for the hidden field
+            widths[i] = newWidth;
+            usedWidth += newWidth;
+
+            var oldWidth = bodyCols.eq(headerBodyColCount).width();
+            if (oldWidth != newWidth) {
+              // set to the body
+              bodyCols.eq(headerBodyColCount).attr("width", newWidth);
+              // reset the width inside of the cells (TD) if the value was changed.
+              var tds = jQuery("td:nth-child(" + (headerBodyColCount + 1) + ")", bodyTable);
+              if (tds.size() > 0) {
+                var innerWidth = tds.children().eq(0).width() - oldWidthList[headerBodyColCount] + newWidth;
+                // setting all sizes of the inner cells to the same value
+                tds.children().width(innerWidth);
+                // XXX later, if we have box-sizing: border-box we can set the width to 100%
+              }
+            }
+            headerBodyColCount++;
+          } else if (hiddenWidths != undefined && hiddenWidths.length >= i) {
+            widths[i] = hiddenWidths[i];
+          } else {
+            if (typeof tokens[i] == "number") {
+              widths[i] = 100;
+            } else if (typeof tokens[i] == "object" && tokens[i].measure != undefined) {
+              var intValue = parseInt(tokens[i].measure);
+              if (tokens[i].measure.lastIndexOf("px") > 0) {
+                widths[i] = intValue;
+              } else if (tokens[i].measure.lastIndexOf("%") > 0) {
+                widths[i] = parseInt(bodyTable.width() / 100 * intValue);
+              }
+            }
+          }
+        }
+        // Remove width attribute: Avoid scrollBar position flip to 0.
+        headerTable.css("width", "");
+        bodyTable.css("width", "");
+
+        // store the width values in a hidden field
+        Tobago.Sheet.findHiddenWidths(sheet).val(JSON.stringify(widths));
+        return false;
+      });
+    });
+  });
+
+  // scrolling
+  jQuery(sheets).find(".tobago-sheet-body").bind("scroll", function () {
+    var sheetBody = jQuery(this);
+    var scrollLeft = sheetBody.prop("scrollLeft");
+    var scrollTop = sheetBody.prop("scrollTop");
+
+    // scrolling the table should move the header
+    sheetBody.siblings(".tobago-sheet-header").prop("scrollLeft", scrollLeft);
+
+    // store the position in a hidden field
+    var hidden = Tobago.Sheet.findHiddenScrollPosition(sheetBody.parent());
+    hidden.val(Math.round(scrollLeft) + ";" + Math.round(scrollTop));
+  });
+
+  // restore scroll position
+  jQuery(sheets).each(function () {
+    var sheet = jQuery(this);
+    var hidden = Tobago.Sheet.findHiddenScrollPosition(sheet);
+    var sep = hidden.val().indexOf(";");
+    if (sep != -1) {
+      var scrollLeft = hidden.val().substr(0, sep);
+      var scrollTop = hidden.val().substr(sep + 1);
+      var body = sheet.children(".tobago-sheet-body");
+      body.prop("scrollLeft", scrollLeft);
+      body.prop("scrollTop", scrollTop);
+      sheet.children(".tobago-sheet-header").prop("scrollLeft", scrollLeft);
+    }
+  });
+
+  // add selection listeners
+  jQuery(sheets).each(function () {
+    var sheet = jQuery(this);
+    var selectionMode = sheet.data("tobago-selection-mode");
+    if (selectionMode == "single" || selectionMode == "singleOrNone" || selectionMode == "multi") {
+      Tobago.Sheet.getRows(sheet).each(function () {
+        var row = jQuery(this);
+        row.bind("mousedown", function (event) {
+          sheet.data("tobago-mouse-down-x", event.clientX);
+          sheet.data("tobago-mouse-down-y", event.clientY);
+        });
+        row.click(function (event) {
+          var $target = jQuery(event.target);
+          var $row = jQuery(this);
+          if ($target.hasClass("tobago-sheet-columnSelector") || !Tobago.Sheet.isInputElement($target)) {
+            var $sheet = $row.closest(".tobago-sheet");
+
+            if (Math.abs($sheet.data("tobago-mouse-down-x") - event.clientX)
+                + Math.abs($sheet.data("tobago-mouse-down-y") - event.clientY) > 5) {
+              // The user has moved the mouse. We assume, the user want to select some text inside the sheet,
+              // so we doesn't select the row.
+              return;
+            }
+
+            Tobago.clearSelection();
+
+            var $rows = Tobago.Sheet.getRows($sheet);
+            var $selector = Tobago.Sheet.getSelectorCheckbox($row);
+
+            var selectionMode = $sheet.data("tobago-selection-mode");
+
+            if ((!event.ctrlKey && !event.metaKey && $selector.size() == 0)
+                || selectionMode == "single" || selectionMode == "singleOrNone") {
+              Tobago.Sheet.deselectAll($sheet);
+              Tobago.Sheet.resetSelected($sheet);
+            }
+
+            var lastClickedRowIndex = $sheet.data("tobago-last-clicked-row-index");
+            if (event.shiftKey && selectionMode == "multi" && lastClickedRowIndex > -1) {
+              if (lastClickedRowIndex <= $row.index()) {
+                Tobago.Sheet.selectRange($sheet, $rows, lastClickedRowIndex, $row.index(), true, false);
+              } else {
+                Tobago.Sheet.selectRange($sheet, $rows, $row.index(), lastClickedRowIndex, true, false);
+              }
+            } else if (selectionMode != "singleOrNone" || !Tobago.Sheet.isRowSelected($sheet, $row)) {
+              Tobago.Sheet.toggleSelection($sheet, $row, $selector);
+            }
+            var commands = sheet.data("tobago-row-action");
+            var click = commands ? commands.click : undefined;
+            var clickActionId = click ? click.action : undefined;
+            var clickExecuteIds = click ? click.execute : undefined;
+            var clickRenderIds = click ? click.render : undefined;
+
+            var id = $sheet.attr("id");
+
+            if (clickActionId) {
+              var action;
+              var index = clickActionId.indexOf(id);
+              var rowIndex = Tobago.Sheet.getDataIndex($sheet, $row);
+              if (index >= 0) {
+                action = id + ":" + rowIndex + ":" + clickActionId.substring(index + id.length +1);
+              } else {
+                action = id + ":" + rowIndex + ":" + clickActionId;
+              }
+              if (clickExecuteIds && clickExecuteIds.length > 0) {
+                //Tobago.reloadComponent($target.get(0), clickReloadComponentId, action)
+                jsf.ajax.request(
+                    action,
+                    event,
+                    {
+                      //"javax.faces.behavior.event": "click",
+                      execute: clickExecuteIds,
+                      render: clickRenderIds
+                    });
+              } else {
+                Tobago.submitAction($target.get(0), action);
+              }
+            }
+          }
+        });
+        // todo:
+        if (Tobago.Sheets.get(sheet.attr("id")).dblClickActionId) {
+          row.bind("dblclick", function (event) {
+            // todo: re-implement
+            Tobago.Sheets.get(sheet.attr("id")).doDblClick(event);
+          });
+        }
+      });
+    }
+    sheet.find("input.tobago-sheet-columnSelector").click(function(event) {event.preventDefault()});
+  });
+
+    // init reload
+  jQuery(sheets).filter("[data-tobago-reload]").each(function() {
+    var sheet = jQuery(this);
+    Tobago.Sheets.get(sheet.attr("id")).initReload();
+  });
+
+  // init paging by pages
+  jQuery(sheets).find(".tobago-sheet-pagingText").each(function() {
+    var pagingText = jQuery(this);
+    pagingText.click(function () {
+      var text = jQuery(this);
+      text.children(".tobago-sheet-pagingOutput").hide();
+      text.children(".tobago-sheet-pagingInput").show().focus().select();
+    });
+    pagingText.children(".tobago-sheet-pagingInput")
+        .blur(function () {
+          Tobago.Sheet.hideInputOrSubmit(jQuery(this));
+        }).keydown(function (event) {
+          if (event.keyCode == 13) {
+            event.stopPropagation();
+            event.preventDefault();
+            jQuery(this).blur();
+          }
+        });
+  });
+};
+
+Tobago.Sheet.hideInputOrSubmit = function(input) {
+  var output = input.siblings(".tobago-sheet-pagingOutput");
+  var changed = output.html() != input.val();
+  var sheetId = input.parents(".tobago-sheet:first").attr("id");
+  output.html(input.val());
+  if (changed) {
+    Tobago.Sheets.get(sheetId).reloadWithAction(input.get(0), input.attr("id"));
+  } else {
+    console.info("no update needed"); // @DEV_ONLY
+    input.hide();
+    output.show();
+  }
+};
+
+Tobago.Sheet.findHiddenSelected = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "selected";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenScrollPosition = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "scrollPosition";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenWidths = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "widths";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.findHiddenRendered = function($sheet){
+  var id = $sheet.attr("id") + Tobago.SUB_COMPONENT_SEP + "rendered";
+  return jQuery(Tobago.Utils.escapeClientId(id));
+};
+
+Tobago.Sheet.addHeaderFillerWidth = function($sheet) {
+  var $headerTable = $sheet.find(".tobago-sheet-headerTable");
+  var $headerCols = $headerTable.find("col");
+  $headerCols.last().attr("width", Tobago.Sheet.getScrollBarSize());
+};
+
+Tobago.Sheet.getScrollBarSize = function() {
+  var $outer = $('<div>').css({visibility: 'hidden', width: 100, overflow: 'scroll'}).appendTo('body'),
+      widthWithScroll = $('<div>').css({width: '100%'}).appendTo($outer).outerWidth();
+  $outer.remove();
+  return 100 - widthWithScroll;
+};
+
+Tobago.Sheet.prototype.setup = function() {
+  console.time("[tobago-sheet] setup"); // @DEV_ONLY
+  this.initReload();
+  console.timeEnd("[tobago-sheet] setup"); // @DEV_ONLY
+};
+
+Tobago.Sheet.prototype.initReload = function() {
+  var sheet = jQuery(Tobago.Utils.escapeClientId(this.id));
+  var reload = sheet.data("tobago-reload");
+  if (typeof reload == "number") {
+    Tobago.addReloadTimeout(this.id, Tobago.bind2(this, "reloadWithAction", null, this.id), reload);
+  }
+};
+
+Tobago.Sheet.prototype.doDblClick = function(event) {
+    if (! event) {
+      event = window.event;
+    }
+
+    var srcElement;
+    if (event.target) {
+      // W3C DOM level 2
+      srcElement = event.target;
+    } else {
+      // IE
+      srcElement = event.srcElement;
+    }
+
+    if (!Tobago.Sheet.isInputElement(jQuery(srcElement))) {
+      var row = jQuery(srcElement).closest("tr");
+      var sheet = row.closest(".tobago-sheet");
+      var rowIndex = row.index() + sheet.data("tobago-first");
+      if (this.dblClickActionId) {
+        var action;
+        var index = this.dblClickActionId.indexOf(this.id);
+        if (index >= 0) {
+          action = this.id + ":" + rowIndex + ":" + this.dblClickActionId.substring(index + this.id.length +1);
+        } else {
+          action = this.id + ":" + rowIndex + ":" + this.dblClickActionId;
+        }
+        if (this.dblClickReloadComponentId && this.dblClickReloadComponentId.length > 0) {
+          //Tobago.reloadComponent(srcElement, this.dblClickReloadComponentId, action);
+          jsf.ajax.request(
+              action,
+              event,
+              {
+                //"javax.faces.behavior.event": "dblclick",
+                execute: this.dblClickReloadComponentId,
+                render: this.dblClickReloadComponentId
+              });
+        } else {
+          Tobago.submitAction(srcElement, action);
+        }
+      }
+    }
+  };
+
+/**
+ * Get the element, which indicates the selection
+ * @param row as a jQuery object
+ */
+Tobago.Sheet.getSelectorCheckbox = function(row) {
+  return row.find(">td>input.tobago-sheet-columnSelector");
+};
+
+Tobago.Sheet.prototype.getSiblingRow = function(row, i) {
+  return row.parentNode.childNodes[i];
+};
+
+Tobago.Sheet.getRows = function($sheet) {
+  return $sheet.find(">div>table>tbody>tr");
+};
+
+Tobago.Sheet.isRowSelected = function(sheet, row) {
+  var rowIndex = +row.data("tobago-row-index");
+  if (!rowIndex) {
+    rowIndex = row.index() + sheet.data("tobago-first");
+  }
+  return Tobago.Sheet.isSelected(sheet, rowIndex);
+};
+
+Tobago.Sheet.isSelected = function(sheet, rowIndex) {
+  return Tobago.Sheet.findHiddenSelected(sheet).val().indexOf("," + rowIndex + ",") >= 0;
+};
+
+Tobago.Sheet.resetSelected = function($sheet) {
+  Tobago.Sheet.findHiddenSelected($sheet).val(",");
+};
+
+Tobago.Sheet.toggleSelection = function($sheet, $row, $checkbox) {
+  $sheet.data("tobago-last-clicked-row-index", $row.index());
+  if (!$checkbox.is(":disabled")) {
+    var $selected = Tobago.Sheet.findHiddenSelected($sheet);
+    var rowIndex = Tobago.Sheet.getDataIndex($sheet, $row);
+    if (Tobago.Sheet.isSelected($sheet, rowIndex)) {
+      Tobago.Sheet.deselectRow($selected, rowIndex, $row, $checkbox);
+    } else {
+      Tobago.Sheet.selectRow($selected, rowIndex, $row, $checkbox);
+    }
+  }
+};
+
+Tobago.Sheet.selectAll = function($sheet) {
+  var $rows = Tobago.Sheet.getRows($sheet);
+  Tobago.Sheet.selectRange($sheet, $rows, 0, $rows.size() - 1, true, false);
+};
+
+Tobago.Sheet.deselectAll = function($sheet) {
+  var $rows = Tobago.Sheet.getRows($sheet);
+  Tobago.Sheet.selectRange($sheet, $rows, 0, $rows.size() - 1, false, true);
+};
+
+Tobago.Sheet.toggleAll = function(sheet) {
+  var rows = Tobago.Sheet.getRows(sheet);
+  Tobago.Sheet.selectRange(sheet, rows, 0, rows.size() - 1, true, true);
+};
+
+Tobago.Sheet.selectRange = function($sheet, $rows, first, last, selectDeselected, deselectSelected) {
+  if ($rows.size() == 0) {
+    return;
+  }
+  var selected = Tobago.Sheet.findHiddenSelected($sheet);
+  for (var i = first; i <= last; i++) {
+    var row = $rows.eq(i);
+    var checkbox = Tobago.Sheet.getSelectorCheckbox(row);
+    if (!checkbox.is(":disabled")) {
+      var rowIndex = Tobago.Sheet.getDataIndex($sheet, row);
+      var on = selected.val().indexOf("," + rowIndex + ",") >= 0;
+      if (selectDeselected && !on) {
+        Tobago.Sheet.selectRow(selected, rowIndex, row, checkbox);
+      } else if (deselectSelected && on) {
+        Tobago.Sheet.deselectRow(selected, rowIndex, row, checkbox);
+      }
+    }
+  }
+};
+
+Tobago.Sheet.getDataIndex = function(sheet, row) {
+  var rowIndex = row.data("tobago-row-index");
+  if (rowIndex) {
+    return +rowIndex;
+  } else {
+    return row.index() + sheet.data("tobago-first");
+  }
+};
+
+/**
+ * @param $selected input-element type=hidden: Hidden field with the selection state information
+ * @param rowIndex int: zero based index of the row.
+ * @param $row tr-element: the row.
+ * @param $checkbox input-element: selector in the row.
+ */
+Tobago.Sheet.selectRow = function($selected, rowIndex, $row, $checkbox) {
+  $selected.val($selected.val() + rowIndex + ",");
+  $row.addClass("tobago-sheet-row-markup-selected table-info");
+//  checkbox.prop("checked", true);
+  setTimeout(function() {$checkbox.prop("checked", true);}, 0);
+};
+
+/**
+ * @param $selected input-element type=hidden: Hidden field with the selection state information
+ * @param rowIndex int: zero based index of the row.
+ * @param $row tr-element: the row.
+ * @param $checkbox input-element: selector in the row.
+ */
+Tobago.Sheet.deselectRow = function($selected, rowIndex, $row, $checkbox) {
+  $selected.val($selected.val().replace(new RegExp("," + rowIndex + ","), ","));
+  $row.removeClass("tobago-sheet-row-markup-selected table-info");
+//  checkbox.prop("checked", false); Async because of TOBAGO-1312
+  setTimeout(function() {$checkbox.prop("checked", false);}, 0);
+};
+
+Tobago.Sheet.resetInputFieldSize = function (table) {
+  var span = table.find("td>div>span");
+  span.children("input,select").each(function () {
+    var input = jQuery(this);
+    input.outerWidth(input.parent().width());
+  });
+};
+
+Tobago.Sheet.isInputElement = function($element) {
+  return ["INPUT", "TEXTAREA", "SELECT", "A", "BUTTON"].indexOf($element.prop("tagName")) > -1;
+};
+
+(function(jQuery){
+ jQuery.fn.borderBoxWidth = function(width) {
+    return this.each(function() {
+       obj = jQuery(this);
+       var extraWidth = obj.outerWidth() - obj.width();
+       obj.width(width - extraWidth);
+    });
+ };
+})(jQuery);
+
+/*
+ var header = $(".tobago-sheet-headerTable");
+ var body = $(".tobago-sheet-bodyTable");
+
+ header;
+ body;
+
+ header.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ $(this).attr("width", 100);
+ ;
+ })
+
+ header.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ ;
+ })
+
+
+ body.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ $(this).attr("width", 100);
+ ;
+ })
+
+ body.find("col").each(function(){
+
+ console.info($(this).attr("width"));
+ ;
+ })
+ */
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-suggest.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-suggest.js
new file mode 100644
index 0000000..8695574
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-suggest.js
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Suggest = {};
+
+Tobago.Suggest.loadFromServer = function(input) {
+
+  var timeout;
+
+  return function findMatches(query, syncResults, asyncResults) {
+
+    var suggest = jQuery(Tobago.Utils.escapeClientId(input.data("tobago-suggest-for")));
+
+    if (suggest.val() != query) {
+
+      if (timeout) {
+        clearTimeout(timeout);
+      }
+
+      var delay = suggest.data("tobago-suggest-delay");
+
+      timeout = setTimeout(function() {
+        suggest.val(query);
+        suggest.data("tobago-suggest-callback", asyncResults);
+        suggest.removeData("tobago-suggest-data"); // clear jQuery-data-cache
+        var id = suggest.attr("id");
+        console.info("query: '" + query + "'"); // @DEV_ONLY
+
+        jsf.ajax.request(
+            id,
+            null, // todo: event?
+            {
+              "javax.faces.behavior.event": "suggest",
+              execute: id,
+              render: id
+            });
+      }, delay);
+
+    }
+  };
+};
+
+Tobago.Suggest.fromClient = function(data) {
+  return function findMatches(query, syncResults) {
+    var result = [];
+    for (i = 0; i < data.length; i++) {
+      if (data[i].indexOf(query) >= 0) {
+        result.push(data[i]);
+      }
+    }
+    syncResults(result);
+  };
+};
+
+Tobago.Suggest.init = function(elements) {
+
+  var suggests = Tobago.Utils.selectWithJQuery(elements, ".tobago-suggest");
+
+  suggests.each(function() {
+    var suggest = jQuery(this);
+    var input = jQuery(Tobago.Utils.escapeClientId(suggest.data("tobago-suggest-for")));
+
+    var minChars = suggest.data("tobago-suggest-min-chars");
+    var maxItems = suggest.data("tobago-suggest-max-items");
+
+    var update = typeof suggest.data("tobago-suggest-update") != "undefined";
+    var totalCount = suggest.data("tobago-suggest-total-count"); // todo
+
+    if (update && input.hasClass("tt-input")) { // already initialized: so only update data
+      var asyncResults = suggest.data("tobago-suggest-callback"); // comes from "findMatches()"
+      if (asyncResults) {
+        var data1 = suggest.data("tobago-suggest-data");
+        asyncResults(data1);
+      }
+    } else { // new
+      input.data("tobago-suggest-for", suggest.attr("id"));
+      input.attr("autocomplete", "off");
+
+      var source;
+      if (update) {
+        source = Tobago.Suggest.loadFromServer(input);
+      } else {
+        var data2 = suggest.data("tobago-suggest-data");
+        source = Tobago.Suggest.fromClient(data2);
+      }
+
+      var $suggestPopup = jQuery(Tobago.Utils.escapeClientId(suggest.attr('id') + "::popup"));
+      if($suggestPopup.length > 0) {
+        $suggestPopup.remove();
+      }
+
+      jQuery(".tobago-page-menuStore")
+          .append("<div id='" + suggest.attr('id') + "::popup" + "' class='tt-menu tt-empty'/>");
+      $suggestPopup = jQuery($suggestPopup.selector);
+
+      input.typeahead({
+        menu: $suggestPopup,
+        minLength: minChars,
+        hint: true,// todo
+        highlight: true // todo
+      }, {
+        //name: 'test',// todo
+        limit: maxItems,
+        source: source
+      });
+
+      input.bind('typeahead:open', function() {
+        var $input = jQuery(this);
+        var $suggest = $input.parent().siblings(".tobago-suggest");
+        var $suggestPopup = jQuery(Tobago.Utils.escapeClientId($suggest.attr('id') + "::popup"));
+        $suggestPopup.css("top", $input.offset().top + $input.outerHeight() + "px");
+        $suggestPopup.css("left", $input.offset().left + "px");
+        $suggestPopup.css("min-width", $input.outerWidth() + "px");
+      });
+    }
+  });
+};
+
+// using "EARLY", because it must be called before Tobago.Layout.init
+// this is because the suggest puts a span around the input field and doesn't copy the style.
+Tobago.registerListener(Tobago.Suggest.init, Tobago.Phase.DOCUMENT_READY, Tobago.Phase.Order.EARLY);
+Tobago.registerListener(Tobago.Suggest.init, Tobago.Phase.AFTER_UPDATE, Tobago.Phase.Order.EARLY);
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-tab.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-tab.js
new file mode 100644
index 0000000..9bf1d4c
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-tab.js
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.TabGroup = {};
+
+/**
+ * Initializes the tab-groups.
+ * @param elements  a jQuery object to initialize (ajax) or null for initializing the whole document (full load).
+ */
+Tobago.TabGroup.init = function(elements) {
+
+  var tabGroups = Tobago.Utils.selectWithJQuery(elements, ".tobago-tabGroup");
+
+  // setting the active index
+  tabGroups.each(function () {
+    jQuery(this).find(".tobago-tabGroup-header").first().children(".tobago-tab").not(".tobago-tab-markup-disabled")
+        .click(function () {
+      // Update the hidden field for the active index.
+      var tab = jQuery(this);
+      var tabGroup = tab.parents(".tobago-tabGroup:first");
+      var hidden = tabGroup.children("input");
+      var activeIndex = tab.attr("tabgroupindex");
+      hidden.val(activeIndex);
+    })
+  });
+
+  // initialize previous button
+  tabGroups.find("[data-tobago-tabgroup-toolbar-prev]").click(function() {
+    var tabGroup = jQuery(this).parents(".tobago-tabGroup:first");
+    var selected = tabGroup.find(".tobago-tab-markup-selected");
+    // the nearest of the previous siblings, which are not disabled
+    selected.prevAll(":not(.tobago-tab-markup-disabled):first").click();
+  });
+
+  // initialize next button
+  tabGroups.find("[data-tobago-tabgroup-toolbar-next]").click(function() {
+    var tabGroup = jQuery(this).parents(".tobago-tabGroup:first");
+    var selected = tabGroup.find(".tobago-tab-markup-selected");
+    // the nearest of the next siblings, which are not disabled
+    selected.nextAll(":not(.tobago-tab-markup-disabled):first").click();
+  });
+
+  // init scroll position
+  var header = tabGroups.find(".tobago-tabGroup-header");
+  header.each(function() {
+    Tobago.TabGroup.ensureScrollPosition(jQuery(this));
+  });
+
+    // tool tips
+  tabGroups.each(function() {
+    var tabGroup = jQuery(this);
+    tabGroup.find(".tobago-tab").each(function() {
+      var tab = jQuery(this);
+      var tabContent = tabGroup.find(".tobago-tab-content[tabgroupindex=" + tab.attr("tabgroupindex") + "]");
+      tabContent.attr("title", tab.attr("title"));
+    });
+  });
+
+
+  // XXX hack for webkit to avoid scrollbars in box
+//  jQuery('.tobago-tabGroup').hide();
+//  jQuery('.tobago-tabGroup').show();
+};
+
+Tobago.TabGroup.ensureScrollPosition = function (header) {
+  var tab = header.find(".tobago-tab-markup-selected");
+  if (tab.length > 0) {
+    var tabRight = tab.position().left + tab.outerWidth() - header.outerWidth();
+    if (tabRight > 0) {
+      header.scrollLeft(header.scrollLeft() + tabRight + 1); // +1 to avoid rounding problems
+    }
+    var tabLeft = tab.position().left;
+    if (tabLeft < 0) {
+      header.scrollLeft(header.scrollLeft() + tabLeft);
+    }
+  }
+};
+
+Tobago.registerListener(Tobago.TabGroup.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.TabGroup.init, Tobago.Phase.AFTER_UPDATE);
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-tree.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-tree.js
new file mode 100644
index 0000000..b52a61b
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-tree.js
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Tree = {};
+
+Tobago.Tree.toggleNode = function(element, event) {
+  var src;
+  var node = element.closest(".tobago-treeNode, .tobago-treeMenuNode");
+  var data = node.closest(".tobago-treeMenu, .tobago-tree, .tobago-sheet");
+  var expanded = data.children(".tobago-treeMenu-expanded, .tobago-tree-expanded, .tobago-sheet-expanded");
+  var toggle = node.find(".tobago-treeMenuNode-toggle, .tobago-treeNode-toggle");
+  var rowIndex = Tobago.Tree.rowIndex(node);
+  if (Tobago.Tree.isExpanded(node, expanded)) {
+    Tobago.Tree.hideChildren(node);
+    toggle.each(function() {
+      src = jQuery(this).data("tobago-src-closed");
+      if (src == null) { // use the open icon if there is no close icon
+        src = jQuery(this).data("tobago-src-open");
+      }
+      jQuery(this).attr("src", src);
+    });
+    expanded.val(expanded.val().replace(new RegExp("," + rowIndex + ","), ","));
+    node.filter(".tobago-treeNode").removeClass("tobago-treeNode-markup-expanded");
+    node.filter(".tobago-treeMenuNode").removeClass("tobago-treeMenuNode-markup-expanded");
+  } else {
+    var reload = Tobago.Tree.showChildren(node, expanded);
+    expanded.val(expanded.val() + rowIndex + ",");
+    if (reload) {
+      //Tobago.reloadComponent(element, data.attr("id"), toggle.parent().attr("id"), {});
+      jsf.ajax.request(
+          toggle.parent().attr("id"),
+          event,
+          {
+            //"javax.faces.behavior.event": "click",
+            execute: data.attr("id"),
+            render: data.attr("id")
+          });
+    } else {
+      toggle.each(function() {
+        src = jQuery(this).data("tobago-src-open");
+        if (src == null) { // use the close icon if there is no open icon
+          src = jQuery(this).data("tobago-src-closed");
+        }
+        jQuery(this).attr("src", src);
+      });
+      node.filter(".tobago-treeNode").addClass("tobago-treeNode-markup-expanded");
+      node.filter(".tobago-treeMenuNode").addClass("tobago-treeMenuNode-markup-expanded");
+    }
+  }
+};
+
+/**
+ * Hide all children of the node recursively.
+ * @param node A jQuery-Object as a node of the tree.
+ */
+Tobago.Tree.hideChildren = function (node) {
+  var inSheet = Tobago.Tree.isInSheet(node);
+  var children = Tobago.Tree.findChildren(node);
+  children.each(function() {
+    if (inSheet) {
+      jQuery(this).parent().parent().hide();
+    } else {
+      jQuery(this).hide();
+    }
+    Tobago.Tree.hideChildren(jQuery(this));
+  });
+};
+
+/**
+ * Show the children of the node recursively, there parents are expanded.
+ * @param node A jQuery-Object as a node of the tree.
+ * @return is reload needed (to get all nodes from the server)
+ */
+Tobago.Tree.showChildren = function (node, expanded) {
+  var inSheet = Tobago.Tree.isInSheet(node);
+  var children = Tobago.Tree.findChildren(node);
+  if (children.length == 0) {
+    // no children in DOM, reload it from the server
+    return true;
+  }
+  children.each(function() {
+    var child = jQuery(this);
+    if (inSheet) {
+      child.parent().parent().show();
+    } else {
+      child.show();
+    }
+    if (Tobago.Tree.isExpanded(child, expanded)) {
+      var reload = Tobago.Tree.showChildren(child, expanded);
+      if (reload) {
+        return true;
+      }
+    }
+  });
+  return false;
+};
+
+Tobago.Tree.init = function(elements) {
+  
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeNode-markup-folder .tobago-treeNode-toggle").click(function(event) {
+    Tobago.Tree.toggleNode(jQuery(this), event);
+    return false;
+  });
+
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenuNode-markup-folder .tobago-treeMenuNode-toggle")
+      .parent().each(function() {
+    // if there is no command, than the whole node element should be the toggle
+    var toggle = jQuery(this).children(".tobago-treeMenuCommand").size() == 0
+        ? jQuery(this)
+        : jQuery(this).find(".tobago-treeMenuNode-toggle");
+    toggle.click(function(event) {
+      Tobago.Tree.toggleNode(jQuery(this), event);
+    });
+  });
+
+  // normal hover effect (not possible with CSS in IE 6)
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenuNode").hover(function() {
+    jQuery(this).toggleClass("tobago-treeMenuNode-markup-hover");
+  });
+
+  // selected for treeNode
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeCommand").focus(function() {
+    var command = jQuery(this);
+    var node = command.parent(".tobago-treeNode");
+    var tree = node.closest(".tobago-tree");
+    var selected = tree.children(".tobago-tree-selected");
+    selected.val(Tobago.Tree.rowIndex(node));
+    tree.find(".tobago-treeNode").removeClass("tobago-treeNode-markup-selected");
+    node.addClass("tobago-treeNode-markup-selected");
+  });
+
+  // selected for treeSelect
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeSelect > input").change(function () {
+    var select = jQuery(this);
+    var selected = select.prop("checked");
+    var data = select.closest(".tobago-treeMenu, .tobago-tree, .tobago-sheet");
+    var hidden = data.children(".tobago-treeMenu-selected, .tobago-tree-selected, .tobago-sheet-selected");
+    var newValue;
+    if (select.attr("type") == "radio") {
+      newValue = "," + Tobago.Tree.rowIndex(select) + ",";
+    } else if (selected) {
+      newValue = hidden.val() + Tobago.Tree.rowIndex(select) + ",";
+    } else {
+      newValue = hidden.val().replace(new RegExp("," + Tobago.Tree.rowIndex(select) + ","), ",");
+    }
+    // XXX optimize: regexp and Tobago.Tree.rowIndex
+    hidden.val(newValue);
+  });
+
+  // selected for treeMenuNode
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenuCommand").focus(function() {
+    var command = jQuery(this);
+    var node = command.parent(".tobago-treeMenuNode");
+    var tree = node.closest(".tobago-treeMenu");
+    var selected = tree.children(".tobago-treeMenu-selected");
+    selected.val(Tobago.Tree.rowIndex(node));
+    tree.find(".tobago-treeMenuNode").removeClass("tobago-treeMenuNode-markup-selected");
+    node.addClass("tobago-treeMenuNode-markup-selected");
+  });
+
+  // init selected field
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenu, .tobago-tree, .tobago-sheet").each(function() {
+    var hidden = jQuery(this).children(".tobago-treeMenu-selected, .tobago-tree-selected, .tobago-sheet-selected");
+    var string = ",";
+    jQuery(this).find(".tobago-treeMenuNode-markup-selected, .tobago-treeNode-markup-selected").each(function() {
+      string += Tobago.Tree.rowIndex(jQuery(this)) + ",";
+    });
+    hidden.val(string);
+  });
+
+  // init expanded field
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-treeMenu, .tobago-tree, .tobago-sheet").each(function() {
+    var hidden = jQuery(this).children(".tobago-treeMenu-expanded, .tobago-tree-expanded, .tobago-sheet-expanded");
+    var string = ",";
+    jQuery(this).find(".tobago-treeMenuNode-markup-expanded, .tobago-treeNode-markup-expanded").each(function() {
+      string += Tobago.Tree.rowIndex(jQuery(this)) + ",";
+    });
+    hidden.val(string);
+  });
+
+  // init tree selection for multiCascade
+  Tobago.Utils.selectWithJQuery(elements, ".tobago-tree[data-tobago-selectable=multiCascade]").each(function() {
+    var tree = jQuery(this);
+    tree.find("input[type=checkbox]").each(function() {
+      jQuery(this).change(function(event) {
+        var node = jQuery(event.target).parents(".tobago-treeNode");
+        var checked = node.find("input[type=checkbox]").prop("checked");
+        var children = Tobago.Tree.findChildren(node);
+        children.each(function() {
+          var childsCheckbox = jQuery(this).find("input[type=checkbox]");
+          childsCheckbox.prop("checked", checked);
+          childsCheckbox.change();
+        });
+      });
+    });
+  });
+
+};
+
+Tobago.Tree.isExpanded = function(node, expanded) {
+  var rowIndex = Tobago.Tree.rowIndex(node);
+  return expanded.val().indexOf("," + rowIndex + ",") > -1;
+};
+
+Tobago.Tree.rowIndex = function (node) {
+  return node.attr("id").replace(/.+\:(\d+)(\:\w+)+/, '$1');
+};
+
+Tobago.Tree.findChildren = function (node) {
+  var treeParentSelector = "[data-tobago-tree-parent='" + node.attr("id") + "']";
+  var children;
+  if (Tobago.Tree.isInSheet(node)) {
+    children = node.parent("td").parent("tr").nextAll().children().children(treeParentSelector);
+  } else { // normal tree
+    children = node.nextAll(treeParentSelector);
+  }
+  return children;
+};
+
+Tobago.Tree.isInSheet = function(node) {
+  return node.parent("td").size() == 1;
+};
+
+Tobago.registerListener(Tobago.Tree.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Tree.init, Tobago.Phase.AFTER_UPDATE);
+
+
+Tobago.TreeListbox = {};
+
+Tobago.TreeListbox.init = function(elements) {
+
+  var treeListbox = Tobago.Utils.selectWithJQuery(elements, ".tobago-treeListbox");
+  // hide select tags for level > root
+  treeListbox.children().find("select:not(:first)").hide();
+
+  var listboxSelects = treeListbox.find("select");
+
+  listboxSelects.children("option").each(Tobago.TreeListbox.initNextLevel);
+  listboxSelects.each(Tobago.TreeListbox.initListeners);
+};
+
+// find all option tags and add the dedicated select tag in its data section.
+Tobago.TreeListbox.initNextLevel = function() {
+  var option = jQuery(this);
+  var select = option.closest(".tobago-treeListbox-level").next()
+      .find("[data-tobago-tree-parent='" + option.attr("id") + "']");
+  if (select.length == 1) {
+    option.data("tobago-select", select);
+  } else {
+    var empty = option.closest(".tobago-treeListbox-level").next().children(":first");
+    option.data("tobago-select", empty);
+  }
+};
+
+// add on change on all select tag, all options that are not selected hide there dedicated
+// select tag, and the selected option show its dedicated select tag.
+Tobago.TreeListbox.initListeners = function() {
+
+  jQuery(this).change(Tobago.TreeListbox.onChange);
+
+  jQuery(this).focus(function() {
+    jQuery(this).change();
+  });
+};
+
+Tobago.TreeListbox.onChange = function() {
+  var listbox = jQuery(this);
+  listbox.children("option:not(:selected)").each(function() {
+    jQuery(this).data("tobago-select").hide();
+  });
+  listbox.children("option:selected").each(function() {
+    jQuery(this).data("tobago-select").show();
+  });
+  Tobago.TreeListbox.setSelected(listbox);
+
+  // Deeper level (2nd and later) should only show the empty select tag.
+  // The first child is the empty selection.
+  listbox.parent().nextAll(":not(:first)").each(function() {
+    jQuery(this).children(":not(:first)").hide();
+    jQuery(this).children(":first").show();
+  });
+
+};
+
+Tobago.TreeListbox.setSelected = function(listbox) {
+  var hidden = listbox.closest(".tobago-treeListbox").children("[data-tobago-selection-mode]");
+  if (hidden.length == 1){
+    var selectedValue = ";";
+    listbox.children("option:selected").each(function() {
+      selectedValue += jQuery(this).attr("id") + ";";
+    });
+    hidden.val(selectedValue);
+  }
+};
+
+Tobago.registerListener(Tobago.TreeListbox.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.TreeListbox.init, Tobago.Phase.AFTER_UPDATE);
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-utils.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-utils.js
new file mode 100644
index 0000000..b7e3ad9
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago-utils.js
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+Tobago.Utils = {};
+
+/**
+ *
+ * @param id A JSF client id, type=string. Example: escapeClientId("page:input") -> "#page\\:input"
+ * @return A string which can be used as a jQuery selector.
+ */
+Tobago.Utils.escapeClientId = function(id) {
+  return '#' + id.replace(/([:\.])/g, '\\$1');
+};
+
+/**
+ * @deprecated since Tobago 2.0.5 because of misspelling
+ */
+Tobago.Utils.selectWidthJQuery = function(elements, selector) {
+  return Tobago.Utils.selectWithJQuery(elements, selector);
+};
+
+/**
+ * Helps to select either elements from the whole DOM or only find in sub trees
+ * (in the case of AJAX partial rendering)
+ * @param elements a jQuery object to initialize (ajax) or null for initializing the whole document (full load).
+ * @param selector a jQuery selector.
+ */
+Tobago.Utils.selectWithJQuery = function(elements, selector) {
+  return elements == null
+      ? jQuery(selector)
+      : elements.find(selector).add(elements.filter(selector));
+};
+
+Tobago.Utils.findSubComponent = function(element, subId) {
+  return jQuery(Tobago.Utils.getSubComponentId(element.attr('id'), subId));
+};
+
+Tobago.Utils.getSubComponentId = function(id, subId) {
+  if (id != null) {
+    return "#" + id.replace(/:/g, "\\:") + "\\:\\:" + subId;
+  } else {
+    return null;
+  }
+};
+
+/** @deprecated */
+Tobago.Utils.findSuperComponent = function(element) {
+  return jQuery(Tobago.Utils.getSuperComponentId(element.attr('id')));
+};
+
+Tobago.Utils.getSuperComponentId = function(id) {
+  return "#" + id.substring(0, id.lastIndexOf("::")).replace(/:/g, "\\:");
+};
+
+/**
+ * "a:b" -> "a"
+ * "a:b:c" -> "a:b"
+ * "a" -> null
+ * null -> null
+ * "a:b::sub-component" -> "a"
+ * "a::sub-component:b" -> "a::sub-component" // should currently not happen in Tobago
+ *
+ * @param id The clientId of a component.
+ * @return The clientId of the naming container.
+ */
+Tobago.Utils.getNamingContainerId = function (id) {
+  if (id == null) {
+    return null;
+  }
+  if (id.lastIndexOf(":") == -1) {
+    return null;
+  }
+  while (true) {
+    var sub = id.lastIndexOf("::");
+    if (sub == -1) {
+      break;
+    }
+    if (sub + 1 == id.lastIndexOf(":")) {
+      id = id.substring(0, sub);
+    } else {
+      break;
+    }
+  }
+  return id.substring(0, id.lastIndexOf(":"));
+};
+
+/**
+ * fix position, when the element it is outside of the current page
+ * @param elements is an jQuery Array of elements to be fixed.
+ */
+Tobago.Utils.keepElementInVisibleArea = function(elements) {
+  elements.each(function() {
+    var element = jQuery(this);
+    var page = jQuery(".tobago-page-content:first");
+    var left = element.offset().left;
+    var top = element.offset().top;
+    // fix menu position, when it is outside of the current page
+    left = Math.max(0, Math.min(left, page.outerWidth() - element.outerWidth()));
+    top = Math.max(0, Math.min(top, page.outerHeight() - element.outerHeight()));
+    element.css('left', left);
+    element.css('top', top);
+  });
+};
+
+/** @deprecated */
+Tobago.Utils.acceleratorKeyEvent = function() {
+  return Tobago.browser.isWebkit || Tobago.browser.isGecko ? 'keydown' : 'keypress';
+};
+
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago.js
new file mode 100644
index 0000000..bb82068
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/script/tobago.js
@@ -0,0 +1,1445 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+var Tobago = {
+
+  // -------- Constants -------------------------------------------------------
+
+  /**
+   * Component separator constant
+   * @const
+   * @type {string}
+   */
+  COMPONENT_SEP: ':',
+
+  /**
+   * Tobago's subComponent separator constant
+   * @const
+   * @type {string}
+   */
+  SUB_COMPONENT_SEP: '::',
+
+  // -------- Variables -------------------------------------------------------
+
+  /**
+   * The html form object of current page.
+   * set via init function
+   */
+  form: null,
+
+  htmlIdIndex: 0,
+
+  createHtmlId: function() {
+    var id = '__tbg_id_' + this.htmlIdIndex++;
+    console.debug('created id = ' + id); // @DEV_ONLY
+    return id;
+  },
+
+  reloadTimer: {},
+
+  jsObjects: [],
+
+  eventListeners: [],
+
+  /**
+    * Check browser types and versions.
+    * Please try to use jQuery.support instead of this object!
+    */
+  browser: {
+    isMsie: false,
+    isMsie6: false,
+    isMsie67: false,
+    isMsie678: false,
+    isMsie6789: false,
+    isMsie678910: false,
+    isGecko: false,
+    isWebkit: false
+  },
+
+  isSubmit: false,
+
+  initMarker: false,
+
+  listeners: {
+    documentReady: [[], [], [], []],
+    windowLoad: [[], [], [], []],
+    beforeSubmit: [[], [], [], []],
+    afterUpdate: [[], [], [], []],
+    beforeUnload: [[], [], [], []],
+    beforeExit: [[], [], [], []]
+  },
+
+  // -------- Functions -------------------------------------------------------
+
+  /**
+   * Register a function to be executed on certain events.
+   * @param listener Function to be executed.
+   * @param phase The phase when code should be executed (e. g. Tobago.Phase.DOCUMENT_READY).
+   * @param order An optional order to sort function they depend on others (default: Tobago.Phase.Order.NORMAL).
+   */
+  registerListener: function(listener, phase, order) {
+
+    if (order == undefined) {
+      order = Tobago.Phase.Order.NORMAL;
+    }
+
+    var phaseMap;
+    if (Tobago.Phase.DOCUMENT_READY == phase) {
+      phaseMap = Tobago.listeners.documentReady;
+    } else if (Tobago.Phase.WINDOW_LOAD == phase) {
+      phaseMap = Tobago.listeners.windowLoad;
+    } else if (Tobago.Phase.BEFORE_SUBMIT == phase) {
+      phaseMap = Tobago.listeners.beforeSubmit;
+    } else if (Tobago.Phase.AFTER_UPDATE == phase) {
+      phaseMap = Tobago.listeners.afterUpdate;
+    } else if (Tobago.Phase.BEFORE_UNLOAD == phase) {
+      phaseMap = Tobago.listeners.beforeUnload;
+    } else if (Tobago.Phase.BEFORE_EXIT == phase) {
+      phaseMap = Tobago.listeners.beforeExit;
+    } else {
+      console.error("Unknown phase: " + phase); // @DEV_ONLY
+      return;
+    }
+
+    phaseMap[order].push(listener);
+  },
+
+  findPage: function() {
+    return jQuery(".tobago-page");
+  },
+
+  findForm: function() {
+    return Tobago.findSubElementOfPage("form");
+  },
+
+  /**
+   * Find a sub-element of the page. Like the form with id e.g. page::form
+   * @param suffix
+   */
+  findSubElementOfPage: function(suffix) {
+    return jQuery(Tobago.Utils.escapeClientId(Tobago.findPage().attr("id") + Tobago.SUB_COMPONENT_SEP + suffix));
+  },
+
+  /**
+   * Tobago's central init function.
+   * Called when the document (DOM) is ready
+   */
+  init: function() {
+
+    if (this.initMarker) {
+      return;
+    }
+    this.initMarker = true;
+
+    console.time("[tobago] init"); // @DEV_ONLY
+    this.addBindEventListener(Tobago.findForm().get(0), 'submit', this, 'onSubmit');
+
+    this.addBindEventListener(window, 'unload', this, 'onUnload');
+
+    for (var order = 0; order < Tobago.listeners.documentReady.length; order++) {
+      var list = Tobago.listeners.documentReady[order];
+      for (var i = 0; i < list.length; i++) {
+        console.time("[tobago] init " + order + " " + i); // @DEV_ONLY
+        list[i]();
+        console.timeEnd("[tobago] init " + order + " " + i); // @DEV_ONLY
+      }
+    }
+
+    console.timeEnd("[tobago] init"); // @DEV_ONLY
+  },
+
+  onSubmit: function(listenerOptions) {
+    var result = true; // Do not continue if any function returns false
+    for (var order = 0; order < Tobago.listeners.beforeSubmit.length; order++) {
+      var list = Tobago.listeners.beforeSubmit[order];
+      for (var i = 0; i < list.length; i++) {
+        result = list[i](listenerOptions);
+        if (result == false) {
+          break;
+        }
+      }
+    }
+    if (result == false) {
+      this.isSubmit = false;
+      return false;
+    }
+
+    this.isSubmit = true;
+
+    Tobago.onBeforeUnload();
+
+    return true;
+  },
+
+  onBeforeUnload: function() {
+    if (Tobago.transition) {
+      jQuery("body").overlay();
+    }
+    Tobago.transition = Tobago.oldTransition;
+  },
+
+  preparePartialOverlay: function(options) {
+    if (options.transition === undefined || options.transition == null || options.transition) {
+      console.info("options.render: " + options.render); // @DEV_ONLY
+      if (options.render) {
+        var partialIds = options.render.split(" ");
+        for (var i = 0; i < partialIds.length; i++) {
+          console.info("partialId: " + partialIds[i]); // @DEV_ONLY
+          var element = jQuery(Tobago.Utils.escapeClientId(partialIds[i]));
+          element.data("tobago-partial-overlay-set", true);
+          element.overlay({ajax: true});
+        }
+      }
+    }
+  },
+
+  /**
+   * Wrapper function to call application generated onunload function
+   */
+  onUnload: function() {
+
+    var phase = this.isSubmit ? Tobago.listeners.beforeUnload : Tobago.listeners.beforeExit;
+
+    for (var order = 0; order < phase.length; order++) {
+      var list = phase[order];
+      for (var i = 0; i < list.length; i++) {
+        list[i]();
+      }
+    }
+
+    this.destroyObjects();
+  },
+
+  addJsObject: function(obj) {
+    this.jsObjects[this.jsObjects.length] = obj;
+  },
+
+  destroyObjects: function() {
+    this.removeEventListeners();
+
+    for (var i = 0; i < this.jsObjects.length; i++) {
+      try {
+        this.destroyObject(this.jsObjects[i]);
+      } catch (ex) {
+        // ignore
+      }
+    }
+    this.jsObjects.length = 0;
+    delete this.jsObjects;
+  },
+
+  removeEventListeners: function() {
+    var count = 0;
+    for (var i = 0; i < this.eventListeners.length; i++) {
+      var el = this.eventListeners[i];
+      this.removeEventListener(el);
+      delete el.element;
+      delete el.event;
+      delete el.func;
+      this.eventListeners[i] = undefined;
+      count++;
+    }
+    delete this.eventListeners;
+//    alert(count + " EverntListener geloescht");
+  },
+
+  destroyObject: function(obj) {
+    if (obj.htmlElement) {
+      // test
+      delete obj.htmlElement.jsObjects;
+      delete obj.htmlElement;
+    } else {
+      // Unknown Object --> delete all properties
+      if (typeof obj == 'Object') {
+        this.destroyJsObject(obj);
+      } else if (typeof obj == 'Array') {
+        obj.length = 0;
+        delete obj;
+      }
+    }
+  },
+
+  destroyJsObject: function(obj) {
+    try {
+      for (var item in obj) {
+        delete obj[item];
+      }
+      delete obj;
+    } catch (ex) {
+      // ignore
+    }
+  },
+
+  /**
+   * Submitting the page with specified actionId.
+   * options.transition
+   * options.target
+   */
+  submitAction: function(source, actionId, options) {
+    options = options || {};
+
+    var transition = options.transition === undefined || options.transition == null || options.transition;
+
+    Tobago.Transport.request(function() {
+      if (!this.isSubmit) {
+        this.isSubmit = true;
+        var form = Tobago.findForm();
+        var oldTarget = form.attr("target");
+        var $sourceHidden = jQuery(Tobago.Utils.escapeClientId("javax.faces.source"));
+        $sourceHidden.prop("disabled", false);
+        $sourceHidden.val(actionId);
+        if (options.target) {
+          form.attr("target", options.target);
+        }
+        Tobago.oldTransition = Tobago.transition;
+        Tobago.transition = transition && !options.target;
+
+        var listenerOptions = {
+          source: source,
+          actionId: actionId,
+          options: options
+        };
+        var onSubmitResult = Tobago.onSubmit(listenerOptions);
+        if (onSubmitResult) {
+          try {
+            // console.debug("submit form with action: " + Tobago.action.value);
+            form.get(0).submit();
+            // reset the source field after submit, to be prepared for possible next AJAX with transition=false
+            $sourceHidden.prop("disabled", true);
+            $sourceHidden.val();
+            if (Tobago.browser.isMsie) {
+              // without this "redundant" code the animation will not be animated in IE (tested with 6,7,8,9,10,11)
+              var image = jQuery(".tobago-page-overlayCenter img");
+              image.appendTo(image.parent());
+            }
+          } catch (e) {
+            Tobago.findPage().overlay("destroy");
+            Tobago.isSubmit = false;
+            alert('Submit failed: ' + e); // XXX localization, better error handling
+          }
+        }
+        if (options.target) {
+          if (oldTarget) {
+            form.attr("target", oldTarget);
+          } else {
+            form.removeAttr("target");
+          }
+        }
+        if (options.target || !transition || !onSubmitResult) {
+          this.isSubmit = false;
+          Tobago.Transport.pageSubmitted = false;
+        }
+      }
+      if (!this.isSubmit) {
+        Tobago.Transport.requestComplete(); // remove this from queue
+      }
+
+
+    }, true);
+  },
+
+  getJsfState: function() {
+    var stateContainer = Tobago.findSubElementOfPage("jsf-state-container").get(0);
+    var jsfState = "";
+    if (stateContainer) {
+      for (var i = 0; i < stateContainer.childNodes.length; i++) {
+        var child = stateContainer.childNodes[i];
+        if (child.tagName == 'INPUT') {
+          if (jsfState.length > 0) {
+            jsfState += '&';
+          }
+          jsfState += encodeURIComponent(child.name);
+          jsfState += '=';
+          jsfState += encodeURIComponent(child.value);
+        }
+      }
+    }
+//    console.debug("jsfState = " + jsfState);
+    return jsfState;
+  },
+
+  clearReloadTimer: function(id) {
+    var timer = Tobago.reloadTimer[id];
+    if (timer) {
+      clearTimeout(timer);
+    }
+  },
+
+  addReloadTimeout: function(id, func, time) {
+    Tobago.clearReloadTimer(id);
+    Tobago.reloadTimer[id] = setTimeout(func, time);
+  },
+
+  initCommand: function(element) {
+    // command is jQuery object
+    // setupInputFacetCommand
+    var commands = element.data("tobago-commands");
+
+    var normalEvents = []; // todo: find a better way to do that in JS
+    if (commands.click) {
+      normalEvents.push({event: "click", command: commands.click});
+    }
+    if (commands.dblclick) {
+      normalEvents.push({event: "dblclick", command: commands.dblclick});
+    }
+    if (commands.focus) {
+      normalEvents.push({event: "focus", command: commands.focus});
+    }
+    if (commands.blur) {
+      normalEvents.push({event: "blur", command: commands.blur});
+    }
+
+    for (var i in normalEvents) {
+
+      element.on(normalEvents[i].event, {command: normalEvents[i].command}, function (event) {
+        var command = event.data.command;
+        var confirmation = command.confirmation;
+        if (confirmation != null) {
+          if (!confirm(confirmation)) {
+            event.preventDefault();
+            return;
+          }
+        }
+        var collapse = command.collapse;
+        if (collapse) {
+          Tobago.Collapse.execute(collapse);
+        }
+
+        if (command.omit != true) {
+          var popup = command.popup;
+          if (popup && popup.command == "close" && popup.immediate) {
+            Tobago.Popup.close(this);
+          } else {
+            var action = command.action ? command.action : jQuery(this).attr("id");
+            if (command.execute || command.render) {
+              Tobago.preparePartialOverlay(command);
+              jsf.ajax.request(
+                  action,
+                  event,
+                  {
+                    "javax.faces.behavior.event": event.type,
+                    execute: command.execute,
+                    render: command.render
+                  });
+              event.preventDefault();
+              event.stopPropagation();
+            } else {
+              Tobago.submitAction(this, action, command);
+            }
+            if (popup && popup.command == "close") {
+              Tobago.Popup.close(this);
+            }
+          }
+        }
+      });
+    }
+    if (commands.change) {
+      element.change(function(event) {
+        if (commands.change.execute || commands.change.render) {
+          jsf.ajax.request(
+              jQuery(this).attr("name"),
+              event,
+              {
+                "javax.faces.behavior.event": "change",
+                execute: commands.change.execute,
+                render: commands.change.render
+              });
+        } else {
+          Tobago.submitAction(this, commands.change.action, commands.change);
+        }
+      });
+    }
+    if (commands.complete) {
+      if (element.val() >= parseFloat(element.attr("max"))) {
+        if (commands.complete.execute || commands.complete.render) {
+          jsf.ajax.request(
+              jQuery(this).attr("id"),
+              null,
+              {
+                "javax.faces.behavior.event": "complete",
+                execute: commands.complete.execute,
+                render: commands.complete.render
+              });
+        } else {
+          Tobago.submitAction(this, commands.complete.action, commands.complete);
+        }
+      }
+    }
+    if (commands.load) {
+      setTimeout(function() {
+            Tobago.submitAction(this, commands.load.action, commands.load);
+          },
+          commands.load.delay || 100);
+    }
+    if (commands.resize) {
+      jQuery(window).resize(function() {
+        console.debug("window resize event: " + commands.resize); // @DEV_ONLY
+        Tobago.submitAction(this, commands.resize.action, commands.resize);
+      });
+    }
+  },
+
+  initDom: function(elements) {
+
+    // focus
+    Tobago.initFocus(elements);
+
+    // commands
+    Tobago.Utils.selectWithJQuery(elements, '[data-tobago-commands]')
+        .each(function () {Tobago.initCommand(jQuery(this));});
+
+    Tobago.initScrollPosition(elements ? elements : jQuery(".tobago-page"));
+  },
+
+  initScrollPosition: function(elements) {
+    var scrollPanels;
+    if (elements.data("tobago-scroll-panel")) {
+      scrollPanels = elements;
+    } else {
+      scrollPanels = elements.find("[data-tobago-scroll-panel]");
+    }
+    scrollPanels.bind("scroll", function () {
+      var panel = jQuery(this);
+      var scrollLeft = panel.prop("scrollLeft");
+      var scrollTop = panel.prop("scrollTop");
+      // store the position in a hidden field
+      panel.children("[data-tobago-scroll-position]").val(scrollLeft + ";" + scrollTop);
+    });
+    scrollPanels.each(function () {
+      var panel = jQuery(this);
+      var hidden = panel.children("[data-tobago-scroll-position]");
+      var sep = hidden.val().indexOf(";");
+      if (sep != -1) {
+        var scrollLeft = hidden.val().substr(0, sep);
+        var scrollTop = hidden.val().substr(sep + 1);
+        panel.prop("scrollLeft", scrollLeft);
+        panel.prop("scrollTop", scrollTop);
+      }
+    });
+  },
+
+  initCss: function (elements) {
+    // element styles
+    console.time("[tobago] initCss"); // @DEV_ONLY
+    Tobago.Utils.selectWithJQuery(elements, "[data-tobago-style]").each(function () {
+      var element = jQuery(this);
+      var data = element.data("tobago-style");
+
+      // set only known properties (because of security)
+      element.css({
+        width: data.width,
+        height: data.height,
+
+        minWidth: data.minWidth,
+        minHeight: data.minHeight,
+        maxWidth: data.maxWidth,
+        maxHeight: data.maxHeight,
+
+        left: data.left,
+        right: data.right,
+        top: data.top,
+        bottom: data.bottom,
+
+        paddingLeft: data.paddingLeft,
+        paddingRight: data.paddingRight,
+        paddingTop: data.paddingTop,
+        paddingBottom: data.paddingBottom,
+
+        marginLeft: data.marginLeft,
+        marginRight: data.marginRight,
+        marginTop: data.marginTop,
+        marginBottom: data.marginBottom,
+
+        overflowX: data.overflowX,
+        overflowY: data.overflowY,
+        display: data.display,
+        position: data.position,
+
+        backgroundImage: data.backgroundImage,         // TBD
+        backgroundPosition: data.backgroundPosition,   // TBD
+        zIndex: data.zIndex, // TBD: needed? will be set by Tobago? check org.apache.myfaces.tobago.renderkit.css.Style
+        textAlign: data.textAlign
+      });
+    });
+
+    console.timeEnd("[tobago] initCss"); // @DEV_ONLY
+  },
+
+  /* supports only two background images in the moment */
+  fixMultiBackgroundIE8: function (element) {
+    var style = element.data("tobago-style");
+    var index;
+    var backgroundImage = style.backgroundImage;
+    var backgroundImage2;
+    if (backgroundImage) {
+      index = backgroundImage.indexOf(",");
+      if (index > -1) {
+        style.backgroundImage = backgroundImage.substring(0, index);
+        backgroundImage2 = backgroundImage.substring(index + 1);
+      }
+    }
+    var backgroundPosition = style.backgroundPosition;
+    var backgroundPosition2;
+    if (backgroundPosition) {
+      index = backgroundPosition.indexOf(",");
+      if (index > -1) {
+        style.backgroundPosition = backgroundPosition.substring(0, index);
+        backgroundPosition2 = backgroundPosition.substring(index + 1);
+      }
+    }
+    if (backgroundImage2) {
+      var extra = jQuery("<span>").appendTo(element);
+      extra.css({
+        backgroundImage: backgroundImage2,
+        backgroundPosition: backgroundPosition2,
+        backgroundRepeat: "no-repeat",
+        position: "absolute",
+        left: "0",
+        right: "0",
+        top: "0",
+        bottom: "0"
+      });
+      element.css({
+        position: "relative"
+      });
+    }
+  },
+
+  preventFrameAttacks: function() {
+    if (self == top) {
+      jQuery(".tobago-page-preventFrameAttacks").removeClass("tobago-page-preventFrameAttacks");
+    } else {
+      if (jQuery(".tobago-page-preventFrameAttacks").size() > 0) { // preventFrameAttacks is true
+        var page = Tobago.findPage();
+        page.attr("title", "This application can't be used embedded inside an other site " +
+        "(configuration: prevent-frame-attacks=true)!");
+        jQuery("<i>")
+            .addClass("fa fa-flash")
+            .css({fontSize: "xx-large", margin: "20px"})
+            .appendTo(page);
+        page.addClass("alert-danger");
+      }
+    }
+  },
+
+// -------- Util functions ----------------------------------------------------
+
+  /**
+   * Sets the focus to the requested element or to the first possible if
+   * no element is explicitly requested.
+   *
+   * The priority order is:
+   * - error (the first error element gets the focus)
+   * - auto (the element with the tobago tag attribute focus="true" gets the focus)
+   * - last (the element from the last request with same id gets the focus, not AJAX)
+   * - first (the first input element (without tabindex=-1) gets the focus, not AJAX)
+   */
+  initFocus: function(elements) {
+
+    var $focusable = jQuery(":input:enabled:visible:not(button):not([tabindex='-1'])");
+    $focusable.focus(function () {
+      // remember the last focused element, for later
+      Tobago.findSubElementOfPage("lastFocusId").val(jQuery(this).attr("id"));
+    });
+
+    var $hasDanger = Tobago.Utils.selectWithJQuery(elements, '.has-danger');
+    var $dangerInput = $hasDanger.find("*").filter(":input:enabled:visible:first");
+    if ($dangerInput.size() > 0) {
+      Tobago.setFocus($dangerInput);
+      return;
+    }
+
+    var $autoFocus = Tobago.Utils.selectWithJQuery(elements, '[autofocus]');
+    var hasAutoFocus = $autoFocus.size() > 0;
+    if (hasAutoFocus) {
+      // nothing to do, because the browser make the work.
+
+      // autofocus in popups doesn't work automatically... so we fix that here
+      jQuery('.modal').on('shown.bs.modal', function() {
+        Tobago.setFocus(jQuery(this).find('[autofocus]'));
+      });
+
+      return;
+    }
+
+    if (elements) {
+      // seems to be AJAX, so end here
+      return;
+    }
+
+    var lastFocusId = Tobago.findSubElementOfPage("lastFocusId").val();
+    if (lastFocusId) {
+      Tobago.setFocus(jQuery(Tobago.Utils.escapeClientId(lastFocusId)));
+      return;
+    }
+
+    var $firstInput = jQuery(":input:enabled:visible:not(button):not([tabindex='-1']):first");
+    if ($firstInput.size() > 0) {
+      Tobago.setFocus($firstInput);
+      return;
+    }
+  },
+
+  setFocus: function($element) {
+    try {
+      // focus() on not visible elements breaks some IE
+      $element.focus();
+    } catch (e) {
+      console.error("element-id=" + $element.attr("id") + " exception=" + e); // @DEV_ONLY
+    }
+  },
+
+  /**
+   * Create a HTML input element with given type, name and value.
+   */
+  createInput: function(type, name, value) {
+    var input = document.createElement('INPUT');
+    if (type) {
+      input.type = type;
+    }
+    if (name) {
+      input.name = name;
+    }
+    if (value) {
+      input.value = value;
+    }
+    return input;
+  },
+
+  /**
+   * Clear the selection.
+   */
+  clearSelection: function() {
+    if (document.selection) {  // IE
+      try {
+        document.selection.empty();
+      } catch (error) {
+        // Ignore error: seems to be a browser bug (TOBAGO-1201)
+      }
+    } else if (window.getSelection) {  // GECKO
+      window.getSelection().removeAllRanges();
+    }
+  },
+
+  /**
+   * Add an event listener to an HTML element
+   */
+  addEventListener: function(element, event, myFunction) {
+    var el = new Tobago.EventListener(element, event, myFunction);
+    if (el.element.addEventListener) { // this is DOM2
+      el.element.addEventListener(el.event, el.func, false);
+    } else { // IE
+      el.element.attachEvent('on' + el.event, el.func);
+    }
+  },
+
+  /**
+   * Remove an event listener from an HTML element
+   */
+  removeEventListener: function(element, event, myFunction) {
+    if (!event && !myFunction && element.element && element.event && element.func) {
+      myFunction = element.func;
+      event = element.event;
+      element = element.element;
+    }
+    if (element.removeEventListener) { // this is DOM2
+      element.removeEventListener(event, myFunction, true);
+    }
+    else if (element.detachEvent) {  // IE
+      element.detachEvent('on' + event, myFunction);
+    } else {
+      console.debug('Unknown Element: ' + typeof element); // @DEV_ONLY
+    }
+
+  },
+
+  /**
+   * Returns a function which binds the named function 'func' of the object 'object'.
+   * additional arguments to bind function are added to the arguments at
+   * function call.
+   * E.g.:
+   * var f = Tobago.bind(Tobago, "setElementWidth");
+   * will bind Tobago.setElementWidth(...) to f(...)
+   * and
+   * var f = Tobago.bind(Tobago, "setElementWidth", id, width);
+   * will bind Tobago.setElementWidth(id, widt) to f()
+   * and
+   * var f = Tobago.bind(Tobago, "setElementWidth", width);
+   * will bind Tobago.setElementWidth(id, width) to f(id)
+   *
+   */
+  bind: function(object, func) {
+    var rest = [];
+    for (var i = 2; i < arguments.length; i++) {
+      rest.push(arguments[i]);
+    }
+    return function() {
+      var args = [];
+      for (var i = 0; i < arguments.length; i++) {
+        args.push(arguments[i]);
+      }
+      object[func].apply(object, args.concat(rest));
+    };
+  },
+
+  bind2: function(object, func) {
+    var rest = [];
+    for (var i = 2; i < arguments.length; i++) {
+      rest.push(arguments[i]);
+    }
+    return function() {
+      for (var i = 0; i < arguments.length; i++) {
+        rest.push(arguments[i]);
+      }
+      object[func].apply(object, rest);
+    };
+  },
+
+  /**
+   * Returns a function which binds the named function 'func' of the object 'object'
+   * as eventListener.
+   * E.g.:
+   * var f = Tobago.bindAsEventListener(Tobago, "doSomthing");
+   * will bind Tobago.doSomthing(event) to f(event)
+   */
+  bindAsEventListener: function(object, func) {
+    return function(event) {
+      object[func].call(object, event || window.event);
+    };
+  },
+
+  /**
+   * Adds a function which binds the named function 'func' of the object 'object'
+   * as eventListener to an element.
+   */
+  addBindEventListener: function(element, event, object, func) {
+    this.addEventListener(element, event, this.bindAsEventListener(object, func));
+  },
+
+
+  /**
+   * Stop event bubbling
+   */
+  stopEventPropagation: function(event) {
+    if (! event) {
+      event = window.event;
+    }
+    event.cancelBubble = true;  // this is IE, no matter if not supported by actual browser
+    if (event.stopPropagation) {
+      event.stopPropagation(); // this is DOM2
+    }
+    if (event.preventDefault) {
+      event.preventDefault();
+    } else {
+      event.returnValue = false;
+    }
+  },
+
+  /**
+   * Returns the absolute top value, related to the body element, for an HTML element.
+   */
+  getAbsoluteTop: function(element) {
+    var top = 0;
+    var parent = false;
+    while (element && element.offsetParent) {
+      top += element.offsetTop;
+      top -= element.scrollTop;
+      if (parent && element.currentStyle) { // IE only
+        top += element.currentStyle.borderTopWidth.replace(/\D/g, '') - 0;
+      }
+      element = element.offsetParent;
+      parent = true;
+    }
+    return Math.max(top, 0);
+  },
+
+  extend: function(target, source) {
+    for (var property in source) {
+      target[property] = source[property];
+    }
+    return target;
+  },
+
+  raiseEvent: function(eventType, element) {
+    var event;
+    if (document.createEvent) {
+      event = document.createEvent('Events');
+      event.initEvent(eventType, true, true);
+      element.dispatchEvent(event);
+    }
+    else if (document.createEventObject) {
+      event = document.createEventObject();
+      element.fireEvent('on' + eventType, event);
+    }
+  },
+
+  toString: function(element) {
+    var result = '';
+    for (var property in element) {
+      if (property && element[property]) {
+        var value = '' + element[property];
+        if (value != '') {
+          result += '\r\n' + property + '=' + value;
+        }
+      }
+    }
+    return result;
+  },
+
+  initBrowser: function() {
+    var ua = navigator.userAgent;
+    if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) {
+      Tobago.browser.isMsie = true;
+      if (ua.indexOf("MSIE 6") > -1) {
+        Tobago.browser.isMsie6 = true;
+        Tobago.browser.isMsie67 = true;
+        Tobago.browser.isMsie678 = true;
+        Tobago.browser.isMsie6789 = true;
+        Tobago.browser.isMsie678910 = true;
+      } else if (ua.indexOf("MSIE 7") > -1) {
+        Tobago.browser.isMsie67 = true;
+        Tobago.browser.isMsie678 = true;
+        Tobago.browser.isMsie6789 = true;
+        Tobago.browser.isMsie678910 = true;
+      } else if (ua.indexOf("MSIE 8") > -1) {
+        Tobago.browser.isMsie678 = true;
+        Tobago.browser.isMsie6789 = true;
+        Tobago.browser.isMsie678910 = true;
+      } else if (ua.indexOf("MSIE 9") > -1) {
+        Tobago.browser.isMsie6789 = true;
+        Tobago.browser.isMsie678910 = true;
+      } else if (ua.indexOf("MSIE 10") > -1) {
+        Tobago.browser.isMsie678910 = true;
+      }
+    } else if (ua.indexOf("AppleWebKit") > -1) {
+      Tobago.browser.isWebkit = true;
+    } else if (ua.indexOf("Gecko") > -1) {
+      Tobago.browser.isGecko = true;
+    }
+  }
+};
+
+Tobago.initBrowser();
+
+jQuery(document).ready(function() {
+  Tobago.init();
+});
+
+jQuery(window).load(function() {
+  for (var order = 0; order < Tobago.listeners.windowLoad.length; order++) {
+    var list = Tobago.listeners.windowLoad[order];
+    for (var i = 0; i < list.length; i++) {
+      list[i]();
+    }
+  }
+});
+
+Tobago.Phase = {
+  /** after the DOM was build */
+  DOCUMENT_READY:{},
+  /** after all images and CSS was loaded */
+  WINDOW_LOAD:{},
+  /** before sending a normal submit action */
+  BEFORE_SUBMIT:{},
+  /** after an AJAX call */
+  AFTER_UPDATE:{},
+  /** before ending a page */
+  BEFORE_UNLOAD:{},
+  /** before closing a window or tab */
+  BEFORE_EXIT:{},
+
+  Order:{
+    EARLY:0,
+    NORMAL:1,
+    LATE:2,
+    LATER:3
+  }
+};
+
+Tobago.Config = {
+  set: function(name, key, value) {
+    if (!this[name]) {
+      this[name] = {};
+    }
+    this[name][key] = value;
+  },
+
+  get: function(name, key) {
+    while (name && !(this[name] && this[name][key])) {
+      name = this.getFallbackName(name);
+    }
+
+    if (name) {
+      return this[name][key];
+    } else {
+      console.warn("Tobago.Config.get(" + name + ", " + key + ") = undefined"); // @DEV_ONLY
+      return 0;
+    }
+  },
+
+  fallbackNames: {},
+
+  getFallbackName: function(name){
+    if (this.fallbackNames[name]) {
+      return this.fallbackNames[name];
+    } else if (name == "Tobago") {
+      return undefined;
+    } else {
+      return "Tobago";
+    }
+  }
+};
+
+Tobago.registerListener(Tobago.preventFrameAttacks, Tobago.Phase.DOCUMENT_READY);
+// using Tobago.Phase.Order.LATE, because the command event generated by data-tobago-commands
+// may produce a submit, but we need to do something before the submit (and also on click,
+// e. g. selectOne in a toolBar).
+Tobago.registerListener(Tobago.initDom, Tobago.Phase.DOCUMENT_READY, Tobago.Phase.Order.LATER);
+Tobago.registerListener(Tobago.initDom, Tobago.Phase.AFTER_UPDATE, Tobago.Phase.Order.LATER);
+
+// the inline css should be applied early, so that other init functions can use the dimensions
+Tobago.registerListener(Tobago.initCss, Tobago.Phase.DOCUMENT_READY, Tobago.Phase.Order.EARLY);
+Tobago.registerListener(Tobago.initCss, Tobago.Phase.AFTER_UPDATE, Tobago.Phase.Order.EARLY);
+
+// XXX: 2nd parameter enableAjax is deprecated
+Tobago.Panel = function(panelId, enableAjax, autoReload) {
+  this.id = panelId;
+  this.autoReload = autoReload;
+  this.options = {
+  };
+
+  this.setup();
+};
+
+Tobago.Panel.init = function(elements) {
+  var reloads = Tobago.Utils.selectWithJQuery(elements, ".tobago-panel[data-tobago-reload]");
+  reloads.each(function(){
+    var id = jQuery(this).attr("id");
+    var period = jQuery(this).data("tobago-reload");
+    new Tobago.Panel(id, true, period);
+  });
+};
+
+Tobago.Panel.prototype.setup = function() {
+  this.initReload();
+};
+
+
+Tobago.Panel.prototype.initReload = function() {
+  if (typeof this.autoReload == 'number' && this.autoReload > 0) {
+    Tobago.addReloadTimeout(this.id, Tobago.bind2(this, 'reloadWithAction', null, this.id), this.autoReload);
+  }
+};
+
+Tobago.Panel.prototype.reloadWithAction = function(source, action) {
+  jsf.ajax.request(
+      action,
+      null,
+      {
+        "javax.faces.behavior.event": "reload",
+        execute: this.id,
+        render: this.id
+      });
+};
+
+Tobago.registerListener(Tobago.Panel.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.Panel.init, Tobago.Phase.AFTER_UPDATE);
+
+Tobago.EventListener = function(element, event, func) {
+  this.element = element;
+  this.event = event;
+  this.func = func;
+  Tobago.eventListeners[Tobago.eventListeners.length] = this;
+};
+
+Tobago.Transport = {
+  requests: [],
+  currentActionId: null,
+  pageSubmitted: false,
+
+  /**
+   * @return true if the request is queued.
+   */
+  request: function(req, submitPage, actionId) {
+    var index = 0;
+    if (submitPage) {
+      this.pageSubmitted = true;
+      index = this.requests.push(req);
+      //console.debug('index = ' + index)
+    } else if (!this.pageSubmitted) { // AJAX case
+      console.debug('Current ActionId = ' + this.currentActionId + ' action= ' + actionId); // @DEV_ONLY
+      if (actionId && this.currentActionId == actionId) {
+        console.info('Ignoring request'); // @DEV_ONLY
+        // If actionId equals currentActionId assume double request: do nothing
+        return false;
+      }
+      index = this.requests.push(req);
+      //console.debug('index = ' + index)
+      this.currentActionId = actionId;
+    } else {
+      console.debug("else case"); // @DEV_ONLY
+      return false;
+    }
+    console.debug('index = ' + index);  // @DEV_ONLY
+    if (index == 1) {
+      console.info('Execute request!'); // @DEV_ONLY
+      this.startTime = new Date().getTime();
+      this.requests[0]();
+    } else {
+      console.info('Request queued!'); // @DEV_ONLY
+    }
+    return true;
+  },
+
+
+// TBD XXX REMOVE is this called in non AJAX case?
+  
+  requestComplete: function() {
+    this.requests.shift();
+    this.currentActionId = null;
+    console.debug('Request complete! Duration: ' + (new Date().getTime() - this.startTime) + 'ms; Queue size : ' + this.requests.length); // @DEV_ONLY
+    if (this.requests.length > 0) {
+      console.debug('Execute request!'); // @DEV_ONLY
+      this.startTime = new Date().getTime();
+      this.requests[0]();
+    }
+  }
+};
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+// Commands
+
+Tobago.Command = {};
+
+Tobago.Command.initEnter = function(elements) {
+  var page = Tobago.Utils.selectWithJQuery(elements, ".tobago-page");
+  page.keypress(function (event) {
+    var code = event.which;
+    if (code == 0) {
+      code = event.keyCode;
+    }
+    if (code == 13) {
+      var target = event.target;
+      if (target.tagName == "A" || target.tagName == "BUTTON") {
+        return;
+      }
+      if (target.tagName == "TEXTAREA") {
+        if (!event.metaKey && !event.ctrlKey) {
+          return;
+        }
+      }
+      var id = target.name ? target.name : target.id;
+      while (id != null) {
+        var command = jQuery("[data-tobago-default='" + id + "']");
+        if (command.size() > 0) {
+          command.click();
+          break;
+        }
+        id = Tobago.Utils.getNamingContainerId(id);
+      }
+      return false;
+    }
+  })};
+
+Tobago.registerListener(Tobago.Command.initEnter, Tobago.Phase.DOCUMENT_READY);
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Tobago.SelectManyShuttle = {};
+
+Tobago.SelectManyShuttle.init = function(elements) {
+
+  var shuttles = Tobago.Utils.selectWithJQuery(elements, ".tobago-selectManyShuttle:not(.tobago-selectManyShuttle-disabled)");
+
+  shuttles.find(".tobago-selectManyShuttle-unselected").dblclick(function() {
+    Tobago.SelectManyShuttle.moveSelectedItems(jQuery(this).parents(".tobago-selectManyShuttle"), true, false);
+  });
+
+  shuttles.find(".tobago-selectManyShuttle-selected").dblclick(function() {
+    Tobago.SelectManyShuttle.moveSelectedItems(jQuery(this).parents(".tobago-selectManyShuttle"), false, false);
+  });
+
+  shuttles.find(".tobago-selectManyShuttle-addAll").click(function() {
+    Tobago.SelectManyShuttle.moveSelectedItems(jQuery(this).parents(".tobago-selectManyShuttle"), true, true);
+  });
+
+  shuttles.find(".tobago-selectManyShuttle-add").click(function() {
+    Tobago.SelectManyShuttle.moveSelectedItems(jQuery(this).parents(".tobago-selectManyShuttle"), true, false);
+  });
+
+  shuttles.find(".tobago-selectManyShuttle-removeAll").click(function() {
+    Tobago.SelectManyShuttle.moveSelectedItems(jQuery(this).parents(".tobago-selectManyShuttle"), false, true);
+  });
+
+  shuttles.find(".tobago-selectManyShuttle-remove").click(function() {
+    Tobago.SelectManyShuttle.moveSelectedItems(jQuery(this).parents(".tobago-selectManyShuttle"), false, false);
+  });
+};
+
+Tobago.SelectManyShuttle.moveSelectedItems = function(shuttle, direction, all) {
+  var unselected = shuttle.find(".tobago-selectManyShuttle-unselected");
+  var selected = shuttle.find(".tobago-selectManyShuttle-selected");
+  var count = selected.children().size();
+  var source = direction ? unselected : selected;
+  var target = direction ? selected : unselected;
+  var shifted = source.find(all ? "option:not(:disabled)" : "option:selected").remove().appendTo(target);
+
+  // synchronize the hidden select
+  var hidden = shuttle.find(".tobago-selectManyShuttle-hidden");
+  var hiddenOptions = hidden.find("option");
+  // todo: may be optimized: put values in a hash map?
+  shifted.each(function() {
+    var option = jQuery(this);
+    hiddenOptions.filter("[value='" + option.val() + "']").prop("selected", direction);
+  });
+
+  if (count != selected.children().size()) {
+    var e = jQuery.Event("change");
+    // trigger an change event for command facets
+    hidden.trigger( e );
+  }
+};
+
+Tobago.registerListener(Tobago.SelectManyShuttle.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.SelectManyShuttle.init, Tobago.Phase.AFTER_UPDATE);
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Tobago.SelectOneRadio = {};
+
+Tobago.SelectOneRadio.init = function(elements) {
+  var selectOneRadios = Tobago.Utils.selectWithJQuery(elements, ".tobago-selectOneRadio");
+  selectOneRadios.each(function() {
+    var ul = jQuery(this);
+    var id = ul.closest("[id]").attr("id");
+    var radios = jQuery('input[name="' + id.replace(/([:\.])/g, '\\$1') + '"]');
+    radios.each(function () {
+      var selectOneRadio = jQuery(this);
+      selectOneRadio.data("tobago-old-value", selectOneRadio.prop("checked"));
+    });
+    radios.click(function() {
+      var selectOneRadio = jQuery(this);
+      var readonly = selectOneRadio.prop("readonly");
+      var required = selectOneRadio.prop("required");
+      if (!required && !readonly) {
+        if (selectOneRadio.data("tobago-old-value") == selectOneRadio.prop("checked")) {
+          selectOneRadio.prop("checked", false);
+        }
+        selectOneRadio.data("tobago-old-value", selectOneRadio.prop("checked"));
+      }
+      if (readonly) {
+        radios.each(function () {
+          var radio = jQuery(this);
+          radio.prop("checked", radio.data("tobago-old-value"));
+        });
+      } else {
+        radios.each(function () {
+          if (this.id != selectOneRadio.get(0).id) {
+            var radio = jQuery(this);
+            radio.prop("checked", false);
+            radio.data("tobago-old-value", radio.prop("checked"));
+          }
+        });
+      }
+    });
+  });
+};
+
+Tobago.registerListener(Tobago.SelectOneRadio.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.SelectOneRadio.init, Tobago.Phase.AFTER_UPDATE);
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Tobago.SelectOneListbox = {};
+
+Tobago.SelectOneListbox.init = function (elements) {
+  var selects = Tobago.Utils.selectWithJQuery(elements, ".tobago-selectOneListbox");
+  var notRequired = selects.not(".tobago-selectOneListbox-markup-required");
+  notRequired
+      .change(function () {
+        var element = jQuery(this);
+        if (element.data("tobago-old-value") == undefined) {
+          element.data("tobago-old-value", -1);
+        }
+      }).click(function () {
+        var element = jQuery(this);
+        if (element.data("tobago-old-value") == undefined
+            || element.data("tobago-old-value") == element.prop("selectedIndex")) {
+          element.prop("selectedIndex", -1);
+        }
+        element.data("tobago-old-value", element.prop("selectedIndex"));
+      });
+};
+
+Tobago.registerListener(Tobago.SelectOneListbox.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.SelectOneListbox.init, Tobago.Phase.AFTER_UPDATE);
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Tobago.SelectBooleanCheckbox = {};
+
+Tobago.SelectBooleanCheckbox.init = function(elements) {
+  var checkboxes = Tobago.Utils.selectWithJQuery(elements, ".tobago-selectBooleanCheckbox-markup-readonly input");
+  checkboxes.each(function() {
+    // Save the initial state to restore it, when the user tries to manipulate it.
+    var initial = jQuery(this).is(":checked");
+    jQuery(this).click(function() {
+      jQuery(this).prop("checked", initial);
+    });
+  });
+};
+
+Tobago.registerListener(Tobago.SelectBooleanCheckbox.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.SelectBooleanCheckbox.init, Tobago.Phase.AFTER_UPDATE);
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Tobago.SelectManyCheckbox = {};
+
+Tobago.SelectManyCheckbox.init = function(elements) {
+  var checkboxes = Tobago.Utils.selectWithJQuery(elements, ".tobago-selectManyCheckbox-markup-readonly input");
+  checkboxes.each(function() {
+    // Save the initial state to restore it, when the user tries to manipulate it.
+    var initial = jQuery(this).is(":checked");
+    jQuery(this).click(function() {
+      jQuery(this).prop("checked", initial);
+    });
+  });
+};
+
+Tobago.registerListener(Tobago.SelectManyCheckbox.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.SelectManyCheckbox.init, Tobago.Phase.AFTER_UPDATE);
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Tobago.File = {};
+
+Tobago.File.init = function(elements) {
+  var files = Tobago.Utils.selectWithJQuery(elements, ".tobago-file-real");
+  files.change(function () {
+    var file = jQuery(this);
+    var pretty = file.parent().find(".tobago-file-pretty");
+    var text;
+    if (file.prop("multiple")) {
+      var format = file.data("tobago-file-multi-format");
+      text = format.replace("{}", file.prop("files").length);
+    } else {
+      text = file.val();
+      // remove path, if any. Some old browsers set the path, others like webkit uses the prefix "C:\facepath\".
+      var pos = Math.max(text.lastIndexOf('/'), text.lastIndexOf('\\'));
+      if (pos >= 0) {
+        text = text.substr(pos + 1);
+      }
+    }
+    pretty.val(text);
+  });
+  // click on the button (when using focus with keyboard)
+  files.each(function() {
+    var real = jQuery(this);
+    real.parent().find("button").click(function() {
+      real.click();
+    });
+  });
+  if (files.length > 0) {
+    Tobago.findForm().attr('enctype', 'multipart/form-data');
+  }
+};
+
+Tobago.registerListener(Tobago.File.init, Tobago.Phase.DOCUMENT_READY);
+Tobago.registerListener(Tobago.File.init, Tobago.Phase.AFTER_UPDATE);
+
+// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+Tobago.Codi = {};
+
+/**
+ * If the window has no name set we set the name and request a new view with unset windowId, so that the
+ * server will generate a new one for us.
+ */
+Tobago.Codi.init = function() {
+
+  var form = Tobago.findForm();
+  var action = form.attr("action");
+  var windowIdEnabled = Tobago.Codi.hasUrlWindowId(action);
+  if (windowIdEnabled && window.name == "") {
+    form.attr("action", Tobago.Codi.urlWithoutWindowId(action));
+    window.name = "window";
+    Tobago.submitAction();
+  }
+};
+
+Tobago.Codi.hasUrlWindowId = function(base) {
+  return base.indexOf("?windowId=") > -1 || base.indexOf("&windowId=") > -1;
+};
+
+/**
+ * taken from myfaces-extcdi (Codi)
+ */
+Tobago.Codi.urlWithoutWindowId = function(base) {
+    var query = base;
+    var vars = query.split(/&|\?/g);
+    var newQuery = "";
+    var iParam = 0;
+    for (var i=0; vars != null && i < vars.length; i++) {
+        var pair = vars[i].split("=");
+        if (pair.length == 1) {
+            newQuery = pair[0];
+        }
+        else {
+            if (pair[0] != "windowId") {
+                var amp = iParam++ > 0 ? "&" : "?";
+                newQuery =  newQuery + amp + pair[0] + "=" + pair[1];
+            }
+        }
+    }
+    return newQuery;
+};
+
+Tobago.registerListener(Tobago.Codi.init, Tobago.Phase.DOCUMENT_READY);
+
+jsf.ajax.addOnEvent(function (event) {
+  console.timeEnd("x"); // @DEV_ONLY
+  console.time("x"); // @DEV_ONLY
+  console.log(event);
+  if (event.status == "success") {
+    console.log("success");// @DEV_ONLY
+
+    jQuery(event.responseXML).find("update").each(function () {
+      var newElement = jQuery(Tobago.Utils.escapeClientId(jQuery(this).attr("id")));
+      console.info("Update after jsf.ajax success: id='" + newElement.attr("id") + "'"); // @DEV_ONLY
+
+      for (var order = 0; order < Tobago.listeners.afterUpdate.length; order++) {
+        var list = Tobago.listeners.afterUpdate[order];
+        for (var i = 0; i < list.length; i++) {
+          list[i](newElement);
+        }
+      }
+    });
+  } else if (event.status == "complete") {
+    console.log("complete");// @DEV_ONLY
+    jQuery(event.responseXML).find("update").each(function () {
+      var updateId = jQuery(this).attr("id");
+      if ("javax.faces.ViewState" != updateId) {
+        var oldElement = jQuery(Tobago.Utils.escapeClientId(updateId));
+        console.info("Update after jsf.ajax complete: id='" + oldElement.attr("id") + "'"); // @DEV_ONLY
+        if (oldElement.data("tobago-partial-overlay-set")) {
+          oldElement.overlay("destroy")
+        }
+      }
+    });
+  }
+});
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows-dark.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows-dark.css
new file mode 100755
index 0000000..630adf7
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows-dark.css
@@ -0,0 +1,106 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+  box-sizing: border-box; }
+
+.tether-element {
+  position: absolute;
+  display: none; }
+  .tether-element.tether-open {
+    display: block; }
+
+.tether-element.tether-theme-arrows-dark {
+  max-width: 100%;
+  max-height: 100%; }
+  .tether-element.tether-theme-arrows-dark .tether-content {
+    border-radius: 5px;
+    position: relative;
+    font-family: inherit;
+    background: #000;
+    color: #fff;
+    padding: 1em;
+    font-size: 1.1em;
+    line-height: 1.5em; }
+    .tether-element.tether-theme-arrows-dark .tether-content:before {
+      content: "";
+      display: block;
+      position: absolute;
+      width: 0;
+      height: 0;
+      border-color: transparent;
+      border-width: 16px;
+      border-style: solid; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-center .tether-content {
+    margin-bottom: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-center .tether-content:before {
+      top: 100%;
+      left: 50%;
+      margin-left: -16px;
+      border-top-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-center .tether-content {
+    margin-top: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-center .tether-content:before {
+      bottom: 100%;
+      left: 50%;
+      margin-left: -16px;
+      border-bottom-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-right.tether-element-attached-middle .tether-content {
+    margin-right: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-right.tether-element-attached-middle .tether-content:before {
+      left: 100%;
+      top: 50%;
+      margin-top: -16px;
+      border-left-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-left.tether-element-attached-middle .tether-content {
+    margin-left: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-left.tether-element-attached-middle .tether-content:before {
+      right: 100%;
+      top: 50%;
+      margin-top: -16px;
+      border-right-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content {
+    margin-top: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content:before {
+      bottom: 100%;
+      left: 16px;
+      border-bottom-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content {
+    margin-top: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content:before {
+      bottom: 100%;
+      right: 16px;
+      border-bottom-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content {
+    margin-bottom: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content:before {
+      top: 100%;
+      left: 16px;
+      border-top-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content {
+    margin-bottom: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content:before {
+      top: 100%;
+      right: 16px;
+      border-top-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content {
+    margin-right: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+      top: 16px;
+      left: 100%;
+      border-left-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content {
+    margin-left: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+      top: 16px;
+      right: 100%;
+      border-right-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content {
+    margin-right: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+      bottom: 16px;
+      left: 100%;
+      border-left-color: #000; }
+  .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content {
+    margin-left: 16px; }
+    .tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+      bottom: 16px;
+      right: 100%;
+      border-right-color: #000; }
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows-dark.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows-dark.min.css
new file mode 100755
index 0000000..8732823
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows-dark.min.css
@@ -0,0 +1 @@
+.tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-center .tether-content,.tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content,.tether-element.tether-theme-arrows-dark.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content{margin-bottom:1pc}.tether-element.tether-theme-arrows-dark.tether-element-attached-b [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows.css
new file mode 100755
index 0000000..2f641a6
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows.css
@@ -0,0 +1,110 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+  box-sizing: border-box; }
+
+.tether-element {
+  position: absolute;
+  display: none; }
+  .tether-element.tether-open {
+    display: block; }
+
+.tether-element.tether-theme-arrows {
+  max-width: 100%;
+  max-height: 100%; }
+  .tether-element.tether-theme-arrows .tether-content {
+    border-radius: 5px;
+    position: relative;
+    font-family: inherit;
+    background: #fff;
+    color: inherit;
+    padding: 1em;
+    font-size: 1.1em;
+    line-height: 1.5em;
+    -webkit-transform: translateZ(0);
+            transform: translateZ(0);
+    -webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
+            filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2)); }
+    .tether-element.tether-theme-arrows .tether-content:before {
+      content: "";
+      display: block;
+      position: absolute;
+      width: 0;
+      height: 0;
+      border-color: transparent;
+      border-width: 16px;
+      border-style: solid; }
+  .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-center .tether-content {
+    margin-bottom: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-center .tether-content:before {
+      top: 100%;
+      left: 50%;
+      margin-left: -16px;
+      border-top-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-center .tether-content {
+    margin-top: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-center .tether-content:before {
+      bottom: 100%;
+      left: 50%;
+      margin-left: -16px;
+      border-bottom-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-right.tether-element-attached-middle .tether-content {
+    margin-right: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-right.tether-element-attached-middle .tether-content:before {
+      left: 100%;
+      top: 50%;
+      margin-top: -16px;
+      border-left-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-left.tether-element-attached-middle .tether-content {
+    margin-left: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-left.tether-element-attached-middle .tether-content:before {
+      right: 100%;
+      top: 50%;
+      margin-top: -16px;
+      border-right-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content {
+    margin-top: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-bottom .tether-content:before {
+      bottom: 100%;
+      left: 16px;
+      border-bottom-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content {
+    margin-top: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-bottom .tether-content:before {
+      bottom: 100%;
+      right: 16px;
+      border-bottom-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content {
+    margin-bottom: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content:before {
+      top: 100%;
+      left: 16px;
+      border-top-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content {
+    margin-bottom: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content:before {
+      top: 100%;
+      right: 16px;
+      border-top-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content {
+    margin-right: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+      top: 16px;
+      left: 100%;
+      border-left-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content {
+    margin-left: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-top.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+      top: 16px;
+      right: 100%;
+      border-right-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content {
+    margin-right: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-left .tether-content:before {
+      bottom: 16px;
+      left: 100%;
+      border-left-color: #fff; }
+  .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content {
+    margin-left: 16px; }
+    .tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-right .tether-content:before {
+      bottom: 16px;
+      right: 100%;
+      border-right-color: #fff; }
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows.min.css
new file mode 100755
index 0000000..aada8ee
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-arrows.min.css
@@ -0,0 +1 @@
+.tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-center .tether-content,.tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-left.tether-target-attached-top .tether-content,.tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element-attached-right.tether-target-attached-top .tether-content{margin-bottom:1pc}.tether-element.tether-theme-arrows.tether-element-attached-bottom.tether-element [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-basic.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-basic.css
new file mode 100755
index 0000000..f2b3b5c
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-basic.css
@@ -0,0 +1,21 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+  box-sizing: border-box; }
+
+.tether-element {
+  position: absolute;
+  display: none; }
+  .tether-element.tether-open {
+    display: block; }
+
+.tether-element.tether-theme-basic {
+  max-width: 100%;
+  max-height: 100%; }
+  .tether-element.tether-theme-basic .tether-content {
+    border-radius: 5px;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
+    font-family: inherit;
+    background: #fff;
+    color: inherit;
+    padding: 1em;
+    font-size: 1.1em;
+    line-height: 1.5em; }
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-basic.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-basic.min.css
new file mode 100755
index 0000000..f117c47
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether-theme-basic.min.css
@@ -0,0 +1 @@
+.tether-element,.tether-element *,.tether-element :after,.tether-element :before,.tether-element:after,.tether-element:before{box-sizing:border-box}.tether-element{position:absolute;display:none}.tether-element.tether-open{display:block}.tether-element.tether-theme-basic{max-width:100%;max-height:100%}.tether-element.tether-theme-basic .tether-content{border-radius:5px;box-shadow:0 2px 8px rgba(0,0,0,.2);font-family:inherit;background:#fff;color:inherit;padding:1em;font-size:1.1em;line-h [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether.css
new file mode 100755
index 0000000..fc30f56
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether.css
@@ -0,0 +1,8 @@
+.tether-element, .tether-element:after, .tether-element:before, .tether-element *, .tether-element *:after, .tether-element *:before {
+  box-sizing: border-box; }
+
+.tether-element {
+  position: absolute;
+  display: none; }
+  .tether-element.tether-open {
+    display: block; }
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether.min.css b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether.min.css
new file mode 100755
index 0000000..328251c
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/css/tether.min.css
@@ -0,0 +1 @@
+.tether-element,.tether-element *,.tether-element :after,.tether-element :before,.tether-element:after,.tether-element:before{box-sizing:border-box}.tether-element{position:absolute;display:none}.tether-element.tether-open{display:block}
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/js/tether.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/js/tether.js
new file mode 100755
index 0000000..5d47dbe
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/js/tether.js
@@ -0,0 +1,1715 @@
+/*! tether 1.1.0 */
+
+(function(root, factory) {
+  if (typeof define === 'function' && define.amd) {
+    define(factory);
+  } else if (typeof exports === 'object') {
+    module.exports = factory(require, exports, module);
+  } else {
+    root.Tether = factory();
+  }
+}(this, function(require, exports, module) {
+
+'use strict';
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps [...]
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
+
+var TetherBase = undefined;
+if (typeof TetherBase === 'undefined') {
+  TetherBase = { modules: [] };
+}
+
+function getScrollParent(el) {
+  var _getComputedStyle = getComputedStyle(el);
+
+  var position = _getComputedStyle.position;
+
+  if (position === 'fixed') {
+    return el;
+  }
+
+  var parent = el;
+  while (parent = parent.parentNode) {
+    var style = undefined;
+    try {
+      style = getComputedStyle(parent);
+    } catch (err) {}
+
+    if (typeof style === 'undefined' || style === null) {
+      return parent;
+    }
+
+    var _style = style;
+    var overflow = _style.overflow;
+    var overflowX = _style.overflowX;
+    var overflowY = _style.overflowY;
+
+    if (/(auto|scroll)/.test(overflow + overflowY + overflowX)) {
+      if (position !== 'absolute' || ['relative', 'absolute', 'fixed'].indexOf(style.position) >= 0) {
+        return parent;
+      }
+    }
+  }
+
+  return document.body;
+}
+
+var uniqueId = (function () {
+  var id = 0;
+  return function () {
+    return ++id;
+  };
+})();
+
+var zeroPosCache = {};
+var getOrigin = function getOrigin(doc) {
+  // getBoundingClientRect is unfortunately too accurate.  It introduces a pixel or two of
+  // jitter as the user scrolls that messes with our ability to detect if two positions
+  // are equivilant or not.  We place an element at the top left of the page that will
+  // get the same jitter, so we can cancel the two out.
+  var node = doc._tetherZeroElement;
+  if (typeof node === 'undefined') {
+    node = doc.createElement('div');
+    node.setAttribute('data-tether-id', uniqueId());
+    extend(node.style, {
+      top: 0,
+      left: 0,
+      position: 'absolute'
+    });
+
+    doc.body.appendChild(node);
+
+    doc._tetherZeroElement = node;
+  }
+
+  var id = node.getAttribute('data-tether-id');
+  if (typeof zeroPosCache[id] === 'undefined') {
+    zeroPosCache[id] = {};
+
+    var rect = node.getBoundingClientRect();
+    for (var k in rect) {
+      // Can't use extend, as on IE9, elements don't resolve to be hasOwnProperty
+      zeroPosCache[id][k] = rect[k];
+    }
+
+    // Clear the cache when this position call is done
+    defer(function () {
+      delete zeroPosCache[id];
+    });
+  }
+
+  return zeroPosCache[id];
+};
+
+function getBounds(el) {
+  var doc = undefined;
+  if (el === document) {
+    doc = document;
+    el = document.documentElement;
+  } else {
+    doc = el.ownerDocument;
+  }
+
+  var docEl = doc.documentElement;
+
+  var box = {};
+  // The original object returned by getBoundingClientRect is immutable, so we clone it
+  // We can't use extend because the properties are not considered part of the object by hasOwnProperty in IE9
+  var rect = el.getBoundingClientRect();
+  for (var k in rect) {
+    box[k] = rect[k];
+  }
+
+  var origin = getOrigin(doc);
+
+  box.top -= origin.top;
+  box.left -= origin.left;
+
+  if (typeof box.width === 'undefined') {
+    box.width = document.body.scrollWidth - box.left - box.right;
+  }
+  if (typeof box.height === 'undefined') {
+    box.height = document.body.scrollHeight - box.top - box.bottom;
+  }
+
+  box.top = box.top - docEl.clientTop;
+  box.left = box.left - docEl.clientLeft;
+  box.right = doc.body.clientWidth - box.width - box.left;
+  box.bottom = doc.body.clientHeight - box.height - box.top;
+
+  return box;
+}
+
+function getOffsetParent(el) {
+  return el.offsetParent || document.documentElement;
+}
+
+function getScrollBarSize() {
+  var inner = document.createElement('div');
+  inner.style.width = '100%';
+  inner.style.height = '200px';
+
+  var outer = document.createElement('div');
+  extend(outer.style, {
+    position: 'absolute',
+    top: 0,
+    left: 0,
+    pointerEvents: 'none',
+    visibility: 'hidden',
+    width: '200px',
+    height: '150px',
+    overflow: 'hidden'
+  });
+
+  outer.appendChild(inner);
+
+  document.body.appendChild(outer);
+
+  var widthContained = inner.offsetWidth;
+  outer.style.overflow = 'scroll';
+  var widthScroll = inner.offsetWidth;
+
+  if (widthContained === widthScroll) {
+    widthScroll = outer.clientWidth;
+  }
+
+  document.body.removeChild(outer);
+
+  var width = widthContained - widthScroll;
+
+  return { width: width, height: width };
+}
+
+function extend() {
+  var out = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
+
+  var args = [];
+
+  Array.prototype.push.apply(args, arguments);
+
+  args.slice(1).forEach(function (obj) {
+    if (obj) {
+      for (var key in obj) {
+        if (({}).hasOwnProperty.call(obj, key)) {
+          out[key] = obj[key];
+        }
+      }
+    }
+  });
+
+  return out;
+}
+
+function removeClass(el, name) {
+  if (typeof el.classList !== 'undefined') {
+    name.split(' ').forEach(function (cls) {
+      if (cls.trim()) {
+        el.classList.remove(cls);
+      }
+    });
+  } else {
+    var regex = new RegExp('(^| )' + name.split(' ').join('|') + '( |$)', 'gi');
+    var className = getClassName(el).replace(regex, ' ');
+    setClassName(el, className);
+  }
+}
+
+function addClass(el, name) {
+  if (typeof el.classList !== 'undefined') {
+    name.split(' ').forEach(function (cls) {
+      if (cls.trim()) {
+        el.classList.add(cls);
+      }
+    });
+  } else {
+    removeClass(el, name);
+    var cls = getClassName(el) + (' ' + name);
+    setClassName(el, cls);
+  }
+}
+
+function hasClass(el, name) {
+  if (typeof el.classList !== 'undefined') {
+    return el.classList.contains(name);
+  }
+  var className = getClassName(el);
+  return new RegExp('(^| )' + name + '( |$)', 'gi').test(className);
+}
+
+function getClassName(el) {
+  if (el.className instanceof SVGAnimatedString) {
+    return el.className.baseVal;
+  }
+  return el.className;
+}
+
+function setClassName(el, className) {
+  el.setAttribute('class', className);
+}
+
+function updateClasses(el, add, all) {
+  // Of the set of 'all' classes, we need the 'add' classes, and only the
+  // 'add' classes to be set.
+  all.forEach(function (cls) {
+    if (add.indexOf(cls) === -1 && hasClass(el, cls)) {
+      removeClass(el, cls);
+    }
+  });
+
+  add.forEach(function (cls) {
+    if (!hasClass(el, cls)) {
+      addClass(el, cls);
+    }
+  });
+}
+
+var deferred = [];
+
+var defer = function defer(fn) {
+  deferred.push(fn);
+};
+
+var flush = function flush() {
+  var fn = undefined;
+  while (fn = deferred.pop()) {
+    fn();
+  }
+};
+
+var Evented = (function () {
+  function Evented() {
+    _classCallCheck(this, Evented);
+  }
+
+  _createClass(Evented, [{
+    key: 'on',
+    value: function on(event, handler, ctx) {
+      var once = arguments.length <= 3 || arguments[3] === undefined ? false : arguments[3];
+
+      if (typeof this.bindings === 'undefined') {
+        this.bindings = {};
+      }
+      if (typeof this.bindings[event] === 'undefined') {
+        this.bindings[event] = [];
+      }
+      this.bindings[event].push({ handler: handler, ctx: ctx, once: once });
+    }
+  }, {
+    key: 'once',
+    value: function once(event, handler, ctx) {
+      this.on(event, handler, ctx, true);
+    }
+  }, {
+    key: 'off',
+    value: function off(event, handler) {
+      if (typeof this.bindings !== 'undefined' && typeof this.bindings[event] !== 'undefined') {
+        return;
+      }
+
+      if (typeof handler === 'undefined') {
+        delete this.bindings[event];
+      } else {
+        var i = 0;
+        while (i < this.bindings[event].length) {
+          if (this.bindings[event][i].handler === handler) {
+            this.bindings[event].splice(i, 1);
+          } else {
+            ++i;
+          }
+        }
+      }
+    }
+  }, {
+    key: 'trigger',
+    value: function trigger(event) {
+      if (typeof this.bindings !== 'undefined' && this.bindings[event]) {
+        var i = 0;
+
+        for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+          args[_key - 1] = arguments[_key];
+        }
+
+        while (i < this.bindings[event].length) {
+          var _bindings$event$i = this.bindings[event][i];
+          var handler = _bindings$event$i.handler;
+          var ctx = _bindings$event$i.ctx;
+          var once = _bindings$event$i.once;
+
+          var context = ctx;
+          if (typeof context === 'undefined') {
+            context = this;
+          }
+
+          handler.apply(context, args);
+
+          if (once) {
+            this.bindings[event].splice(i, 1);
+          } else {
+            ++i;
+          }
+        }
+      }
+    }
+  }]);
+
+  return Evented;
+})();
+
+TetherBase.Utils = {
+  getScrollParent: getScrollParent,
+  getBounds: getBounds,
+  getOffsetParent: getOffsetParent,
+  extend: extend,
+  addClass: addClass,
+  removeClass: removeClass,
+  hasClass: hasClass,
+  updateClasses: updateClasses,
+  defer: defer,
+  flush: flush,
+  uniqueId: uniqueId,
+  Evented: Evented,
+  getScrollBarSize: getScrollBarSize
+};
+/* globals TetherBase, performance */
+
+'use strict';
+
+var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return ar [...]
+
+var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps [...]
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } }
+
+if (typeof TetherBase === 'undefined') {
+  throw new Error('You must include the utils.js file before tether.js');
+}
+
+var _TetherBase$Utils = TetherBase.Utils;
+var getScrollParent = _TetherBase$Utils.getScrollParent;
+var getBounds = _TetherBase$Utils.getBounds;
+var getOffsetParent = _TetherBase$Utils.getOffsetParent;
+var extend = _TetherBase$Utils.extend;
+var addClass = _TetherBase$Utils.addClass;
+var removeClass = _TetherBase$Utils.removeClass;
+var updateClasses = _TetherBase$Utils.updateClasses;
+var defer = _TetherBase$Utils.defer;
+var flush = _TetherBase$Utils.flush;
+var getScrollBarSize = _TetherBase$Utils.getScrollBarSize;
+
+function within(a, b) {
+  var diff = arguments.length <= 2 || arguments[2] === undefined ? 1 : arguments[2];
+
+  return a + diff >= b && b >= a - diff;
+}
+
+var transformKey = (function () {
+  if (typeof document === 'undefined') {
+    return '';
+  }
+  var el = document.createElement('div');
+
+  var transforms = ['transform', 'webkitTransform', 'OTransform', 'MozTransform', 'msTransform'];
+  for (var i = 0; i < transforms.length; ++i) {
+    var key = transforms[i];
+    if (el.style[key] !== undefined) {
+      return key;
+    }
+  }
+})();
+
+var tethers = [];
+
+var position = function position() {
+  tethers.forEach(function (tether) {
+    tether.position(false);
+  });
+  flush();
+};
+
+function now() {
+  if (typeof performance !== 'undefined' && typeof performance.now !== 'undefined') {
+    return performance.now();
+  }
+  return +new Date();
+}
+
+(function () {
+  var lastCall = null;
+  var lastDuration = null;
+  var pendingTimeout = null;
+
+  var tick = function tick() {
+    if (typeof lastDuration !== 'undefined' && lastDuration > 16) {
+      // We voluntarily throttle ourselves if we can't manage 60fps
+      lastDuration = Math.min(lastDuration - 16, 250);
+
+      // Just in case this is the last event, remember to position just once more
+      pendingTimeout = setTimeout(tick, 250);
+      return;
+    }
+
+    if (typeof lastCall !== 'undefined' && now() - lastCall < 10) {
+      // Some browsers call events a little too frequently, refuse to run more than is reasonable
+      return;
+    }
+
+    if (typeof pendingTimeout !== 'undefined') {
+      clearTimeout(pendingTimeout);
+      pendingTimeout = null;
+    }
+
+    lastCall = now();
+    position();
+    lastDuration = now() - lastCall;
+  };
+
+  if (typeof window !== 'undefined') {
+    ['resize', 'scroll', 'touchmove'].forEach(function (event) {
+      window.addEventListener(event, tick);
+    });
+  }
+})();
+
+var MIRROR_LR = {
+  center: 'center',
+  left: 'right',
+  right: 'left'
+};
+
+var MIRROR_TB = {
+  middle: 'middle',
+  top: 'bottom',
+  bottom: 'top'
+};
+
+var OFFSET_MAP = {
+  top: 0,
+  left: 0,
+  middle: '50%',
+  center: '50%',
+  bottom: '100%',
+  right: '100%'
+};
+
+var autoToFixedAttachment = function autoToFixedAttachment(attachment, relativeToAttachment) {
+  var left = attachment.left;
+  var top = attachment.top;
+
+  if (left === 'auto') {
+    left = MIRROR_LR[relativeToAttachment.left];
+  }
+
+  if (top === 'auto') {
+    top = MIRROR_TB[relativeToAttachment.top];
+  }
+
+  return { left: left, top: top };
+};
+
+var attachmentToOffset = function attachmentToOffset(attachment) {
+  var left = attachment.left;
+  var top = attachment.top;
+
+  if (typeof OFFSET_MAP[attachment.left] !== 'undefined') {
+    left = OFFSET_MAP[attachment.left];
+  }
+
+  if (typeof OFFSET_MAP[attachment.top] !== 'undefined') {
+    top = OFFSET_MAP[attachment.top];
+  }
+
+  return { left: left, top: top };
+};
+
+function addOffset() {
+  var out = { top: 0, left: 0 };
+
+  for (var _len = arguments.length, offsets = Array(_len), _key = 0; _key < _len; _key++) {
+    offsets[_key] = arguments[_key];
+  }
+
+  offsets.forEach(function (_ref) {
+    var top = _ref.top;
+    var left = _ref.left;
+
+    if (typeof top === 'string') {
+      top = parseFloat(top, 10);
+    }
+    if (typeof left === 'string') {
+      left = parseFloat(left, 10);
+    }
+
+    out.top += top;
+    out.left += left;
+  });
+
+  return out;
+}
+
+function offsetToPx(offset, size) {
+  if (typeof offset.left === 'string' && offset.left.indexOf('%') !== -1) {
+    offset.left = parseFloat(offset.left, 10) / 100 * size.width;
+  }
+  if (typeof offset.top === 'string' && offset.top.indexOf('%') !== -1) {
+    offset.top = parseFloat(offset.top, 10) / 100 * size.height;
+  }
+
+  return offset;
+}
+
+var parseOffset = function parseOffset(value) {
+  var _value$split = value.split(' ');
+
+  var _value$split2 = _slicedToArray(_value$split, 2);
+
+  var top = _value$split2[0];
+  var left = _value$split2[1];
+
+  return { top: top, left: left };
+};
+var parseAttachment = parseOffset;
+
+var TetherClass = (function () {
+  function TetherClass(options) {
+    var _this = this;
+
+    _classCallCheck(this, TetherClass);
+
+    this.position = this.position.bind(this);
+
+    tethers.push(this);
+
+    this.history = [];
+
+    this.setOptions(options, false);
+
+    TetherBase.modules.forEach(function (module) {
+      if (typeof module.initialize !== 'undefined') {
+        module.initialize.call(_this);
+      }
+    });
+
+    this.position();
+  }
+
+  _createClass(TetherClass, [{
+    key: 'getClass',
+    value: function getClass() {
+      var key = arguments.length <= 0 || arguments[0] === undefined ? '' : arguments[0];
+      var classes = this.options.classes;
+
+      if (typeof classes !== 'undefined' && classes[key]) {
+        return this.options.classes[key];
+      } else if (this.options.classPrefix) {
+        return this.options.classPrefix + '-' + key;
+      } else {
+        return key;
+      }
+    }
+  }, {
+    key: 'setOptions',
+    value: function setOptions(options) {
+      var _this2 = this;
+
+      var pos = arguments.length <= 1 || arguments[1] === undefined ? true : arguments[1];
+
+      var defaults = {
+        offset: '0 0',
+        targetOffset: '0 0',
+        targetAttachment: 'auto auto',
+        classPrefix: 'tether'
+      };
+
+      this.options = extend(defaults, options);
+
+      var _options = this.options;
+      var element = _options.element;
+      var target = _options.target;
+      var targetModifier = _options.targetModifier;
+
+      this.element = element;
+      this.target = target;
+      this.targetModifier = targetModifier;
+
+      if (this.target === 'viewport') {
+        this.target = document.body;
+        this.targetModifier = 'visible';
+      } else if (this.target === 'scroll-handle') {
+        this.target = document.body;
+        this.targetModifier = 'scroll-handle';
+      }
+
+      ['element', 'target'].forEach(function (key) {
+        if (typeof _this2[key] === 'undefined') {
+          throw new Error('Tether Error: Both element and target must be defined');
+        }
+
+        if (typeof _this2[key].jquery !== 'undefined') {
+          _this2[key] = _this2[key][0];
+        } else if (typeof _this2[key] === 'string') {
+          _this2[key] = document.querySelector(_this2[key]);
+        }
+      });
+
+      addClass(this.element, this.getClass('element'));
+      if (!(this.options.addTargetClasses === false)) {
+        addClass(this.target, this.getClass('target'));
+      }
+
+      if (!this.options.attachment) {
+        throw new Error('Tether Error: You must provide an attachment');
+      }
+
+      this.targetAttachment = parseAttachment(this.options.targetAttachment);
+      this.attachment = parseAttachment(this.options.attachment);
+      this.offset = parseOffset(this.options.offset);
+      this.targetOffset = parseOffset(this.options.targetOffset);
+
+      if (typeof this.scrollParent !== 'undefined') {
+        this.disable();
+      }
+
+      if (this.targetModifier === 'scroll-handle') {
+        this.scrollParent = this.target;
+      } else {
+        this.scrollParent = getScrollParent(this.target);
+      }
+
+      if (!(this.options.enabled === false)) {
+        this.enable(pos);
+      }
+    }
+  }, {
+    key: 'getTargetBounds',
+    value: function getTargetBounds() {
+      if (typeof this.targetModifier !== 'undefined') {
+        if (this.targetModifier === 'visible') {
+          if (this.target === document.body) {
+            return { top: pageYOffset, left: pageXOffset, height: innerHeight, width: innerWidth };
+          } else {
+            var bounds = getBounds(this.target);
+
+            var out = {
+              height: bounds.height,
+              width: bounds.width,
+              top: bounds.top,
+              left: bounds.left
+            };
+
+            out.height = Math.min(out.height, bounds.height - (pageYOffset - bounds.top));
+            out.height = Math.min(out.height, bounds.height - (bounds.top + bounds.height - (pageYOffset + innerHeight)));
+            out.height = Math.min(innerHeight, out.height);
+            out.height -= 2;
+
+            out.width = Math.min(out.width, bounds.width - (pageXOffset - bounds.left));
+            out.width = Math.min(out.width, bounds.width - (bounds.left + bounds.width - (pageXOffset + innerWidth)));
+            out.width = Math.min(innerWidth, out.width);
+            out.width -= 2;
+
+            if (out.top < pageYOffset) {
+              out.top = pageYOffset;
+            }
+            if (out.left < pageXOffset) {
+              out.left = pageXOffset;
+            }
+
+            return out;
+          }
+        } else if (this.targetModifier === 'scroll-handle') {
+          var bounds = undefined;
+          var target = this.target;
+          if (target === document.body) {
+            target = document.documentElement;
+
+            bounds = {
+              left: pageXOffset,
+              top: pageYOffset,
+              height: innerHeight,
+              width: innerWidth
+            };
+          } else {
+            bounds = getBounds(target);
+          }
+
+          var style = getComputedStyle(target);
+
+          var hasBottomScroll = target.scrollWidth > target.clientWidth || [style.overflow, style.overflowX].indexOf('scroll') >= 0 || this.target !== document.body;
+
+          var scrollBottom = 0;
+          if (hasBottomScroll) {
+            scrollBottom = 15;
+          }
+
+          var height = bounds.height - parseFloat(style.borderTopWidth) - parseFloat(style.borderBottomWidth) - scrollBottom;
+
+          var out = {
+            width: 15,
+            height: height * 0.975 * (height / target.scrollHeight),
+            left: bounds.left + bounds.width - parseFloat(style.borderLeftWidth) - 15
+          };
+
+          var fitAdj = 0;
+          if (height < 408 && this.target === document.body) {
+            fitAdj = -0.00011 * Math.pow(height, 2) - 0.00727 * height + 22.58;
+          }
+
+          if (this.target !== document.body) {
+            out.height = Math.max(out.height, 24);
+          }
+
+          var scrollPercentage = this.target.scrollTop / (target.scrollHeight - height);
+          out.top = scrollPercentage * (height - out.height - fitAdj) + bounds.top + parseFloat(style.borderTopWidth);
+
+          if (this.target === document.body) {
+            out.height = Math.max(out.height, 24);
+          }
+
+          return out;
+        }
+      } else {
+        return getBounds(this.target);
+      }
+    }
+  }, {
+    key: 'clearCache',
+    value: function clearCache() {
+      this._cache = {};
+    }
+  }, {
+    key: 'cache',
+    value: function cache(k, getter) {
+      // More than one module will often need the same DOM info, so
+      // we keep a cache which is cleared on each position call
+      if (typeof this._cache === 'undefined') {
+        this._cache = {};
+      }
+
+      if (typeof this._cache[k] === 'undefined') {
+        this._cache[k] = getter.call(this);
+      }
+
+      return this._cache[k];
+    }
+  }, {
+    key: 'enable',
+    value: function enable() {
+      var pos = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
+
+      if (!(this.options.addTargetClasses === false)) {
+        addClass(this.target, this.getClass('enabled'));
+      }
+      addClass(this.element, this.getClass('enabled'));
+      this.enabled = true;
+
+      if (this.scrollParent !== document) {
+        this.scrollParent.addEventListener('scroll', this.position);
+      }
+
+      if (pos) {
+        this.position();
+      }
+    }
+  }, {
+    key: 'disable',
+    value: function disable() {
+      removeClass(this.target, this.getClass('enabled'));
+      removeClass(this.element, this.getClass('enabled'));
+      this.enabled = false;
+
+      if (typeof this.scrollParent !== 'undefined') {
+        this.scrollParent.removeEventListener('scroll', this.position);
+      }
+    }
+  }, {
+    key: 'destroy',
+    value: function destroy() {
+      var _this3 = this;
+
+      this.disable();
+
+      tethers.forEach(function (tether, i) {
+        if (tether === _this3) {
+          tethers.splice(i, 1);
+          return;
+        }
+      });
+    }
+  }, {
+    key: 'updateAttachClasses',
+    value: function updateAttachClasses(elementAttach, targetAttach) {
+      var _this4 = this;
+
+      elementAttach = elementAttach || this.attachment;
+      targetAttach = targetAttach || this.targetAttachment;
+      var sides = ['left', 'top', 'bottom', 'right', 'middle', 'center'];
+
+      if (typeof this._addAttachClasses !== 'undefined' && this._addAttachClasses.length) {
+        // updateAttachClasses can be called more than once in a position call, so
+        // we need to clean up after ourselves such that when the last defer gets
+        // ran it doesn't add any extra classes from previous calls.
+        this._addAttachClasses.splice(0, this._addAttachClasses.length);
+      }
+
+      if (typeof this._addAttachClasses === 'undefined') {
+        this._addAttachClasses = [];
+      }
+      var add = this._addAttachClasses;
+
+      if (elementAttach.top) {
+        add.push(this.getClass('element-attached') + '-' + elementAttach.top);
+      }
+      if (elementAttach.left) {
+        add.push(this.getClass('element-attached') + '-' + elementAttach.left);
+      }
+      if (targetAttach.top) {
+        add.push(this.getClass('target-attached') + '-' + targetAttach.top);
+      }
+      if (targetAttach.left) {
+        add.push(this.getClass('target-attached') + '-' + targetAttach.left);
+      }
+
+      var all = [];
+      sides.forEach(function (side) {
+        all.push(_this4.getClass('element-attached') + '-' + side);
+        all.push(_this4.getClass('target-attached') + '-' + side);
+      });
+
+      defer(function () {
+        if (!(typeof _this4._addAttachClasses !== 'undefined')) {
+          return;
+        }
+
+        updateClasses(_this4.element, _this4._addAttachClasses, all);
+        if (!(_this4.options.addTargetClasses === false)) {
+          updateClasses(_this4.target, _this4._addAttachClasses, all);
+        }
+
+        delete _this4._addAttachClasses;
+      });
+    }
+  }, {
+    key: 'position',
+    value: function position() {
+      var _this5 = this;
+
+      var flushChanges = arguments.length <= 0 || arguments[0] === undefined ? true : arguments[0];
+
+      // flushChanges commits the changes immediately, leave true unless you are positioning multiple
+      // tethers (in which case call Tether.Utils.flush yourself when you're done)
+
+      if (!this.enabled) {
+        return;
+      }
+
+      this.clearCache();
+
+      // Turn 'auto' attachments into the appropriate corner or edge
+      var targetAttachment = autoToFixedAttachment(this.targetAttachment, this.attachment);
+
+      this.updateAttachClasses(this.attachment, targetAttachment);
+
+      var elementPos = this.cache('element-bounds', function () {
+        return getBounds(_this5.element);
+      });
+
+      var width = elementPos.width;
+      var height = elementPos.height;
+
+      if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
+        var _lastSize = this.lastSize;
+
+        // We cache the height and width to make it possible to position elements that are
+        // getting hidden.
+        width = _lastSize.width;
+        height = _lastSize.height;
+      } else {
+        this.lastSize = { width: width, height: height };
+      }
+
+      var targetPos = this.cache('target-bounds', function () {
+        return _this5.getTargetBounds();
+      });
+      var targetSize = targetPos;
+
+      // Get an actual px offset from the attachment
+      var offset = offsetToPx(attachmentToOffset(this.attachment), { width: width, height: height });
+      var targetOffset = offsetToPx(attachmentToOffset(targetAttachment), targetSize);
+
+      var manualOffset = offsetToPx(this.offset, { width: width, height: height });
+      var manualTargetOffset = offsetToPx(this.targetOffset, targetSize);
+
+      // Add the manually provided offset
+      offset = addOffset(offset, manualOffset);
+      targetOffset = addOffset(targetOffset, manualTargetOffset);
+
+      // It's now our goal to make (element position + offset) == (target position + target offset)
+      var left = targetPos.left + targetOffset.left - offset.left;
+      var top = targetPos.top + targetOffset.top - offset.top;
+
+      for (var i = 0; i < TetherBase.modules.length; ++i) {
+        var _module2 = TetherBase.modules[i];
+        var ret = _module2.position.call(this, {
+          left: left,
+          top: top,
+          targetAttachment: targetAttachment,
+          targetPos: targetPos,
+          elementPos: elementPos,
+          offset: offset,
+          targetOffset: targetOffset,
+          manualOffset: manualOffset,
+          manualTargetOffset: manualTargetOffset,
+          scrollbarSize: scrollbarSize,
+          attachment: this.attachment
+        });
+
+        if (ret === false) {
+          return false;
+        } else if (typeof ret === 'undefined' || typeof ret !== 'object') {
+          continue;
+        } else {
+          top = ret.top;
+          left = ret.left;
+        }
+      }
+
+      // We describe the position three different ways to give the optimizer
+      // a chance to decide the best possible way to position the element
+      // with the fewest repaints.
+      var next = {
+        // It's position relative to the page (absolute positioning when
+        // the element is a child of the body)
+        page: {
+          top: top,
+          left: left
+        },
+
+        // It's position relative to the viewport (fixed positioning)
+        viewport: {
+          top: top - pageYOffset,
+          bottom: pageYOffset - top - height + innerHeight,
+          left: left - pageXOffset,
+          right: pageXOffset - left - width + innerWidth
+        }
+      };
+
+      var scrollbarSize = undefined;
+      if (document.body.scrollWidth > window.innerWidth) {
+        scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+        next.viewport.bottom -= scrollbarSize.height;
+      }
+
+      if (document.body.scrollHeight > window.innerHeight) {
+        scrollbarSize = this.cache('scrollbar-size', getScrollBarSize);
+        next.viewport.right -= scrollbarSize.width;
+      }
+
+      if (['', 'static'].indexOf(document.body.style.position) === -1 || ['', 'static'].indexOf(document.body.parentElement.style.position) === -1) {
+        // Absolute positioning in the body will be relative to the page, not the 'initial containing block'
+        next.page.bottom = document.body.scrollHeight - top - height;
+        next.page.right = document.body.scrollWidth - left - width;
+      }
+
+      if (typeof this.options.optimizations !== 'undefined' && this.options.optimizations.moveElement !== false && !(typeof this.targetModifier !== 'undefined')) {
+        (function () {
+          var offsetParent = _this5.cache('target-offsetparent', function () {
+            return getOffsetParent(_this5.target);
+          });
+          var offsetPosition = _this5.cache('target-offsetparent-bounds', function () {
+            return getBounds(offsetParent);
+          });
+          var offsetParentStyle = getComputedStyle(offsetParent);
+          var offsetParentSize = offsetPosition;
+
+          var offsetBorder = {};
+          ['Top', 'Left', 'Bottom', 'Right'].forEach(function (side) {
+            offsetBorder[side.toLowerCase()] = parseFloat(offsetParentStyle['border' + side + 'Width']);
+          });
+
+          offsetPosition.right = document.body.scrollWidth - offsetPosition.left - offsetParentSize.width + offsetBorder.right;
+          offsetPosition.bottom = document.body.scrollHeight - offsetPosition.top - offsetParentSize.height + offsetBorder.bottom;
+
+          if (next.page.top >= offsetPosition.top + offsetBorder.top && next.page.bottom >= offsetPosition.bottom) {
+            if (next.page.left >= offsetPosition.left + offsetBorder.left && next.page.right >= offsetPosition.right) {
+              // We're within the visible part of the target's scroll parent
+              var scrollTop = offsetParent.scrollTop;
+              var scrollLeft = offsetParent.scrollLeft;
+
+              // It's position relative to the target's offset parent (absolute positioning when
+              // the element is moved to be a child of the target's offset parent).
+              next.offset = {
+                top: next.page.top - offsetPosition.top + scrollTop - offsetBorder.top,
+                left: next.page.left - offsetPosition.left + scrollLeft - offsetBorder.left
+              };
+            }
+          }
+        })();
+      }
+
+      // We could also travel up the DOM and try each containing context, rather than only
+      // looking at the body, but we're gonna get diminishing returns.
+
+      this.move(next);
+
+      this.history.unshift(next);
+
+      if (this.history.length > 3) {
+        this.history.pop();
+      }
+
+      if (flushChanges) {
+        flush();
+      }
+
+      return true;
+    }
+
+    // THE ISSUE
+  }, {
+    key: 'move',
+    value: function move(pos) {
+      var _this6 = this;
+
+      if (!(typeof this.element.parentNode !== 'undefined')) {
+        return;
+      }
+
+      var same = {};
+
+      for (var type in pos) {
+        same[type] = {};
+
+        for (var key in pos[type]) {
+          var found = false;
+
+          for (var i = 0; i < this.history.length; ++i) {
+            var point = this.history[i];
+            if (typeof point[type] !== 'undefined' && !within(point[type][key], pos[type][key])) {
+              found = true;
+              break;
+            }
+          }
+
+          if (!found) {
+            same[type][key] = true;
+          }
+        }
+      }
+
+      var css = { top: '', left: '', right: '', bottom: '' };
+
+      var transcribe = function transcribe(_same, _pos) {
+        var hasOptimizations = typeof _this6.options.optimizations !== 'undefined';
+        var gpu = hasOptimizations ? _this6.options.optimizations.gpu : null;
+        if (gpu !== false) {
+          var yPos = undefined,
+              xPos = undefined;
+          if (_same.top) {
+            css.top = 0;
+            yPos = _pos.top;
+          } else {
+            css.bottom = 0;
+            yPos = -_pos.bottom;
+          }
+
+          if (_same.left) {
+            css.left = 0;
+            xPos = _pos.left;
+          } else {
+            css.right = 0;
+            xPos = -_pos.right;
+          }
+
+          css[transformKey] = 'translateX(' + Math.round(xPos) + 'px) translateY(' + Math.round(yPos) + 'px)';
+
+          if (transformKey !== 'msTransform') {
+            // The Z transform will keep this in the GPU (faster, and prevents artifacts),
+            // but IE9 doesn't support 3d transforms and will choke.
+            css[transformKey] += " translateZ(0)";
+          }
+        } else {
+          if (_same.top) {
+            css.top = _pos.top + 'px';
+          } else {
+            css.bottom = _pos.bottom + 'px';
+          }
+
+          if (_same.left) {
+            css.left = _pos.left + 'px';
+          } else {
+            css.right = _pos.right + 'px';
+          }
+        }
+      };
+
+      var moved = false;
+      if ((same.page.top || same.page.bottom) && (same.page.left || same.page.right)) {
+        css.position = 'absolute';
+        transcribe(same.page, pos.page);
+      } else if ((same.viewport.top || same.viewport.bottom) && (same.viewport.left || same.viewport.right)) {
+        css.position = 'fixed';
+        transcribe(same.viewport, pos.viewport);
+      } else if (typeof same.offset !== 'undefined' && same.offset.top && same.offset.left) {
+        (function () {
+          css.position = 'absolute';
+          var offsetParent = _this6.cache('target-offsetparent', function () {
+            return getOffsetParent(_this6.target);
+          });
+
+          if (getOffsetParent(_this6.element) !== offsetParent) {
+            defer(function () {
+              _this6.element.parentNode.removeChild(_this6.element);
+              offsetParent.appendChild(_this6.element);
+            });
+          }
+
+          transcribe(same.offset, pos.offset);
+          moved = true;
+        })();
+      } else {
+        css.position = 'absolute';
+        transcribe({ top: true, left: true }, pos.page);
+      }
+
+      if (!moved) {
+        var offsetParentIsBody = true;
+        var currentNode = this.element.parentNode;
+        while (currentNode && currentNode.tagName !== 'BODY') {
+          if (getComputedStyle(currentNode).position !== 'static') {
+            offsetParentIsBody = false;
+            break;
+          }
+
+          currentNode = currentNode.parentNode;
+        }
+
+        if (!offsetParentIsBody) {
+          this.element.parentNode.removeChild(this.element);
+          document.body.appendChild(this.element);
+        }
+      }
+
+      // Any css change will trigger a repaint, so let's avoid one if nothing changed
+      var writeCSS = {};
+      var write = false;
+      for (var key in css) {
+        var val = css[key];
+        var elVal = this.element.style[key];
+
+        if (elVal !== '' && val !== '' && ['top', 'left', 'bottom', 'right'].indexOf(key) >= 0) {
+          elVal = parseFloat(elVal);
+          val = parseFloat(val);
+        }
+
+        if (elVal !== val) {
+          write = true;
+          writeCSS[key] = val;
+        }
+      }
+
+      if (write) {
+        defer(function () {
+          extend(_this6.element.style, writeCSS);
+        });
+      }
+    }
+  }]);
+
+  return TetherClass;
+})();
+
+TetherClass.modules = [];
+
+TetherBase.position = position;
+
+var Tether = extend(TetherClass, TetherBase);
+/* globals TetherBase */
+
+'use strict';
+
+var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return ar [...]
+
+var _TetherBase$Utils = TetherBase.Utils;
+var getBounds = _TetherBase$Utils.getBounds;
+var extend = _TetherBase$Utils.extend;
+var updateClasses = _TetherBase$Utils.updateClasses;
+var defer = _TetherBase$Utils.defer;
+
+var BOUNDS_FORMAT = ['left', 'top', 'right', 'bottom'];
+
+function getBoundingRect(tether, to) {
+  if (to === 'scrollParent') {
+    to = tether.scrollParent;
+  } else if (to === 'window') {
+    to = [pageXOffset, pageYOffset, innerWidth + pageXOffset, innerHeight + pageYOffset];
+  }
+
+  if (to === document) {
+    to = to.documentElement;
+  }
+
+  if (typeof to.nodeType !== 'undefined') {
+    (function () {
+      var size = getBounds(to);
+      var pos = size;
+      var style = getComputedStyle(to);
+
+      to = [pos.left, pos.top, size.width + pos.left, size.height + pos.top];
+
+      BOUNDS_FORMAT.forEach(function (side, i) {
+        side = side[0].toUpperCase() + side.substr(1);
+        if (side === 'Top' || side === 'Left') {
+          to[i] += parseFloat(style['border' + side + 'Width']);
+        } else {
+          to[i] -= parseFloat(style['border' + side + 'Width']);
+        }
+      });
+    })();
+  }
+
+  return to;
+}
+
+TetherBase.modules.push({
+  position: function position(_ref) {
+    var _this = this;
+
+    var top = _ref.top;
+    var left = _ref.left;
+    var targetAttachment = _ref.targetAttachment;
+
+    if (!this.options.constraints) {
+      return true;
+    }
+
+    var _cache = this.cache('element-bounds', function () {
+      return getBounds(_this.element);
+    });
+
+    var height = _cache.height;
+    var width = _cache.width;
+
+    if (width === 0 && height === 0 && typeof this.lastSize !== 'undefined') {
+      var _lastSize = this.lastSize;
+
+      // Handle the item getting hidden as a result of our positioning without glitching
+      // the classes in and out
+      width = _lastSize.width;
+      height = _lastSize.height;
+    }
+
+    var targetSize = this.cache('target-bounds', function () {
+      return _this.getTargetBounds();
+    });
+
+    var targetHeight = targetSize.height;
+    var targetWidth = targetSize.width;
+
+    var allClasses = [this.getClass('pinned'), this.getClass('out-of-bounds')];
+
+    this.options.constraints.forEach(function (constraint) {
+      var outOfBoundsClass = constraint.outOfBoundsClass;
+      var pinnedClass = constraint.pinnedClass;
+
+      if (outOfBoundsClass) {
+        allClasses.push(outOfBoundsClass);
+      }
+      if (pinnedClass) {
+        allClasses.push(pinnedClass);
+      }
+    });
+
+    allClasses.forEach(function (cls) {
+      ['left', 'top', 'right', 'bottom'].forEach(function (side) {
+        allClasses.push(cls + '-' + side);
+      });
+    });
+
+    var addClasses = [];
+
+    var tAttachment = extend({}, targetAttachment);
+    var eAttachment = extend({}, this.attachment);
+
+    this.options.constraints.forEach(function (constraint) {
+      var to = constraint.to;
+      var attachment = constraint.attachment;
+      var pin = constraint.pin;
+
+      if (typeof attachment === 'undefined') {
+        attachment = '';
+      }
+
+      var changeAttachX = undefined,
+          changeAttachY = undefined;
+      if (attachment.indexOf(' ') >= 0) {
+        var _attachment$split = attachment.split(' ');
+
+        var _attachment$split2 = _slicedToArray(_attachment$split, 2);
+
+        changeAttachY = _attachment$split2[0];
+        changeAttachX = _attachment$split2[1];
+      } else {
+        changeAttachX = changeAttachY = attachment;
+      }
+
+      var bounds = getBoundingRect(_this, to);
+
+      if (changeAttachY === 'target' || changeAttachY === 'both') {
+        if (top < bounds[1] && tAttachment.top === 'top') {
+          top += targetHeight;
+          tAttachment.top = 'bottom';
+        }
+
+        if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+          top -= targetHeight;
+          tAttachment.top = 'top';
+        }
+      }
+
+      if (changeAttachY === 'together') {
+        if (top < bounds[1] && tAttachment.top === 'top') {
+          if (eAttachment.top === 'bottom') {
+            top += targetHeight;
+            tAttachment.top = 'bottom';
+
+            top += height;
+            eAttachment.top = 'top';
+          } else if (eAttachment.top === 'top') {
+            top += targetHeight;
+            tAttachment.top = 'bottom';
+
+            top -= height;
+            eAttachment.top = 'bottom';
+          }
+        }
+
+        if (top + height > bounds[3] && tAttachment.top === 'bottom') {
+          if (eAttachment.top === 'top') {
+            top -= targetHeight;
+            tAttachment.top = 'top';
+
+            top -= height;
+            eAttachment.top = 'bottom';
+          } else if (eAttachment.top === 'bottom') {
+            top -= targetHeight;
+            tAttachment.top = 'top';
+
+            top += height;
+            eAttachment.top = 'top';
+          }
+        }
+
+        if (tAttachment.top === 'middle') {
+          if (top + height > bounds[3] && eAttachment.top === 'top') {
+            top -= height;
+            eAttachment.top = 'bottom';
+          } else if (top < bounds[1] && eAttachment.top === 'bottom') {
+            top += height;
+            eAttachment.top = 'top';
+          }
+        }
+      }
+
+      if (changeAttachX === 'target' || changeAttachX === 'both') {
+        if (left < bounds[0] && tAttachment.left === 'left') {
+          left += targetWidth;
+          tAttachment.left = 'right';
+        }
+
+        if (left + width > bounds[2] && tAttachment.left === 'right') {
+          left -= targetWidth;
+          tAttachment.left = 'left';
+        }
+      }
+
+      if (changeAttachX === 'together') {
+        if (left < bounds[0] && tAttachment.left === 'left') {
+          if (eAttachment.left === 'right') {
+            left += targetWidth;
+            tAttachment.left = 'right';
+
+            left += width;
+            eAttachment.left = 'left';
+          } else if (eAttachment.left === 'left') {
+            left += targetWidth;
+            tAttachment.left = 'right';
+
+            left -= width;
+            eAttachment.left = 'right';
+          }
+        } else if (left + width > bounds[2] && tAttachment.left === 'right') {
+          if (eAttachment.left === 'left') {
+            left -= targetWidth;
+            tAttachment.left = 'left';
+
+            left -= width;
+            eAttachment.left = 'right';
+          } else if (eAttachment.left === 'right') {
+            left -= targetWidth;
+            tAttachment.left = 'left';
+
+            left += width;
+            eAttachment.left = 'left';
+          }
+        } else if (tAttachment.left === 'center') {
+          if (left + width > bounds[2] && eAttachment.left === 'left') {
+            left -= width;
+            eAttachment.left = 'right';
+          } else if (left < bounds[0] && eAttachment.left === 'right') {
+            left += width;
+            eAttachment.left = 'left';
+          }
+        }
+      }
+
+      if (changeAttachY === 'element' || changeAttachY === 'both') {
+        if (top < bounds[1] && eAttachment.top === 'bottom') {
+          top += height;
+          eAttachment.top = 'top';
+        }
+
+        if (top + height > bounds[3] && eAttachment.top === 'top') {
+          top -= height;
+          eAttachment.top = 'bottom';
+        }
+      }
+
+      if (changeAttachX === 'element' || changeAttachX === 'both') {
+        if (left < bounds[0] && eAttachment.left === 'right') {
+          left += width;
+          eAttachment.left = 'left';
+        }
+
+        if (left + width > bounds[2] && eAttachment.left === 'left') {
+          left -= width;
+          eAttachment.left = 'right';
+        }
+      }
+
+      if (typeof pin === 'string') {
+        pin = pin.split(',').map(function (p) {
+          return p.trim();
+        });
+      } else if (pin === true) {
+        pin = ['top', 'left', 'right', 'bottom'];
+      }
+
+      pin = pin || [];
+
+      var pinned = [];
+      var oob = [];
+
+      if (top < bounds[1]) {
+        if (pin.indexOf('top') >= 0) {
+          top = bounds[1];
+          pinned.push('top');
+        } else {
+          oob.push('top');
+        }
+      }
+
+      if (top + height > bounds[3]) {
+        if (pin.indexOf('bottom') >= 0) {
+          top = bounds[3] - height;
+          pinned.push('bottom');
+        } else {
+          oob.push('bottom');
+        }
+      }
+
+      if (left < bounds[0]) {
+        if (pin.indexOf('left') >= 0) {
+          left = bounds[0];
+          pinned.push('left');
+        } else {
+          oob.push('left');
+        }
+      }
+
+      if (left + width > bounds[2]) {
+        if (pin.indexOf('right') >= 0) {
+          left = bounds[2] - width;
+          pinned.push('right');
+        } else {
+          oob.push('right');
+        }
+      }
+
+      if (pinned.length) {
+        (function () {
+          var pinnedClass = undefined;
+          if (typeof _this.options.pinnedClass !== 'undefined') {
+            pinnedClass = _this.options.pinnedClass;
+          } else {
+            pinnedClass = _this.getClass('pinned');
+          }
+
+          addClasses.push(pinnedClass);
+          pinned.forEach(function (side) {
+            addClasses.push(pinnedClass + '-' + side);
+          });
+        })();
+      }
+
+      if (oob.length) {
+        (function () {
+          var oobClass = undefined;
+          if (typeof _this.options.outOfBoundsClass !== 'undefined') {
+            oobClass = _this.options.outOfBoundsClass;
+          } else {
+            oobClass = _this.getClass('out-of-bounds');
+          }
+
+          addClasses.push(oobClass);
+          oob.forEach(function (side) {
+            addClasses.push(oobClass + '-' + side);
+          });
+        })();
+      }
+
+      if (pinned.indexOf('left') >= 0 || pinned.indexOf('right') >= 0) {
+        eAttachment.left = tAttachment.left = false;
+      }
+      if (pinned.indexOf('top') >= 0 || pinned.indexOf('bottom') >= 0) {
+        eAttachment.top = tAttachment.top = false;
+      }
+
+      if (tAttachment.top !== targetAttachment.top || tAttachment.left !== targetAttachment.left || eAttachment.top !== _this.attachment.top || eAttachment.left !== _this.attachment.left) {
+        _this.updateAttachClasses(eAttachment, tAttachment);
+      }
+    });
+
+    defer(function () {
+      if (!(_this.options.addTargetClasses === false)) {
+        updateClasses(_this.target, addClasses, allClasses);
+      }
+      updateClasses(_this.element, addClasses, allClasses);
+    });
+
+    return { top: top, left: left };
+  }
+});
+/* globals TetherBase */
+
+'use strict';
+
+var _TetherBase$Utils = TetherBase.Utils;
+var getBounds = _TetherBase$Utils.getBounds;
+var updateClasses = _TetherBase$Utils.updateClasses;
+var defer = _TetherBase$Utils.defer;
+
+TetherBase.modules.push({
+  position: function position(_ref) {
+    var _this = this;
+
+    var top = _ref.top;
+    var left = _ref.left;
+
+    var _cache = this.cache('element-bounds', function () {
+      return getBounds(_this.element);
+    });
+
+    var height = _cache.height;
+    var width = _cache.width;
+
+    var targetPos = this.getTargetBounds();
+
+    var bottom = top + height;
+    var right = left + width;
+
+    var abutted = [];
+    if (top <= targetPos.bottom && bottom >= targetPos.top) {
+      ['left', 'right'].forEach(function (side) {
+        var targetPosSide = targetPos[side];
+        if (targetPosSide === left || targetPosSide === right) {
+          abutted.push(side);
+        }
+      });
+    }
+
+    if (left <= targetPos.right && right >= targetPos.left) {
+      ['top', 'bottom'].forEach(function (side) {
+        var targetPosSide = targetPos[side];
+        if (targetPosSide === top || targetPosSide === bottom) {
+          abutted.push(side);
+        }
+      });
+    }
+
+    var allClasses = [];
+    var addClasses = [];
+
+    var sides = ['left', 'top', 'right', 'bottom'];
+    allClasses.push(this.getClass('abutted'));
+    sides.forEach(function (side) {
+      allClasses.push(_this.getClass('abutted') + '-' + side);
+    });
+
+    if (abutted.length) {
+      addClasses.push(this.getClass('abutted'));
+    }
+
+    abutted.forEach(function (side) {
+      addClasses.push(_this.getClass('abutted') + '-' + side);
+    });
+
+    defer(function () {
+      if (!(_this.options.addTargetClasses === false)) {
+        updateClasses(_this.target, addClasses, allClasses);
+      }
+      updateClasses(_this.element, addClasses, allClasses);
+    });
+
+    return true;
+  }
+});
+/* globals TetherBase */
+
+'use strict';
+
+var _slicedToArray = (function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i['return']) _i['return'](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return ar [...]
+
+TetherBase.modules.push({
+  position: function position(_ref) {
+    var top = _ref.top;
+    var left = _ref.left;
+
+    if (!this.options.shift) {
+      return;
+    }
+
+    var shift = this.options.shift;
+    if (typeof this.options.shift === 'function') {
+      shift = this.options.shift.call(this, { top: top, left: left });
+    }
+
+    var shiftTop = undefined,
+        shiftLeft = undefined;
+    if (typeof shift === 'string') {
+      shift = shift.split(' ');
+      shift[1] = shift[1] || shift[0];
+
+      var _shift = shift;
+
+      var _shift2 = _slicedToArray(_shift, 2);
+
+      shiftTop = _shift2[0];
+      shiftLeft = _shift2[1];
+
+      shiftTop = parseFloat(shiftTop, 10);
+      shiftLeft = parseFloat(shiftLeft, 10);
+    } else {
+      shiftTop = shift.top;
+      shiftLeft = shift.left;
+    }
+
+    top += shiftTop;
+    left += shiftLeft;
+
+    return { top: top, left: left };
+  }
+});
+return Tether;
+
+}));
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/js/tether.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/js/tether.min.js
new file mode 100755
index 0000000..fceb25c
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/tether/1.1.1/js/tether.min.js
@@ -0,0 +1 @@
+!function(t,e){"function"==typeof define&&define.amd?define(e):"object"==typeof exports?module.exports=e(require,exports,module):t.Tether=e()}(this,function(t,e,o){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function n(t){var e=getComputedStyle(t),o=e.position;if("fixed"===o)return t;for(var i=t;i=i.parentNode;){var n=void 0;try{n=getComputedStyle(i)}catch(r){}if("undefined"==typeof n||null===n)return i;var s=n,a=s.overflow,f [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.js
new file mode 100644
index 0000000..c0fb6c2
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.js
@@ -0,0 +1,1540 @@
+/*!
+ * typeahead.js 0.11.1-patched-with-1212 (including patch https://github.com/twitter/typeahead.js/pull/1212)
+ * https://github.com/twitter/typeahead.js
+ * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
+ */
+
+(function(root, factory) {
+  if (typeof define === "function" && define.amd) {
+    define("typeahead.js", [ "jquery" ], function(a0) {
+      return factory(a0);
+    });
+  } else if (typeof exports === "object") {
+    module.exports = factory(require("jquery"));
+  } else {
+    factory(jQuery);
+  }
+})(this, function($) {
+  var _ = function() {
+    "use strict";
+    return {
+      isMsie: function() {
+        return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
+      },
+      isBlankString: function(str) {
+        return !str || /^\s*$/.test(str);
+      },
+      escapeRegExChars: function(str) {
+        return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
+      },
+      isString: function(obj) {
+        return typeof obj === "string";
+      },
+      isNumber: function(obj) {
+        return typeof obj === "number";
+      },
+      isArray: $.isArray,
+      isFunction: $.isFunction,
+      isObject: $.isPlainObject,
+      isUndefined: function(obj) {
+        return typeof obj === "undefined";
+      },
+      isElement: function(obj) {
+        return !!(obj && obj.nodeType === 1);
+      },
+      isJQuery: function(obj) {
+        return obj instanceof $;
+      },
+      toStr: function toStr(s) {
+        return _.isUndefined(s) || s === null ? "" : s + "";
+      },
+      bind: $.proxy,
+      each: function(collection, cb) {
+        $.each(collection, reverseArgs);
+        function reverseArgs(index, value) {
+          return cb(value, index);
+        }
+      },
+      map: $.map,
+      filter: $.grep,
+      every: function(obj, test) {
+        var result = true;
+        if (!obj) {
+          return result;
+        }
+        $.each(obj, function(key, val) {
+          if (!(result = test.call(null, val, key, obj))) {
+            return false;
+          }
+        });
+        return !!result;
+      },
+      some: function(obj, test) {
+        var result = false;
+        if (!obj) {
+          return result;
+        }
+        $.each(obj, function(key, val) {
+          if (result = test.call(null, val, key, obj)) {
+            return false;
+          }
+        });
+        return !!result;
+      },
+      mixin: $.extend,
+      identity: function(x) {
+        return x;
+      },
+      clone: function(obj) {
+        return $.extend(true, {}, obj);
+      },
+      getIdGenerator: function() {
+        var counter = 0;
+        return function() {
+          return counter++;
+        };
+      },
+      templatify: function templatify(obj) {
+        return $.isFunction(obj) ? obj : template;
+        function template() {
+          return String(obj);
+        }
+      },
+      defer: function(fn) {
+        setTimeout(fn, 0);
+      },
+      debounce: function(func, wait, immediate) {
+        var timeout, result;
+        return function() {
+          var context = this, args = arguments, later, callNow;
+          later = function() {
+            timeout = null;
+            if (!immediate) {
+              result = func.apply(context, args);
+            }
+          };
+          callNow = immediate && !timeout;
+          clearTimeout(timeout);
+          timeout = setTimeout(later, wait);
+          if (callNow) {
+            result = func.apply(context, args);
+          }
+          return result;
+        };
+      },
+      throttle: function(func, wait) {
+        var context, args, timeout, result, previous, later;
+        previous = 0;
+        later = function() {
+          previous = new Date();
+          timeout = null;
+          result = func.apply(context, args);
+        };
+        return function() {
+          var now = new Date(), remaining = wait - (now - previous);
+          context = this;
+          args = arguments;
+          if (remaining <= 0) {
+            clearTimeout(timeout);
+            timeout = null;
+            previous = now;
+            result = func.apply(context, args);
+          } else if (!timeout) {
+            timeout = setTimeout(later, remaining);
+          }
+          return result;
+        };
+      },
+      stringify: function(val) {
+        return _.isString(val) ? val : JSON.stringify(val);
+      },
+      noop: function() {}
+    };
+  }();
+  var WWW = function() {
+    "use strict";
+    var defaultClassNames = {
+      wrapper: "twitter-typeahead",
+      input: "tt-input",
+      hint: "tt-hint",
+      menu: "tt-menu",
+      dataset: "tt-dataset",
+      suggestion: "tt-suggestion",
+      selectable: "tt-selectable",
+      empty: "tt-empty",
+      open: "tt-open",
+      cursor: "tt-cursor",
+      highlight: "tt-highlight"
+    };
+    return build;
+    function build(o) {
+      var www, classes;
+      classes = _.mixin({}, defaultClassNames, o);
+      www = {
+        css: buildCss(),
+        classes: classes,
+        html: buildHtml(classes),
+        selectors: buildSelectors(classes)
+      };
+      return {
+        css: www.css,
+        html: www.html,
+        classes: www.classes,
+        selectors: www.selectors,
+        mixin: function(o) {
+          _.mixin(o, www);
+        }
+      };
+    }
+    function buildHtml(c) {
+      return {
+        wrapper: '<span class="' + c.wrapper + '"></span>',
+        menu: '<div class="' + c.menu + '"></div>'
+      };
+    }
+    function buildSelectors(classes) {
+      var selectors = {};
+      _.each(classes, function(v, k) {
+        selectors[k] = "." + v;
+      });
+      return selectors;
+    }
+    function buildCss() {
+      var css = {
+        wrapper: {
+          position: "relative",
+          display: "inline-block"
+        },
+        hint: {
+          position: "absolute",
+          top: "0",
+          left: "0",
+          borderColor: "transparent",
+          boxShadow: "none",
+          opacity: "1"
+        },
+        input: {
+          position: "relative",
+          verticalAlign: "top",
+          backgroundColor: "transparent"
+        },
+        inputWithNoHint: {
+          position: "relative",
+          verticalAlign: "top"
+        },
+        menu: {
+          position: "absolute",
+          top: "100%",
+          left: "0",
+          zIndex: "100",
+          display: "none"
+        },
+        ltr: {
+          left: "0",
+          right: "auto"
+        },
+        rtl: {
+          left: "auto",
+          right: " 0"
+        }
+      };
+      if (_.isMsie()) {
+        _.mixin(css.input, {
+          backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
+        });
+      }
+      return css;
+    }
+  }();
+  var EventBus = function() {
+    "use strict";
+    var namespace, deprecationMap;
+    namespace = "typeahead:";
+    deprecationMap = {
+      render: "rendered",
+      cursorchange: "cursorchanged",
+      select: "selected",
+      autocomplete: "autocompleted"
+    };
+    function EventBus(o) {
+      if (!o || !o.el) {
+        $.error("EventBus initialized without el");
+      }
+      this.$el = $(o.el);
+    }
+    _.mixin(EventBus.prototype, {
+      _trigger: function(type, args) {
+        var $e;
+        $e = $.Event(namespace + type);
+        (args = args || []).unshift($e);
+        this.$el.trigger.apply(this.$el, args);
+        return $e;
+      },
+      before: function(type) {
+        var args, $e;
+        args = [].slice.call(arguments, 1);
+        $e = this._trigger("before" + type, args);
+        return $e.isDefaultPrevented();
+      },
+      trigger: function(type) {
+        var deprecatedType;
+        this._trigger(type, [].slice.call(arguments, 1));
+        if (deprecatedType = deprecationMap[type]) {
+          this._trigger(deprecatedType, [].slice.call(arguments, 1));
+        }
+      }
+    });
+    return EventBus;
+  }();
+  var EventEmitter = function() {
+    "use strict";
+    var splitter = /\s+/, nextTick = getNextTick();
+    return {
+      onSync: onSync,
+      onAsync: onAsync,
+      off: off,
+      trigger: trigger
+    };
+    function on(method, types, cb, context) {
+      var type;
+      if (!cb) {
+        return this;
+      }
+      types = types.split(splitter);
+      cb = context ? bindContext(cb, context) : cb;
+      this._callbacks = this._callbacks || {};
+      while (type = types.shift()) {
+        this._callbacks[type] = this._callbacks[type] || {
+              sync: [],
+              async: []
+            };
+        this._callbacks[type][method].push(cb);
+      }
+      return this;
+    }
+    function onAsync(types, cb, context) {
+      return on.call(this, "async", types, cb, context);
+    }
+    function onSync(types, cb, context) {
+      return on.call(this, "sync", types, cb, context);
+    }
+    function off(types) {
+      var type;
+      if (!this._callbacks) {
+        return this;
+      }
+      types = types.split(splitter);
+      while (type = types.shift()) {
+        delete this._callbacks[type];
+      }
+      return this;
+    }
+    function trigger(types) {
+      var type, callbacks, args, syncFlush, asyncFlush;
+      if (!this._callbacks) {
+        return this;
+      }
+      types = types.split(splitter);
+      args = [].slice.call(arguments, 1);
+      while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
+        syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
+        asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
+        syncFlush() && nextTick(asyncFlush);
+      }
+      return this;
+    }
+    function getFlush(callbacks, context, args) {
+      return flush;
+      function flush() {
+        var cancelled;
+        for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
+          cancelled = callbacks[i].apply(context, args) === false;
+        }
+        return !cancelled;
+      }
+    }
+    function getNextTick() {
+      var nextTickFn;
+      if (window.setImmediate) {
+        nextTickFn = function nextTickSetImmediate(fn) {
+          setImmediate(function() {
+            fn();
+          });
+        };
+      } else {
+        nextTickFn = function nextTickSetTimeout(fn) {
+          setTimeout(function() {
+            fn();
+          }, 0);
+        };
+      }
+      return nextTickFn;
+    }
+    function bindContext(fn, context) {
+      return fn.bind ? fn.bind(context) : function() {
+        fn.apply(context, [].slice.call(arguments, 0));
+      };
+    }
+  }();
+  var highlight = function(doc) {
+    "use strict";
+    var defaults = {
+      node: null,
+      pattern: null,
+      tagName: "strong",
+      className: null,
+      wordsOnly: false,
+      caseSensitive: false
+    };
+    return function hightlight(o) {
+      var regex;
+      o = _.mixin({}, defaults, o);
+      if (!o.node || !o.pattern) {
+        return;
+      }
+      o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
+      regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
+      traverse(o.node, hightlightTextNode);
+      function hightlightTextNode(textNode) {
+        var match, patternNode, wrapperNode;
+        if (match = regex.exec(textNode.data)) {
+          wrapperNode = doc.createElement(o.tagName);
+          o.className && (wrapperNode.className = o.className);
+          patternNode = textNode.splitText(match.index);
+          patternNode.splitText(match[0].length);
+          wrapperNode.appendChild(patternNode.cloneNode(true));
+          textNode.parentNode.replaceChild(wrapperNode, patternNode);
+        }
+        return !!match;
+      }
+      function traverse(el, hightlightTextNode) {
+        var childNode, TEXT_NODE_TYPE = 3;
+        for (var i = 0; i < el.childNodes.length; i++) {
+          childNode = el.childNodes[i];
+          if (childNode.nodeType === TEXT_NODE_TYPE) {
+            i += hightlightTextNode(childNode) ? 1 : 0;
+          } else {
+            traverse(childNode, hightlightTextNode);
+          }
+        }
+      }
+    };
+    function getRegex(patterns, caseSensitive, wordsOnly) {
+      var escapedPatterns = [], regexStr;
+      for (var i = 0, len = patterns.length; i < len; i++) {
+        escapedPatterns.push(_.escapeRegExChars(patterns[i]));
+      }
+      regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
+      return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
+    }
+  }(window.document);
+  var Input = function() {
+    "use strict";
+    var specialKeyCodeMap;
+    specialKeyCodeMap = {
+      9: "tab",
+      27: "esc",
+      37: "left",
+      39: "right",
+      13: "enter",
+      38: "up",
+      40: "down"
+    };
+    function Input(o, www) {
+      o = o || {};
+      if (!o.input) {
+        $.error("input is missing");
+      }
+      www.mixin(this);
+      this.$hint = $(o.hint);
+      this.$input = $(o.input);
+      this.query = this.$input.val();
+      this.queryWhenFocused = this.hasFocus() ? this.query : null;
+      this.$overflowHelper = buildOverflowHelper(this.$input);
+      this._checkLanguageDirection();
+      if (this.$hint.length === 0) {
+        this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
+      }
+    }
+    Input.normalizeQuery = function(str) {
+      return _.toStr(str).replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
+    };
+    _.mixin(Input.prototype, EventEmitter, {
+      _onBlur: function onBlur() {
+        this.resetInputValue();
+        this.trigger("blurred");
+      },
+      _onFocus: function onFocus() {
+        this.queryWhenFocused = this.query;
+        this.trigger("focused");
+      },
+      _onKeydown: function onKeydown($e) {
+        var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
+        this._managePreventDefault(keyName, $e);
+        if (keyName && this._shouldTrigger(keyName, $e)) {
+          this.trigger(keyName + "Keyed", $e);
+        }
+      },
+      _onInput: function onInput() {
+        this._setQuery(this.getInputValue());
+        this.clearHintIfInvalid();
+        this._checkLanguageDirection();
+      },
+      _managePreventDefault: function managePreventDefault(keyName, $e) {
+        var preventDefault;
+        switch (keyName) {
+          case "up":
+          case "down":
+            preventDefault = !withModifier($e);
+            break;
+
+          default:
+            preventDefault = false;
+        }
+        preventDefault && $e.preventDefault();
+      },
+      _shouldTrigger: function shouldTrigger(keyName, $e) {
+        var trigger;
+        switch (keyName) {
+          case "tab":
+            trigger = !withModifier($e);
+            break;
+
+          default:
+            trigger = true;
+        }
+        return trigger;
+      },
+      _checkLanguageDirection: function checkLanguageDirection() {
+        var dir = (this.$input.css("direction") || "ltr").toLowerCase();
+        if (this.dir !== dir) {
+          this.dir = dir;
+          this.$hint.attr("dir", dir);
+          this.trigger("langDirChanged", dir);
+        }
+      },
+      _setQuery: function setQuery(val, silent) {
+        var areEquivalent, hasDifferentWhitespace;
+        areEquivalent = areQueriesEquivalent(val, this.query);
+        hasDifferentWhitespace = areEquivalent ? this.query.length !== val.length : false;
+        this.query = val;
+        if (!silent && !areEquivalent) {
+          this.trigger("queryChanged", this.query);
+        } else if (!silent && hasDifferentWhitespace) {
+          this.trigger("whitespaceChanged", this.query);
+        }
+      },
+      bind: function() {
+        var that = this, onBlur, onFocus, onKeydown, onInput;
+        onBlur = _.bind(this._onBlur, this);
+        onFocus = _.bind(this._onFocus, this);
+        onKeydown = _.bind(this._onKeydown, this);
+        onInput = _.bind(this._onInput, this);
+        this.$input.on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
+        if (!_.isMsie() || _.isMsie() > 9) {
+          this.$input.on("input.tt", onInput);
+        } else {
+          this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
+            if (specialKeyCodeMap[$e.which || $e.keyCode]) {
+              return;
+            }
+            _.defer(_.bind(that._onInput, that, $e));
+          });
+        }
+        return this;
+      },
+      focus: function focus() {
+        this.$input.focus();
+      },
+      blur: function blur() {
+        this.$input.blur();
+      },
+      getLangDir: function getLangDir() {
+        return this.dir;
+      },
+      getQuery: function getQuery() {
+        return this.query || "";
+      },
+      setQuery: function setQuery(val, silent) {
+        this.setInputValue(val);
+        this._setQuery(val, silent);
+      },
+      hasQueryChangedSinceLastFocus: function hasQueryChangedSinceLastFocus() {
+        return this.query !== this.queryWhenFocused;
+      },
+      getInputValue: function getInputValue() {
+        return this.$input.val();
+      },
+      setInputValue: function setInputValue(value) {
+        this.$input.val(value);
+        this.clearHintIfInvalid();
+        this._checkLanguageDirection();
+      },
+      resetInputValue: function resetInputValue() {
+        this.setInputValue(this.query);
+      },
+      getHint: function getHint() {
+        return this.$hint.val();
+      },
+      setHint: function setHint(value) {
+        this.$hint.val(value);
+      },
+      clearHint: function clearHint() {
+        this.setHint("");
+      },
+      clearHintIfInvalid: function clearHintIfInvalid() {
+        var val, hint, valIsPrefixOfHint, isValid;
+        val = this.getInputValue();
+        hint = this.getHint();
+        valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
+        isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
+        !isValid && this.clearHint();
+      },
+      hasFocus: function hasFocus() {
+        return this.$input.is(":focus");
+      },
+      hasOverflow: function hasOverflow() {
+        var constraint = this.$input.width() - 2;
+        this.$overflowHelper.text(this.getInputValue());
+        return this.$overflowHelper.width() >= constraint;
+      },
+      isCursorAtEnd: function() {
+        var valueLength, selectionStart, range;
+        valueLength = this.$input.val().length;
+        selectionStart = this.$input[0].selectionStart;
+        if (_.isNumber(selectionStart)) {
+          return selectionStart === valueLength;
+        } else if (document.selection) {
+          range = document.selection.createRange();
+          range.moveStart("character", -valueLength);
+          return valueLength === range.text.length;
+        }
+        return true;
+      },
+      destroy: function destroy() {
+        this.$hint.off(".tt");
+        this.$input.off(".tt");
+        this.$overflowHelper.remove();
+        this.$hint = this.$input = this.$overflowHelper = $("<div>");
+      }
+    });
+    return Input;
+    function buildOverflowHelper($input) {
+      return $('<pre aria-hidden="true"></pre>').css({
+        position: "absolute",
+        visibility: "hidden",
+        whiteSpace: "pre",
+        fontFamily: $input.css("font-family"),
+        fontSize: $input.css("font-size"),
+        fontStyle: $input.css("font-style"),
+        fontVariant: $input.css("font-variant"),
+        fontWeight: $input.css("font-weight"),
+        wordSpacing: $input.css("word-spacing"),
+        letterSpacing: $input.css("letter-spacing"),
+        textIndent: $input.css("text-indent"),
+        textRendering: $input.css("text-rendering"),
+        textTransform: $input.css("text-transform")
+      }).insertAfter($input);
+    }
+    function areQueriesEquivalent(a, b) {
+      return Input.normalizeQuery(a) === Input.normalizeQuery(b);
+    }
+    function withModifier($e) {
+      return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
+    }
+  }();
+  var Dataset = function() {
+    "use strict";
+    var keys, nameGenerator;
+    keys = {
+      val: "tt-selectable-display",
+      obj: "tt-selectable-object"
+    };
+    nameGenerator = _.getIdGenerator();
+    function Dataset(o, www) {
+      o = o || {};
+      o.templates = o.templates || {};
+      o.templates.notFound = o.templates.notFound || o.templates.empty;
+      if (!o.source) {
+        $.error("missing source");
+      }
+      if (!o.node) {
+        $.error("missing node");
+      }
+      if (o.name && !isValidName(o.name)) {
+        $.error("invalid dataset name: " + o.name);
+      }
+      www.mixin(this);
+      this.highlight = !!o.highlight;
+      this.name = o.name || nameGenerator();
+      this.limit = o.limit || 5;
+      this.displayFn = getDisplayFn(o.display || o.displayKey);
+      this.templates = getTemplates(o.templates, this.displayFn);
+      this.source = o.source.__ttAdapter ? o.source.__ttAdapter() : o.source;
+      this.async = _.isUndefined(o.async) ? this.source.length > 2 : !!o.async;
+      this._resetLastSuggestion();
+      this.$el = $(o.node).addClass(this.classes.dataset).addClass(this.classes.dataset + "-" + this.name);
+    }
+    Dataset.extractData = function extractData(el) {
+      var $el = $(el);
+      if ($el.data(keys.obj)) {
+        return {
+          val: $el.data(keys.val) || "",
+          obj: $el.data(keys.obj) || null
+        };
+      }
+      return null;
+    };
+    _.mixin(Dataset.prototype, EventEmitter, {
+      _overwrite: function overwrite(query, suggestions) {
+        suggestions = suggestions || [];
+        if (suggestions.length) {
+          this._renderSuggestions(query, suggestions);
+        } else if (this.async && this.templates.pending) {
+          this._renderPending(query);
+        } else if (!this.async && this.templates.notFound) {
+          this._renderNotFound(query);
+        } else {
+          this._empty();
+        }
+        this.trigger("rendered", this.name, suggestions, false);
+      },
+      _append: function append(query, suggestions) {
+        suggestions = suggestions || [];
+        if (suggestions.length && this.$lastSuggestion.length) {
+          this._appendSuggestions(query, suggestions);
+        } else if (suggestions.length) {
+          this._renderSuggestions(query, suggestions);
+        } else if (!this.$lastSuggestion.length && this.templates.notFound) {
+          this._renderNotFound(query);
+        }
+        this.trigger("rendered", this.name, suggestions, true);
+      },
+      _renderSuggestions: function renderSuggestions(query, suggestions) {
+        var $fragment;
+        $fragment = this._getSuggestionsFragment(query, suggestions);
+        this.$lastSuggestion = $fragment.children().last();
+        this.$el.html($fragment).prepend(this._getHeader(query, suggestions)).append(this._getFooter(query, suggestions));
+      },
+      _appendSuggestions: function appendSuggestions(query, suggestions) {
+        var $fragment, $lastSuggestion;
+        $fragment = this._getSuggestionsFragment(query, suggestions);
+        $lastSuggestion = $fragment.children().last();
+        this.$lastSuggestion.after($fragment);
+        this.$lastSuggestion = $lastSuggestion;
+      },
+      _renderPending: function renderPending(query) {
+        var template = this.templates.pending;
+        this._resetLastSuggestion();
+        template && this.$el.html(template({
+          query: query,
+          dataset: this.name
+        }));
+      },
+      _renderNotFound: function renderNotFound(query) {
+        var template = this.templates.notFound;
+        this._resetLastSuggestion();
+        template && this.$el.html(template({
+          query: query,
+          dataset: this.name
+        }));
+      },
+      _empty: function empty() {
+        this.$el.empty();
+        this._resetLastSuggestion();
+      },
+      _getSuggestionsFragment: function getSuggestionsFragment(query, suggestions) {
+        var that = this, fragment;
+        fragment = document.createDocumentFragment();
+        _.each(suggestions, function getSuggestionNode(suggestion) {
+          var $el, context;
+          context = that._injectQuery(query, suggestion);
+          $el = $(that.templates.suggestion(context)).data(keys.obj, suggestion).data(keys.val, that.displayFn(suggestion)).addClass(that.classes.suggestion + " " + that.classes.selectable);
+          fragment.appendChild($el[0]);
+        });
+        this.highlight && highlight({
+          className: this.classes.highlight,
+          node: fragment,
+          pattern: query
+        });
+        return $(fragment);
+      },
+      _getFooter: function getFooter(query, suggestions) {
+        return this.templates.footer ? this.templates.footer({
+          query: query,
+          suggestions: suggestions,
+          dataset: this.name
+        }) : null;
+      },
+      _getHeader: function getHeader(query, suggestions) {
+        return this.templates.header ? this.templates.header({
+          query: query,
+          suggestions: suggestions,
+          dataset: this.name
+        }) : null;
+      },
+      _resetLastSuggestion: function resetLastSuggestion() {
+        this.$lastSuggestion = $();
+      },
+      _injectQuery: function injectQuery(query, obj) {
+        return _.isObject(obj) ? _.mixin({
+          _query: query
+        }, obj) : obj;
+      },
+      update: function update(query) {
+        var that = this, canceled = false, syncCalled = false, rendered = 0;
+        this.cancel();
+        this.cancel = function cancel() {
+          canceled = true;
+          that.cancel = $.noop;
+          that.async && that.trigger("asyncCanceled", query);
+        };
+        this.source(query, sync, async);
+        !syncCalled && sync([]);
+        function sync(suggestions) {
+          if (syncCalled) {
+            return;
+          }
+          syncCalled = true;
+          suggestions = (suggestions || []).slice(0, that.limit);
+          rendered = suggestions.length;
+          that._overwrite(query, suggestions);
+          if (rendered < that.limit && that.async) {
+            that.trigger("asyncRequested", query);
+          }
+        }
+        function async(suggestions) {
+          suggestions = suggestions || [];
+          if (!canceled && rendered < that.limit) {
+            that.cancel = $.noop;
+            // patch rendered += suggestions.length;
+            that._append(query, suggestions.slice(0, that.limit - rendered));
+            // patch: https://github.com/twitter/typeahead.js/pull/1212
+            rendered += suggestions.length;
+            that.async && that.trigger("asyncReceived", query);
+          }
+        }
+      },
+      cancel: $.noop,
+      clear: function clear() {
+        this._empty();
+        this.cancel();
+        this.trigger("cleared");
+      },
+      isEmpty: function isEmpty() {
+        return this.$el.is(":empty");
+      },
+      destroy: function destroy() {
+        this.$el = $("<div>");
+      }
+    });
+    return Dataset;
+    function getDisplayFn(display) {
+      display = display || _.stringify;
+      return _.isFunction(display) ? display : displayFn;
+      function displayFn(obj) {
+        return obj[display];
+      }
+    }
+    function getTemplates(templates, displayFn) {
+      return {
+        notFound: templates.notFound && _.templatify(templates.notFound),
+        pending: templates.pending && _.templatify(templates.pending),
+        header: templates.header && _.templatify(templates.header),
+        footer: templates.footer && _.templatify(templates.footer),
+        suggestion: templates.suggestion || suggestionTemplate
+      };
+      function suggestionTemplate(context) {
+        return $("<div>").text(displayFn(context));
+      }
+    }
+    function isValidName(str) {
+      return /^[_a-zA-Z0-9-]+$/.test(str);
+    }
+  }();
+  var Menu = function() {
+    "use strict";
+    function Menu(o, www) {
+      var that = this;
+      o = o || {};
+      if (!o.node) {
+        $.error("node is required");
+      }
+      www.mixin(this);
+      this.$node = $(o.node);
+      this.query = null;
+      this.datasets = _.map(o.datasets, initializeDataset);
+      function initializeDataset(oDataset) {
+        var node = that.$node.find(oDataset.node).first();
+        oDataset.node = node.length ? node : $("<div>").appendTo(that.$node);
+        return new Dataset(oDataset, www);
+      }
+    }
+    _.mixin(Menu.prototype, EventEmitter, {
+      _onSelectableClick: function onSelectableClick($e) {
+        this.trigger("selectableClicked", $($e.currentTarget));
+      },
+      _onRendered: function onRendered(type, dataset, suggestions, async) {
+        this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
+        this.trigger("datasetRendered", dataset, suggestions, async);
+      },
+      _onCleared: function onCleared() {
+        this.$node.toggleClass(this.classes.empty, this._allDatasetsEmpty());
+        this.trigger("datasetCleared");
+      },
+      _propagate: function propagate() {
+        this.trigger.apply(this, arguments);
+      },
+      _allDatasetsEmpty: function allDatasetsEmpty() {
+        return _.every(this.datasets, isDatasetEmpty);
+        function isDatasetEmpty(dataset) {
+          return dataset.isEmpty();
+        }
+      },
+      _getSelectables: function getSelectables() {
+        return this.$node.find(this.selectors.selectable);
+      },
+      _removeCursor: function _removeCursor() {
+        var $selectable = this.getActiveSelectable();
+        $selectable && $selectable.removeClass(this.classes.cursor);
+      },
+      _ensureVisible: function ensureVisible($el) {
+        var elTop, elBottom, nodeScrollTop, nodeHeight;
+        elTop = $el.position().top;
+        elBottom = elTop + $el.outerHeight(true);
+        nodeScrollTop = this.$node.scrollTop();
+        nodeHeight = this.$node.height() + parseInt(this.$node.css("paddingTop"), 10) + parseInt(this.$node.css("paddingBottom"), 10);
+        if (elTop < 0) {
+          this.$node.scrollTop(nodeScrollTop + elTop);
+        } else if (nodeHeight < elBottom) {
+          this.$node.scrollTop(nodeScrollTop + (elBottom - nodeHeight));
+        }
+      },
+      bind: function() {
+        var that = this, onSelectableClick;
+        onSelectableClick = _.bind(this._onSelectableClick, this);
+        this.$node.on("click.tt", this.selectors.selectable, onSelectableClick);
+        _.each(this.datasets, function(dataset) {
+          dataset.onSync("asyncRequested", that._propagate, that).onSync("asyncCanceled", that._propagate, that).onSync("asyncReceived", that._propagate, that).onSync("rendered", that._onRendered, that).onSync("cleared", that._onCleared, that);
+        });
+        return this;
+      },
+      isOpen: function isOpen() {
+        return this.$node.hasClass(this.classes.open);
+      },
+      open: function open() {
+        this.$node.addClass(this.classes.open);
+      },
+      close: function close() {
+        this.$node.removeClass(this.classes.open);
+        this._removeCursor();
+      },
+      setLanguageDirection: function setLanguageDirection(dir) {
+        this.$node.attr("dir", dir);
+      },
+      selectableRelativeToCursor: function selectableRelativeToCursor(delta) {
+        var $selectables, $oldCursor, oldIndex, newIndex;
+        $oldCursor = this.getActiveSelectable();
+        $selectables = this._getSelectables();
+        oldIndex = $oldCursor ? $selectables.index($oldCursor) : -1;
+        newIndex = oldIndex + delta;
+        newIndex = (newIndex + 1) % ($selectables.length + 1) - 1;
+        newIndex = newIndex < -1 ? $selectables.length - 1 : newIndex;
+        return newIndex === -1 ? null : $selectables.eq(newIndex);
+      },
+      setCursor: function setCursor($selectable) {
+        this._removeCursor();
+        if ($selectable = $selectable && $selectable.first()) {
+          $selectable.addClass(this.classes.cursor);
+          this._ensureVisible($selectable);
+        }
+      },
+      getSelectableData: function getSelectableData($el) {
+        return $el && $el.length ? Dataset.extractData($el) : null;
+      },
+      getActiveSelectable: function getActiveSelectable() {
+        var $selectable = this._getSelectables().filter(this.selectors.cursor).first();
+        return $selectable.length ? $selectable : null;
+      },
+      getTopSelectable: function getTopSelectable() {
+        var $selectable = this._getSelectables().first();
+        return $selectable.length ? $selectable : null;
+      },
+      update: function update(query) {
+        var isValidUpdate = query !== this.query;
+        if (isValidUpdate) {
+          this.query = query;
+          _.each(this.datasets, updateDataset);
+        }
+        return isValidUpdate;
+        function updateDataset(dataset) {
+          dataset.update(query);
+        }
+      },
+      empty: function empty() {
+        _.each(this.datasets, clearDataset);
+        this.query = null;
+        this.$node.addClass(this.classes.empty);
+        function clearDataset(dataset) {
+          dataset.clear();
+        }
+      },
+      destroy: function destroy() {
+        this.$node.off(".tt");
+        this.$node = $("<div>");
+        _.each(this.datasets, destroyDataset);
+        function destroyDataset(dataset) {
+          dataset.destroy();
+        }
+      }
+    });
+    return Menu;
+  }();
+  var DefaultMenu = function() {
+    "use strict";
+    var s = Menu.prototype;
+    function DefaultMenu() {
+      Menu.apply(this, [].slice.call(arguments, 0));
+    }
+    _.mixin(DefaultMenu.prototype, Menu.prototype, {
+      open: function open() {
+        !this._allDatasetsEmpty() && this._show();
+        return s.open.apply(this, [].slice.call(arguments, 0));
+      },
+      close: function close() {
+        this._hide();
+        return s.close.apply(this, [].slice.call(arguments, 0));
+      },
+      _onRendered: function onRendered() {
+        if (this._allDatasetsEmpty()) {
+          this._hide();
+        } else {
+          this.isOpen() && this._show();
+        }
+        return s._onRendered.apply(this, [].slice.call(arguments, 0));
+      },
+      _onCleared: function onCleared() {
+        if (this._allDatasetsEmpty()) {
+          this._hide();
+        } else {
+          this.isOpen() && this._show();
+        }
+        return s._onCleared.apply(this, [].slice.call(arguments, 0));
+      },
+      setLanguageDirection: function setLanguageDirection(dir) {
+        this.$node.css(dir === "ltr" ? this.css.ltr : this.css.rtl);
+        return s.setLanguageDirection.apply(this, [].slice.call(arguments, 0));
+      },
+      _hide: function hide() {
+        this.$node.hide();
+      },
+      _show: function show() {
+        this.$node.css("display", "block");
+      }
+    });
+    return DefaultMenu;
+  }();
+  var Typeahead = function() {
+    "use strict";
+    function Typeahead(o, www) {
+      var onFocused, onBlurred, onEnterKeyed, onTabKeyed, onEscKeyed, onUpKeyed, onDownKeyed, onLeftKeyed, onRightKeyed, onQueryChanged, onWhitespaceChanged;
+      o = o || {};
+      if (!o.input) {
+        $.error("missing input");
+      }
+      if (!o.menu) {
+        $.error("missing menu");
+      }
+      if (!o.eventBus) {
+        $.error("missing event bus");
+      }
+      www.mixin(this);
+      this.eventBus = o.eventBus;
+      this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
+      this.input = o.input;
+      this.menu = o.menu;
+      this.enabled = true;
+      this.active = false;
+      this.input.hasFocus() && this.activate();
+      this.dir = this.input.getLangDir();
+      this._hacks();
+      this.menu.bind().onSync("selectableClicked", this._onSelectableClicked, this).onSync("asyncRequested", this._onAsyncRequested, this).onSync("asyncCanceled", this._onAsyncCanceled, this).onSync("asyncReceived", this._onAsyncReceived, this).onSync("datasetRendered", this._onDatasetRendered, this).onSync("datasetCleared", this._onDatasetCleared, this);
+      onFocused = c(this, "activate", "open", "_onFocused");
+      onBlurred = c(this, "deactivate", "_onBlurred");
+      onEnterKeyed = c(this, "isActive", "isOpen", "_onEnterKeyed");
+      onTabKeyed = c(this, "isActive", "isOpen", "_onTabKeyed");
+      onEscKeyed = c(this, "isActive", "_onEscKeyed");
+      onUpKeyed = c(this, "isActive", "open", "_onUpKeyed");
+      onDownKeyed = c(this, "isActive", "open", "_onDownKeyed");
+      onLeftKeyed = c(this, "isActive", "isOpen", "_onLeftKeyed");
+      onRightKeyed = c(this, "isActive", "isOpen", "_onRightKeyed");
+      onQueryChanged = c(this, "_openIfActive", "_onQueryChanged");
+      onWhitespaceChanged = c(this, "_openIfActive", "_onWhitespaceChanged");
+      this.input.bind().onSync("focused", onFocused, this).onSync("blurred", onBlurred, this).onSync("enterKeyed", onEnterKeyed, this).onSync("tabKeyed", onTabKeyed, this).onSync("escKeyed", onEscKeyed, this).onSync("upKeyed", onUpKeyed, this).onSync("downKeyed", onDownKeyed, this).onSync("leftKeyed", onLeftKeyed, this).onSync("rightKeyed", onRightKeyed, this).onSync("queryChanged", onQueryChanged, this).onSync("whitespaceChanged", onWhitespaceChanged, this).onSync("langDirChanged", this [...]
+    }
+    _.mixin(Typeahead.prototype, {
+      _hacks: function hacks() {
+        var $input, $menu;
+        $input = this.input.$input || $("<div>");
+        $menu = this.menu.$node || $("<div>");
+        $input.on("blur.tt", function($e) {
+          var active, isActive, hasActive;
+          active = document.activeElement;
+          isActive = $menu.is(active);
+          hasActive = $menu.has(active).length > 0;
+          if (_.isMsie() && (isActive || hasActive)) {
+            $e.preventDefault();
+            $e.stopImmediatePropagation();
+            _.defer(function() {
+              $input.focus();
+            });
+          }
+        });
+        $menu.on("mousedown.tt", function($e) {
+          $e.preventDefault();
+        });
+      },
+      _onSelectableClicked: function onSelectableClicked(type, $el) {
+        this.select($el);
+      },
+      _onDatasetCleared: function onDatasetCleared() {
+        this._updateHint();
+      },
+      _onDatasetRendered: function onDatasetRendered(type, dataset, suggestions, async) {
+        this._updateHint();
+        this.eventBus.trigger("render", suggestions, async, dataset);
+      },
+      _onAsyncRequested: function onAsyncRequested(type, dataset, query) {
+        this.eventBus.trigger("asyncrequest", query, dataset);
+      },
+      _onAsyncCanceled: function onAsyncCanceled(type, dataset, query) {
+        this.eventBus.trigger("asynccancel", query, dataset);
+      },
+      _onAsyncReceived: function onAsyncReceived(type, dataset, query) {
+        this.eventBus.trigger("asyncreceive", query, dataset);
+      },
+      _onFocused: function onFocused() {
+        this._minLengthMet() && this.menu.update(this.input.getQuery());
+      },
+      _onBlurred: function onBlurred() {
+        if (this.input.hasQueryChangedSinceLastFocus()) {
+          this.eventBus.trigger("change", this.input.getQuery());
+        }
+      },
+      _onEnterKeyed: function onEnterKeyed(type, $e) {
+        var $selectable;
+        if ($selectable = this.menu.getActiveSelectable()) {
+          this.select($selectable) && $e.preventDefault();
+        }
+      },
+      _onTabKeyed: function onTabKeyed(type, $e) {
+        var $selectable;
+        if ($selectable = this.menu.getActiveSelectable()) {
+          this.select($selectable) && $e.preventDefault();
+        } else if ($selectable = this.menu.getTopSelectable()) {
+          this.autocomplete($selectable) && $e.preventDefault();
+        }
+      },
+      _onEscKeyed: function onEscKeyed() {
+        this.close();
+      },
+      _onUpKeyed: function onUpKeyed() {
+        this.moveCursor(-1);
+      },
+      _onDownKeyed: function onDownKeyed() {
+        this.moveCursor(+1);
+      },
+      _onLeftKeyed: function onLeftKeyed() {
+        if (this.dir === "rtl" && this.input.isCursorAtEnd()) {
+          this.autocomplete(this.menu.getTopSelectable());
+        }
+      },
+      _onRightKeyed: function onRightKeyed() {
+        if (this.dir === "ltr" && this.input.isCursorAtEnd()) {
+          this.autocomplete(this.menu.getTopSelectable());
+        }
+      },
+      _onQueryChanged: function onQueryChanged(e, query) {
+        this._minLengthMet(query) ? this.menu.update(query) : this.menu.empty();
+      },
+      _onWhitespaceChanged: function onWhitespaceChanged() {
+        this._updateHint();
+      },
+      _onLangDirChanged: function onLangDirChanged(e, dir) {
+        if (this.dir !== dir) {
+          this.dir = dir;
+          this.menu.setLanguageDirection(dir);
+        }
+      },
+      _openIfActive: function openIfActive() {
+        this.isActive() && this.open();
+      },
+      _minLengthMet: function minLengthMet(query) {
+        query = _.isString(query) ? query : this.input.getQuery() || "";
+        return query.length >= this.minLength;
+      },
+      _updateHint: function updateHint() {
+        var $selectable, data, val, query, escapedQuery, frontMatchRegEx, match;
+        $selectable = this.menu.getTopSelectable();
+        data = this.menu.getSelectableData($selectable);
+        val = this.input.getInputValue();
+        if (data && !_.isBlankString(val) && !this.input.hasOverflow()) {
+          query = Input.normalizeQuery(val);
+          escapedQuery = _.escapeRegExChars(query);
+          frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
+          match = frontMatchRegEx.exec(data.val);
+          match && this.input.setHint(val + match[1]);
+        } else {
+          this.input.clearHint();
+        }
+      },
+      isEnabled: function isEnabled() {
+        return this.enabled;
+      },
+      enable: function enable() {
+        this.enabled = true;
+      },
+      disable: function disable() {
+        this.enabled = false;
+      },
+      isActive: function isActive() {
+        return this.active;
+      },
+      activate: function activate() {
+        if (this.isActive()) {
+          return true;
+        } else if (!this.isEnabled() || this.eventBus.before("active")) {
+          return false;
+        } else {
+          this.active = true;
+          this.eventBus.trigger("active");
+          return true;
+        }
+      },
+      deactivate: function deactivate() {
+        if (!this.isActive()) {
+          return true;
+        } else if (this.eventBus.before("idle")) {
+          return false;
+        } else {
+          this.active = false;
+          this.close();
+          this.eventBus.trigger("idle");
+          return true;
+        }
+      },
+      isOpen: function isOpen() {
+        return this.menu.isOpen();
+      },
+      open: function open() {
+        if (!this.isOpen() && !this.eventBus.before("open")) {
+          this.menu.open();
+          this._updateHint();
+          this.eventBus.trigger("open");
+        }
+        return this.isOpen();
+      },
+      close: function close() {
+        if (this.isOpen() && !this.eventBus.before("close")) {
+          this.menu.close();
+          this.input.clearHint();
+          this.input.resetInputValue();
+          this.eventBus.trigger("close");
+        }
+        return !this.isOpen();
+      },
+      setVal: function setVal(val) {
+        this.input.setQuery(_.toStr(val));
+      },
+      getVal: function getVal() {
+        return this.input.getQuery();
+      },
+      select: function select($selectable) {
+        var data = this.menu.getSelectableData($selectable);
+        if (data && !this.eventBus.before("select", data.obj)) {
+          this.input.setQuery(data.val, true);
+          this.eventBus.trigger("select", data.obj);
+          this.close();
+          return true;
+        }
+        return false;
+      },
+      autocomplete: function autocomplete($selectable) {
+        var query, data, isValid;
+        query = this.input.getQuery();
+        data = this.menu.getSelectableData($selectable);
+        isValid = data && query !== data.val;
+        if (isValid && !this.eventBus.before("autocomplete", data.obj)) {
+          this.input.setQuery(data.val);
+          this.eventBus.trigger("autocomplete", data.obj);
+          return true;
+        }
+        return false;
+      },
+      moveCursor: function moveCursor(delta) {
+        var query, $candidate, data, payload, cancelMove;
+        query = this.input.getQuery();
+        $candidate = this.menu.selectableRelativeToCursor(delta);
+        data = this.menu.getSelectableData($candidate);
+        payload = data ? data.obj : null;
+        cancelMove = this._minLengthMet() && this.menu.update(query);
+        if (!cancelMove && !this.eventBus.before("cursorchange", payload)) {
+          this.menu.setCursor($candidate);
+          if (data) {
+            this.input.setInputValue(data.val);
+          } else {
+            this.input.resetInputValue();
+            this._updateHint();
+          }
+          this.eventBus.trigger("cursorchange", payload);
+          return true;
+        }
+        return false;
+      },
+      destroy: function destroy() {
+        this.input.destroy();
+        this.menu.destroy();
+      }
+    });
+    return Typeahead;
+    function c(ctx) {
+      var methods = [].slice.call(arguments, 1);
+      return function() {
+        var args = [].slice.call(arguments);
+        _.each(methods, function(method) {
+          return ctx[method].apply(ctx, args);
+        });
+      };
+    }
+  }();
+  (function() {
+    "use strict";
+    var old, keys, methods;
+    old = $.fn.typeahead;
+    keys = {
+      www: "tt-www",
+      attrs: "tt-attrs",
+      typeahead: "tt-typeahead"
+    };
+    methods = {
+      initialize: function initialize(o, datasets) {
+        var www;
+        datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
+        o = o || {};
+        www = WWW(o.classNames);
+        return this.each(attach);
+        function attach() {
+          var $input, $wrapper, $hint, $menu, defaultHint, defaultMenu, eventBus, input, menu, typeahead, MenuConstructor;
+          _.each(datasets, function(d) {
+            d.highlight = !!o.highlight;
+          });
+          $input = $(this);
+          $wrapper = $(www.html.wrapper);
+          $hint = $elOrNull(o.hint);
+          $menu = $elOrNull(o.menu);
+          defaultHint = o.hint !== false && !$hint;
+          defaultMenu = o.menu !== false && !$menu;
+          defaultHint && ($hint = buildHintFromInput($input, www));
+          defaultMenu && ($menu = $(www.html.menu).css(www.css.menu));
+          $hint && $hint.val("");
+          $input = prepInput($input, www);
+          if (defaultHint || defaultMenu) {
+            $wrapper.css(www.css.wrapper);
+            $input.css(defaultHint ? www.css.input : www.css.inputWithNoHint);
+            $input.wrap($wrapper).parent().prepend(defaultHint ? $hint : null).append(defaultMenu ? $menu : null);
+          }
+          MenuConstructor = defaultMenu ? DefaultMenu : Menu;
+          eventBus = new EventBus({
+            el: $input
+          });
+          input = new Input({
+            hint: $hint,
+            input: $input
+          }, www);
+          menu = new MenuConstructor({
+            node: $menu,
+            datasets: datasets
+          }, www);
+          typeahead = new Typeahead({
+            input: input,
+            menu: menu,
+            eventBus: eventBus,
+            minLength: o.minLength
+          }, www);
+          $input.data(keys.www, www);
+          $input.data(keys.typeahead, typeahead);
+        }
+      },
+      isEnabled: function isEnabled() {
+        var enabled;
+        ttEach(this.first(), function(t) {
+          enabled = t.isEnabled();
+        });
+        return enabled;
+      },
+      enable: function enable() {
+        ttEach(this, function(t) {
+          t.enable();
+        });
+        return this;
+      },
+      disable: function disable() {
+        ttEach(this, function(t) {
+          t.disable();
+        });
+        return this;
+      },
+      isActive: function isActive() {
+        var active;
+        ttEach(this.first(), function(t) {
+          active = t.isActive();
+        });
+        return active;
+      },
+      activate: function activate() {
+        ttEach(this, function(t) {
+          t.activate();
+        });
+        return this;
+      },
+      deactivate: function deactivate() {
+        ttEach(this, function(t) {
+          t.deactivate();
+        });
+        return this;
+      },
+      isOpen: function isOpen() {
+        var open;
+        ttEach(this.first(), function(t) {
+          open = t.isOpen();
+        });
+        return open;
+      },
+      open: function open() {
+        ttEach(this, function(t) {
+          t.open();
+        });
+        return this;
+      },
+      close: function close() {
+        ttEach(this, function(t) {
+          t.close();
+        });
+        return this;
+      },
+      select: function select(el) {
+        var success = false, $el = $(el);
+        ttEach(this.first(), function(t) {
+          success = t.select($el);
+        });
+        return success;
+      },
+      autocomplete: function autocomplete(el) {
+        var success = false, $el = $(el);
+        ttEach(this.first(), function(t) {
+          success = t.autocomplete($el);
+        });
+        return success;
+      },
+      moveCursor: function moveCursoe(delta) {
+        var success = false;
+        ttEach(this.first(), function(t) {
+          success = t.moveCursor(delta);
+        });
+        return success;
+      },
+      val: function val(newVal) {
+        var query;
+        if (!arguments.length) {
+          ttEach(this.first(), function(t) {
+            query = t.getVal();
+          });
+          return query;
+        } else {
+          ttEach(this, function(t) {
+            t.setVal(newVal);
+          });
+          return this;
+        }
+      },
+      destroy: function destroy() {
+        ttEach(this, function(typeahead, $input) {
+          revert($input);
+          typeahead.destroy();
+        });
+        return this;
+      }
+    };
+    $.fn.typeahead = function(method) {
+      if (methods[method]) {
+        return methods[method].apply(this, [].slice.call(arguments, 1));
+      } else {
+        return methods.initialize.apply(this, arguments);
+      }
+    };
+    $.fn.typeahead.noConflict = function noConflict() {
+      $.fn.typeahead = old;
+      return this;
+    };
+    function ttEach($els, fn) {
+      $els.each(function() {
+        var $input = $(this), typeahead;
+        (typeahead = $input.data(keys.typeahead)) && fn(typeahead, $input);
+      });
+    }
+    function buildHintFromInput($input, www) {
+      return $input.clone().addClass(www.classes.hint).removeData().css(www.css.hint).css(getBackgroundStyles($input)).prop("readonly", true).removeAttr("id name placeholder required").attr({
+        autocomplete: "off",
+        spellcheck: "false",
+        tabindex: -1
+      });
+    }
+    function prepInput($input, www) {
+      $input.data(keys.attrs, {
+        dir: $input.attr("dir"),
+        autocomplete: $input.attr("autocomplete"),
+        spellcheck: $input.attr("spellcheck"),
+        style: $input.attr("style")
+      });
+      $input.addClass(www.classes.input).attr({
+        autocomplete: "off",
+        spellcheck: false
+      });
+      try {
+        !$input.attr("dir") && $input.attr("dir", "auto");
+      } catch (e) {}
+      return $input;
+    }
+    function getBackgroundStyles($el) {
+      return {
+        backgroundAttachment: $el.css("background-attachment"),
+        backgroundClip: $el.css("background-clip"),
+        backgroundColor: $el.css("background-color"),
+        backgroundImage: $el.css("background-image"),
+        backgroundOrigin: $el.css("background-origin"),
+        backgroundPosition: $el.css("background-position"),
+        backgroundRepeat: $el.css("background-repeat"),
+        backgroundSize: $el.css("background-size")
+      };
+    }
+    function revert($input) {
+      var www, $wrapper;
+      www = $input.data(keys.www);
+      $wrapper = $input.parent().filter(www.selectors.wrapper);
+      _.each($input.data(keys.attrs), function(val, key) {
+        _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
+      });
+      $input.removeData(keys.typeahead).removeData(keys.www).removeData(keys.attr).removeClass(www.classes.input);
+      if ($wrapper.length) {
+        $input.detach().insertAfter($wrapper);
+        $wrapper.remove();
+      }
+    }
+    function $elOrNull(obj) {
+      var isValid, $el;
+      isValid = _.isJQuery(obj) || _.isElement(obj);
+      $el = isValid ? $(obj).first() : [];
+      return $el.length ? $el : null;
+    }
+  })();
+});
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.min.js b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.min.js
new file mode 100644
index 0000000..377ad3d
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/resources/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.min.js
@@ -0,0 +1,7 @@
+/*!
+ * typeahead.js 0.11.1-patched-with-1212 (including patch https://github.com/twitter/typeahead.js/pull/1212)
+ * https://github.com/twitter/typeahead.js
+ * Copyright 2013-2015 Twitter, Inc. and other contributors; Licensed MIT
+ */
+
+!function(a,b){"function"==typeof define&&define.amd?define("typeahead.js",["jquery"],function(a){return b(a)}):"object"==typeof exports?module.exports=b(require("jquery")):b(jQuery)}(this,function(a){var b=function(){"use strict";return{isMsie:function(){return/(msie|trident)/i.test(navigator.userAgent)?navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2]:!1},isBlankString:function(a){return!a||/^\s*$/.test(a)},escapeRegExChars:function(a){return a.replace(/[\-\[\]\/\{\}\(\)\*\+\?\. [...]
\ No newline at end of file
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
new file mode 100644
index 0000000..47aca95
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/resources/META-INF/tobago-config.xml
@@ -0,0 +1,400 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+
+<tobago-config
+    xmlns="http://myfaces.apache.org/tobago/tobago-config"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://myfaces.apache.org/tobago/tobago-config http://myfaces.apache.org/tobago/tobago-config-3.0.xsd"
+    version="3.0">
+
+  <name>tobago-theme-standard</name>
+
+  <content-security-policy mode="on">
+    <directive>default-src 'self'</directive>
+  </content-security-policy>
+
+  <theme-definitions>
+    <theme-definition>
+      <name>standard</name>
+      <display-name>Standard Theme</display-name>
+      <versioned>true</versioned>
+      <renderers>
+        <renderer>
+          <name>Button</name>
+          <supported-markup>
+            <markup>default</markup>
+            <markup>disabled</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Calendar</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>selected</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Command</name>
+          <supported-markup>
+            <markup>disabled</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Date</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>File</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>FlexLayout</name>
+          <supported-markup>
+            <markup>vertically</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Image</name>
+          <supported-markup>
+            <markup>disabled</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>In</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>number</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Label</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Link</name>
+          <supported-markup>
+            <markup>disabled</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Messages</name>
+          <supported-markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Out</name>
+          <supported-markup>
+            <markup>deleted</markup>
+            <markup>strong</markup>
+            <markup>number</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Page</name>
+          <supported-markup>
+            <markup>portlet</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Popup</name>
+          <supported-markup>
+            <markup>modal</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>SelectBooleanCheckbox</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>selected</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>SelectManyCheckbox</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>selected</markup>
+            <markup>inline</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>SelectManyListbox</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>selected</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>SelectManyShuttle</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>selected</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>SelectOneChoice</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>selected</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>SelectOneListbox</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>selected</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>SelectOneRadio</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <markup>selected</markup>
+            <markup>inline</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Sheet</name>
+          <supported-markup>
+            <!-- internal: for the paging buttons -->
+            <markup>disabled</markup>
+            <!-- internal: for the header -->
+            <markup>resizable</markup>
+            <markup>sortable</markup>
+            <markup>ascending</markup>
+            <markup>descending</markup>
+            <!-- for the rows -->
+            <markup>odd</markup>
+            <markup>even</markup>
+            <markup>selected</markup>
+            <!-- for the cells -->
+            <markup>clickable</markup>
+            <markup>filler</markup>
+            <markup>first</markup>
+            <!-- internal: for the paging fields -->
+            <markup>left</markup>
+            <markup>center</markup>
+            <markup>right</markup>
+            <markup>inverse</markup>
+            <markup>striped</markup>
+            <markup>bordered</markup>
+            <markup>hover</markup>
+            <markup>small</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Tab</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>selected</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Textarea</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>Time</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>readonly</markup>
+            <markup>required</markup>
+            <markup>fatal</markup>
+            <markup>error</markup>
+            <markup>warn</markup>
+            <markup>info</markup>
+            <!-- internal: for the seconds field -->
+            <markup>seconds</markup>
+            <markup>timepicker</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>ToolBar</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <markup>selected</markup>
+            <markup>big</markup>
+            <markup>right</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>TreeCommand</name>
+          <supported-markup>
+            <markup>disabled</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>TreeLabel</name>
+          <supported-markup>
+            <markup>disabled</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>TreeNode</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <!--XXX has to be in label and command ? -->
+            <markup>strong</markup>
+            <markup>selected</markup>
+            <markup>folder</markup>
+            <markup>expanded</markup>
+          </supported-markup>
+        </renderer>
+        <renderer>
+          <name>TreeMenuNode</name>
+          <supported-markup>
+            <markup>disabled</markup>
+            <!--XXX has to be in label and command ? -->
+            <markup>strong</markup>
+            <markup>selected</markup>
+            <markup>folder</markup>
+            <markup>expanded</markup>
+          </supported-markup>
+        </renderer>
+      </renderers>
+      <resources production="true">
+        <script name="/tobago/standard/jquery/jquery-2.2.4.min.js"/>
+        <script name="/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.min.js"/>
+        <script name="/tobago/standard/tether/1.1.1/js/tether.min.js"/>
+        <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.min.js"/>
+        <script name="/tobago/standard/moment/2.13.0/moment-with-locales.min.js"/>
+        <script name="/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js"/>
+        <script name="/tobago/standard/script/tobago.min.js"/>
+        <script name="/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.min.js"/>
+        <style name="/tobago/standard/tether/1.1.1/css/tether.min.css"/>
+        <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css"/>
+        <style name="/tobago/standard/font-awesome/4.6.1/css/font-awesome.min.css"/>
+        <style name="/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.min.css"/>
+      </resources>
+      <resources production="false">
+        <script name="/tobago/standard/jquery/jquery-2.2.4.js"/>
+        <script name="/tobago/standard/jquery-ui/1.12.1.custom/jquery-ui.js"/>
+        <script name="/tobago/standard/tether/1.1.1/js/tether.js"/>
+        <script name="/tobago/standard/bootstrap/4.0.0-alpha.5/js/bootstrap.js"/>
+        <script name="/tobago/standard/moment/2.13.0/moment-with-locales.js"/>
+        <script name="/tobago/standard/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.js"/>
+        <script name="/tobago/standard/script/tobago-jsf.js"/>
+        <script name="/tobago/standard/script/tobago.js"/>
+        <script name="/tobago/standard/script/tobago-calendar.js"/>
+        <script name="/tobago/standard/script/tobago-console.js"/>
+        <script name="/tobago/standard/script/tobago-in.js"/>
+        <script name="/tobago/standard/script/tobago-layout.js"/>
+        <script name="/tobago/standard/script/tobago-overlay.js"/>
+        <script name="/tobago/standard/script/tobago-popup.js"/>
+        <script name="/tobago/standard/script/tobago-sheet.js"/>
+        <script name="/tobago/standard/script/tobago-suggest.js"/>
+        <script name="/tobago/standard/script/tobago-tab.js"/>
+        <script name="/tobago/standard/script/tobago-tree.js"/>
+        <script name="/tobago/standard/script/tobago-utils.js"/>
+        <script name="/tobago/standard/typeahead/0.11.1-patched-with-1212/typeahead.js"/>
+        <style name="/tobago/standard/tether/1.1.1/css/tether.css"/>
+        <style name="/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css"/>
+        <style name="/tobago/standard/font-awesome/4.6.1/css/font-awesome.css"/>
+        <style name="/tobago/standard/bootstrap-datetimepicker/4.17.37/css/bootstrap-datetimepicker.css"/>
+      </resources>
+    </theme-definition>
+  </theme-definitions>
+</tobago-config>
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/scss/_custom.scss b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/scss/_custom.scss
new file mode 100644
index 0000000..167df45
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/scss/_custom.scss
@@ -0,0 +1,19 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+@import "tobago";
+
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/scss/_tobago.scss b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/scss/_tobago.scss
new file mode 100644
index 0000000..b342151
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/main/scss/_tobago.scss
@@ -0,0 +1,918 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+Todo: check, if this is needed? (It doesn't work with the build system)
+
+.tobago-file-real {
+  filter: alpha(opacity: 0);
+}
+*/
+
+/*
+ * theme: standard
+ * agent: standard
+ */
+
+/* box -------------------------------------------------------------- */
+
+.tobago-box-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* button -------------------------------------------------------------- */
+
+/* XXX fixes a problem with image in button inside a segmentLayout (with FF40 and IE11)
+   test page: buttons-with-image.xhtml
+   This might not be a good solution, is works only with images not larger then 16px
+*/
+.tobago-button > img {
+  margin-top: -1px;
+  margin-bottom: -1px;
+}
+
+/* collapsible -------------------------------------------------------------- */
+
+.tobago-collapsed.tobago-box .card-block,
+.tobago-collapsed.tobago-section .tobago-section-content,
+.tobago-collapsed.tobago-panel {
+  display: none;
+}
+
+/* date -------------------------------------------------------------- */
+
+.tobago-date {
+  min-width: 7em;
+}
+
+/* Remove IE10's "clear field" X button */
+.tobago-date::-ms-clear {
+  display: none;
+}
+
+/* for pickers with more than one icon, e.g. date-time picker */
+.btn > .fa:nth-child(n+2) {
+  margin-left: .3em;
+}
+
+/*
+XXX workaround for Bootstrap with datetimepicker needed for popups
+*/
+.bootstrap-datetimepicker-widget {
+  z-index: 2000 !important;
+}
+
+/*
+XXX need for fixing wrong positioning of bootstrap datepicker.
+See https://github.com/Eonasdan/bootstrap-datetimepicker/issues/790 for more information.
+*/
+body {
+  position: relative;
+}
+
+/* file -------------------------------------------------------------- */
+
+.tobago-file {
+  position: relative;
+}
+
+.tobago-file-pretty {
+  text-overflow: ellipsis;
+}
+
+.tobago-file-real {
+  position: absolute;
+  right: 0;
+  top: 0;
+  bottom: 0;
+  opacity: 0;
+  width: 100%;
+  z-index: 2;
+}
+
+/* flexLayout -------------------------------------------------------------- */
+
+.tobago-flexLayout {
+    display: -webkit-flex; /* needed e.g. for Safari 8.0.2 */
+    display: -ms-flexbox; /* needed for IE 10 */
+    display: flex;
+    min-width: 0; /* without this, Firefox/Webkit are different from IE:
+    Set the minimal width to zero make flex-layout responsive for the width,
+    even if there is overflowing content.
+    currently e.g. PRE-code blocks in the demo are too wide. XXX */
+}
+
+.tobago-flexLayout-markup-vertically {
+    flex-direction: column;
+    -webkit-flex-direction: column;
+    -ms-flex-direction: column;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-flexLayout-markup-vertically > .btn:nth-child(n+2) {
+  margin-left: 0 !important;
+}
+
+.tobago-flexLayout > .form-control:nth-child(n+2),
+.tobago-flexLayout > .input-group:nth-child(n+2),
+.tobago-flexLayout > .tobago-input-group-outer:nth-child(n+2),
+.tobago-flexLayout > .tobago-out:nth-child(n+2),
+.tobago-flexLayout > .tobago-file:nth-child(n+2),
+.tobago-flexLayout > .tobago-panel:nth-child(n+2),
+.tobago-flexLayout > .tobago-label:nth-child(n+2),
+.tobago-flexLayout > .tobago-selectManyShuttle:nth-child(n+2),
+.tobago-flexLayout > .twitter-typeahead:nth-child(n+2) {
+    margin-left: 5px;
+}
+
+.tobago-alignItems-baseline {
+  align-items: baseline;
+}
+
+.tobago-alignItems-center {
+  align-items: center;
+}
+
+.tobago-alignItems-flexEnd {
+  align-items: flex-end;
+}
+
+.tobago-alignItems-flexStart {
+  align-items: flex-start;
+}
+
+.tobago-alignItems-stretch {
+  align-items: stretch;
+}
+
+.tobago-justifyContent-center {
+  justify-content: center;
+}
+
+.tobago-justifyContent-flexStart {
+  justify-content: flex-start;
+}
+
+.tobago-justifyContent-flexEnd{
+  justify-content: flex-end;
+}
+
+.tobago-justifyContent-spaceBetween{
+  justify-content: space-between;
+}
+
+.tobago-justifyContent-spaceAround{
+  justify-content: space-around;
+}
+
+/* footer -------------------------------------------------------------- */
+
+.tobago-footer {
+  background-color: #ffffff;
+  padding: 5px 10px;
+  -webkit-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  -moz-box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+  box-shadow: 0 0 5px 5px rgba(200,200,200,0.5);
+}
+
+.navbar-fixed-bottom {
+  margin-top: 10px;
+}
+
+/* gridLayout -------------------------------------------------------------- */
+
+.tobago-gridLayout {
+    width: 100%;
+    height: 100%;
+/*
+    border-spacing: 5px;
+    border-collapse: separate;
+*/
+    border-spacing: 0;
+    border-collapse: collapse;
+}
+
+table.tobago-gridLayout > tbody > tr > td {
+    vertical-align: top;
+    padding: 0;
+    border-left: 5px solid transparent;
+    border-top: 5px solid transparent;
+    height: 100%; /* needed for Firefox */
+}
+
+table.tobago-gridLayout > tbody > tr > td:first-child {
+    border-left: 0;
+}
+
+table.tobago-gridLayout > tbody > tr:first-child > td {
+    border-top: 0;
+}
+
+table.tobago-gridLayout > tbody > tr > td > * {
+  height: 100%;
+  width: 100%;
+}
+
+/* header ----------------------------------------------------------- */
+
+.tobago-header {
+    margin-bottom: 1rem;
+}
+
+.tobago-header.navbar-fixed-top {
+    margin-bottom: 0;
+}
+
+/* image ----------------------------------------------------------- */
+
+.tobago-image-markup-disabled {
+  filter: grayscale(1) blur(2px) contrast(0.5) brightness(1.2);
+}
+
+/* in ----------------------------------------------------------- */
+
+.tobago-in-markup-number {
+  text-align: right;
+}
+
+/* link ----------------------------------------------------------- */
+
+.tobago-link {
+  white-space: nowrap;
+}
+
+.tobago-link span {
+  white-space: normal
+}
+
+button.tobago-link, button.tobago-command, button.tobago-treeCommand {
+  color: #0275d8;
+  border-width: 0;
+  padding: 0;
+  background-color: transparent;
+  text-align: left;
+}
+
+button.tobago-link:focus, button.tobago-link:hover,
+button.tobago-command:focus, button.tobago-command:hover,
+button.tobago-treeCommand:focus, button.tobago-treeCommand:hover {
+  color: #014c8c;
+  text-decoration: underline;
+  background-color: transparent;
+  outline: none;
+}
+
+button.tobago-link-markup-disabled, button.tobago-command-markup-disabled {
+  cursor: not-allowed;
+  opacity: .65;
+}
+
+button.tobago-link-markup-disabled:hover, button.tobago-command-markup-disabled:hover {
+  color: #0275d8;
+  text-decoration: none;
+}
+
+/* messages ----------------------------------------------------------- */
+
+.tobago-messages label {
+  display: block;
+}
+
+.tobago-messages label:last-child {
+  margin-bottom: 0;
+}
+
+/* nav ----------------------------------------------------------- */
+
+.nav-item > span > .tobago-link, .nav-item > span > .tobago-command {
+  padding-top: .425rem;
+  padding-bottom: .425rem;
+  display: inline-block;
+}
+
+/* styles for drop down menu first level */
+.dropdown-toggle:focus, .dropdown-toggle:hover {
+  text-decoration: none;
+}
+
+/* styles for drop down menu with deeper level */
+.tobago-dropdown-submenu {
+  position: relative;
+}
+
+/* no bottom border in navtabs, if panel-body under it */
+.nav-tabs {
+  border-bottom-width: 0;
+}
+
+.nav-tabs > li.active > a {
+  background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
+  background-repeat: repeat-x;
+  border-bottom: #dddddd;
+}
+
+.nav-tabs > li.active > a:hover {
+  border-bottom: #dddddd;
+}
+
+.tobago-dropdown-submenu > span {
+  display: inline-block;
+  width: 100%;
+}
+
+.tobago-dropdown-submenu > span > .dropdown-menu {
+  top: 0;
+  left: 100%;
+  margin-top: -6px;
+  margin-left: -1px;
+  -webkit-border-radius: 6px 6px 6px 6px;
+  -moz-border-radius: 6px 6px 6px 6px;
+  border-radius: 6px 6px 6px 6px;
+}
+
+.tobago-dropdown-submenu:hover > span > .dropdown-menu {
+  display: block;
+}
+
+.tobago-dropdown-submenu:after {
+  content: " ";
+  float: right;
+  border-color: transparent;
+  border-style: solid;
+  border-width: 5px 0 5px 5px;
+  border-left-color: #cccccc;
+  margin-top: 7px;
+  margin-right: -10px;
+}
+
+.tobago-dropdown-submenu > span > button:after {
+  display: none;
+}
+
+.tobago-dropdown-submenu:hover > span > a:after {
+  border-left-color: #ffffff;
+}
+
+.tobago-dropdown-submenu.pull-left {
+  float: none;
+}
+
+.tobago-dropdown-submenu.pull-left > .dropdown-menu {
+  left: -100%;
+  margin-left: 10px;
+  -webkit-border-radius: 6px 0 6px 6px;
+  -moz-border-radius: 6px 0 6px 6px;
+  border-radius: 6px 0 6px 6px;
+}
+
+.dropdown-menu .form-check {
+  display: block;
+}
+
+/* out -------------------------------------------------------------------- */
+
+.tobago-out-markup-strong {
+  font-weight: bold;
+}
+
+.tobago-out-markup-deleted {
+  text-decoration: line-through;
+}
+
+.tobago-out-markup-number {
+  display: block;
+  text-align: right;
+}
+
+/* make sure, tc:out has always the same height, no matter if value is empty */
+span.tobago-out:empty:before {
+  content: "\200b";
+}
+
+/* page ----------------------------------------------------------- */
+
+.tobago-page {
+  padding-top: 1rem;
+}
+
+.tobago-page-overlay {
+  display: table;
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 100%;
+  height: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlay-markup-wait {
+  cursor: wait;
+}
+
+.tobago-page-overlay-markup-error {
+  cursor: default;
+}
+
+.tobago-page-overlayCenter {
+  display: table-cell;
+  text-align: center;
+  vertical-align: middle;
+  width: 100%;
+  /* TODO: better z-index strategy */
+  z-index: 500; /* less than the bootstrap navbar */
+}
+
+.tobago-page-overlayCenter img {
+  position: relative;
+}
+
+.tobago-page-noscript {
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  right: 100px;
+  height: 50px;
+  border: 1px solid black;
+  padding: 30px;
+  background-color: white;
+  font-size: 15px;
+}
+
+.tobago-page-preventFrameAttacks {
+  display: none;
+}
+
+.tobago-spread {
+  height: 100%;
+}
+
+/* popup ------------------------------------------------------------- */
+.modal-content > .card {
+  margin-bottom: 0;
+}
+
+/* section ----------------------------------------------------------- */
+
+/* to separate the icon from the rest of the title */
+h1 > .fa:first-child,
+h2 > .fa:first-child,
+h3 > .fa:first-child,
+h4 > .fa:first-child,
+h5 > .fa:first-child,
+h6 > .fa:first-child {
+  margin-right: 0.7em;
+}
+
+.tobago-section-header {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+}
+
+/* selectBooleanCheckbox ----------------------------------------------- */
+.tobago-selectBooleanCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectBooleanCheckbox .form-check-label {
+  margin-top: 0.5ex;
+  vertical-align: text-top;
+}
+
+/* selectManyCheckbox ----------------------------------------------------------- */
+
+.tobago-selectManyCheckbox {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectManyCheckbox input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectManyCheckbox-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+/* selectManyShuttle ----------------------------------------------------------- */
+
+.tobago-selectManyShuttle {
+  display: flex;
+}
+
+.tobago-selectManyShuttle .tobago-selectManyShuttle-unselected,
+.tobago-selectManyShuttle .tobago-selectManyShuttle-selected {
+  flex: 1 0 0px;
+}
+
+.tobago-selectManyShuttle-hidden {
+  display: none;
+}
+
+.tobago-selectManyShuttle-toolBar {
+  display: flex;
+  flex-direction: column;
+  padding: 0 0.5rem;
+}
+
+.tobago-selectManyShuttle-toolBar > button {
+  display: block;
+}
+
+.tobago-selectManyShuttle-toolBar > div {
+  flex: 1 0 0px;
+}
+
+/* XXX this fixes the margin left from .btn:nth-child(n+2), but is ugly */
+.tobago-selectManyShuttle-toolBar > * {
+  margin-left: 0 !important;
+}
+
+/* selectOneRadio ---------------------------------------------------------- */
+
+.tobago-selectOneRadio {
+  padding-left: 0;
+  list-style: none;
+}
+
+.tobago-selectOneRadio input {
+  margin-right: 0.3em;
+  margin-bottom: 0.4ex;
+  vertical-align: text-bottom;
+}
+
+.tobago-selectOneRadio-inline {
+  margin-left: -1.25rem;
+  margin-top: 6px;
+}
+
+.dropdown-menu .tobago-selectOneRadio > .form-check {
+  display: block;
+}
+
+/* segmentLayout ----------------------------------------------------------- */
+
+.tobago-segmentLayout {
+  /*
+  Makes, that the height of the div is set.
+  Otherwise floating elements below, may flew into the area of the segmentLayout.
+  */
+  /*display: inline-block;
+  todo: this breaks the general layout in IE11 and others
+  */
+}
+
+/* separator -------------------------------------------------------------- */
+hr.tobago-separator {
+  border-top: 1px solid rgba(0, 0, 0, 0.1);
+}
+
+p.tobago-separator {
+  text-align: center;
+  border: 0;
+  white-space: nowrap;
+  display: block;
+  overflow: hidden;
+  padding: 0;
+  margin-top: 1em;
+  margin-bottom: 1em;
+}
+
+p.tobago-separator:before, p.tobago-separator:after {
+  content: "";
+  height: 1px;
+  background-color: rgba(0, 0, 0, 0.1);
+  display: inline-block;
+  vertical-align: middle;
+}
+
+p.tobago-separator:before {
+  width: 80px;
+  margin-left: 0;
+  margin-right: 5px;
+}
+
+p.tobago-separator:after {
+  width: 100%;
+  margin-left: 5px;
+  margin-right: 0;
+}
+
+/* sheet -------------------------------------------------------------- */
+
+th.tobago-sheet-headerCell {
+  font-weight: normal;
+}
+
+th.tobago-sheet-headerCell .tobago-out {
+  font-weight: bold;
+}
+
+.tobago-sheet-header {
+  overflow: hidden;
+  flex-shrink: 0;
+}
+
+.tobago-sheet {
+  display: flex;
+  flex-direction: column;
+}
+
+.tobago-sheet-cell-markup-right {
+  text-align: right;
+}
+
+.tobago-sheet-cell-markup-center {
+  text-align: center;
+}
+
+.tobago-sheet-cell-markup-justify {
+  text-align: justify;
+}
+
+.tobago-sheet-cell-markup-filler {
+  padding: 0 !important; /* fix for IE 11 */
+}
+
+.tobago-sheet-footer {
+  text-align: center;
+}
+
+.tobago-sheet-paging-markup-left {
+  float: left;
+}
+.tobago-sheet-paging-markup-center {
+}
+
+.tobago-sheet-paging-markup-right {
+  float:right;
+}
+
+.tobago-sheet-pagingInput {
+  text-align: center;
+  display: none;
+  margin: -4px 0;
+  width: 3em;
+}
+
+.tobago-sheet-pagingText {
+  cursor: pointer;
+}
+
+.tobago-sheet-body {
+  overflow-y: auto;
+  flex: 1 1 auto;
+}
+
+.tobago-sheet-headerTable {
+  margin-bottom: 0;
+}
+
+.tobago-tableLayout-fixed {
+  table-layout: fixed;
+}
+
+.tobago-sheet-headerCell-markup-filler {
+  border-width: 0 !important;
+}
+
+.tobago-sheet-headerCell {
+  position: relative;
+}
+
+.tobago-sheet-headerResize {
+  position: absolute;
+  right: -5px;
+  top: 0;
+  width: 10px;
+  height: 100%;
+  z-index: 1;
+  cursor: col-resize;
+}
+
+.tobago-sheet-headerCell {
+  overflow: hidden;
+}
+
+.tobago-sheet-cell div {
+  overflow: hidden;
+}
+
+/* suggest ---------------------------------------------------------------------- */
+
+.tobago-suggest {
+  display: none;
+}
+
+.twitter-typeahead {
+  width: 100%;
+  display: inherit !important; /* height of tc:in must not be influenced by tc:suggest */
+}
+
+.typeahead {
+  background-color: #FFFFFF;
+}
+
+.typeahead:focus {
+  border: 2px solid #0097CF;
+}
+
+.tt-query {
+  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset;
+}
+
+.tt-hint {
+  color: #aaaaaa;
+}
+
+.tt-menu {
+  display: none;
+  position: absolute;
+  z-index: 100;
+  background-color: #FFFFFF;
+  border: 1px solid rgba(0, 0, 0, 0.2);
+  border-radius: 3px;
+  box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+  margin-top: 1px;
+  padding: 8px 0;
+}
+
+.tt-open {
+  display: block;
+}
+
+.tt-empty {
+  display: none;
+}
+
+.tt-suggestion {
+    padding: 3px 20px;
+}
+
+.tt-suggestion:hover {
+    background-color: #0097CF;
+    color: #FFFFFF;
+    cursor: pointer;
+}
+
+.tt-suggestion.tt-cursor {
+  background-color: #0097CF;
+  color: #FFFFFF;
+}
+
+.tt-suggestion p {
+  margin: 0;
+}
+
+/* tab / tab-group ----------------------------------------------------------------- */
+
+.tobago-tab {
+  display: flex;
+  justify-content: space-between;
+  align-content: center;
+  margin-left: 0.2rem;
+}
+
+.tab-content {
+  border: 1px solid #ddd;
+  border-radius: 0.25rem;
+  padding: 0.3rem;
+}
+
+.tobago-tabGroup > .tobago-tabGroup-header.nav-tabs {
+  border-bottom-width: 0;
+}
+
+/* tree ---------------------------------------------------------------------- */
+
+.tobago-treeCommand {
+  cursor: pointer;
+}
+
+/* out -------------------------------------------------------------- */
+
+.tobago-out {
+  display: inline-block;
+}
+
+/* menuStore -------------------------------------------------------- */
+
+.tobago-page-menuStore {
+  position: absolute;
+  top: 0;
+  left: 0;
+  width: 0;
+  height: 0;
+}
+
+/* Bootstrap workarounds ------------------------------------------------------------------ */
+
+/* fixes the problem, that input controls have 100% in the toolbar if they are not in a form,
+ but in Tobago we have a global form.
+ */
+/*
+.navbar .form-control {
+    width: auto;
+}
+*/
+
+/*
+fixes missing space, I thinks normal Websites have a " " Space char in the source code, Tobago not.
+
+fixme: there is a problem with the selectManyShuttle with this style.
+*/
+.navbar button:nth-child(n+2),
+.navbar input:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.btn:nth-child(n+2) {
+  margin-left: 5px;
+}
+
+.tobago-button > *:nth-child(n+2),
+.tobago-link > *:nth-child(n+2) {
+  margin-left: .4em;
+}
+
+.tobago-label {
+  width: 155px;
+}
+
+/* fixes vertical space, todo: why is is needed? is there a better way? */
+.form-horizontal > * {
+  margin-top: 10px;
+  margin-bottom: 5px;
+  /* XXX MUST BE REMOVED */
+}.form-horizontal .control-label {
+   margin-top: 10px;
+   margin-bottom: 5px;
+ }
+/* FIXME: This is to hide the toolbar, until it is implemented */
+.tobago-tabGroup-toolBar {
+  display: none;
+}
+
+.tobago-has-info .form-control-feedback,
+.tobago-has-info .form-control-label,
+.tobago-has-info .form-check-label,
+.tobago-has-info .form-check-inline,
+.tobago-has-info .custom-control {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control {
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .input-group-addon {
+  color: #5bc0de;
+  background-color: #eaf6ea;
+  border-color: #5bc0de;
+}
+
+.tobago-has-info .form-control-feedback {
+  color: #5bc0de;
+}
+
+.tobago-has-info .form-control-success {
+  background-image: url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2MTIgNzkyIj48cGF0aCBmaWxsPSIjNWNiODVjIiBkPSJNMjMzLjggNjEwYy0xMy4zIDAtMjYtNi0zNC0xNi44TDkwLjUgNDQ4LjhDNzYuMyA0MzAgODAgNDAzLjMgOTguOCAzODljMTguOC0xNC4yIDQ1LjUtMTAuNCA1OS44IDguNGw3MiA5NUw0NTEuMyAyNDJjMTIuNS0yMCAzOC44LTI2LjIgNTguOC0xMy43IDIwIDEyLjQgMjYgMzguNyAxMy43IDU4LjhMMjcwIDU5MGMtNy40IDEyLTIwLjIgMTkuNC0zNC4zIDIwaC0yeiIvPjwvc3ZnPg==");
+}
+
+.tobago-required .tobago-label:after {
+  content:"*";
+  color:red;
+}
+
+/* Bootstrap datetimepicker workarounds ------------------------------------------------------------------ */
+
+/*
+ * CSS extension for bootstrap3-datetimepicker to fit with bootstrap4.
+ */
+
+.bootstrap-datetimepicker-widget th,
+.bootstrap-datetimepicker-widget td {
+  padding: 5px;
+}
diff --git a/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/CssClassCompareUnitTest.java b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/CssClassCompareUnitTest.java
new file mode 100644
index 0000000..8419fd6
--- /dev/null
+++ b/tobago-3.0.x/tobago-theme/tobago-theme-standard/src/test/java/org/apache/myfaces/tobago/renderkit/html/CssClassCompareUnitTest.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.renderkit.html;
+
+import org.apache.myfaces.tobago.internal.config.AbstractTobagoTestBase;
+import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
+import org.apache.myfaces.tobago.renderkit.css.CssItem;
+import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+/**
+ * Test if every in Java declared CSS class has really an entry in a CSS file.
+ */
+public class CssClassCompareUnitTest extends AbstractTobagoTestBase {
+
+  private static final Logger LOG = LoggerFactory.getLogger(CssClassCompareUnitTest.class);
+
+  /**
+   * This test checks, if every item of the {@link BootstrapClass} occurs in the bootstrap.css.
+   */
+  @Test
+  public void testCompareBootstrapCss() throws FileNotFoundException {
+    File bootstrapCss = new File(
+        "src/main/resources/META-INF/resources/tobago/standard/bootstrap/4.0.0-alpha.5/css/bootstrap.css");
+    compareCss(bootstrapCss, BootstrapClass.values());
+  }
+
+  /**
+   * This test checks, if every item of the {@link TobagoClass} occurs in the _tobago.scss.
+   */
+  @Test
+  public void testCompareTobagoCss() throws FileNotFoundException {
+    File tobagoCss = new File(
+        "src/main/scss/_tobago.scss");
+
+    List<CssItem> classNames = new ArrayList<CssItem>();
+    for (TobagoClass value : TobagoClass.values()) {
+      if (!value.getName().startsWith("tobago-")) {
+        classNames.add(value);
+      }
+    }
+
+    compareCss(tobagoCss, classNames.toArray(new CssItem[classNames.size()]));
+  }
+
+  private void compareCss(File cssFile, CssItem[] cssItems) throws FileNotFoundException {
+    Assert.assertTrue(cssFile.exists());
+
+    String fileContent = new Scanner(cssFile).useDelimiter("\\Z").next();
+
+    for (CssItem cssItem : cssItems) {
+      final String className = cssItem.getName();
+
+      Assert.assertTrue("'" + className + "' exist in " + cssItem.getClass().getName() + " but not in "
+              + cssFile.getName(),
+          containsClassName(fileContent, className));
+    }
+  }
+
+  private boolean containsClassName(String content, String className) {
+    return content.contains("." + className + " ")
+        || content.contains("." + className + "{")
+        || content.contains("." + className + ",")
+        || content.contains("." + className + ":")
+        || content.contains("." + className + ".")
+        || content.contains("." + className + ">");
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/pom.xml b/tobago-3.0.x/tobago-tool/pom.xml
new file mode 100644
index 0000000..4688a68
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.e.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <packaging>pom</packaging>
+  <name>Tobago Tool</name>
+  <artifactId>tobago-tool</artifactId>
+
+  <modules>
+    <module>tobago-tool-apt</module>
+    <module>tobago-tool-annotation</module>
+  </modules>
+
+</project>
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/pom.xml b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/pom.xml
new file mode 100644
index 0000000..eb5a791
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-tool</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-tool-annotation</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Tool Annotation</name>
+</project>
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/appended-resouces/META-INF/NOTICE b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/appended-resouces/META-INF/NOTICE
new file mode 100644
index 0000000..b1db76e
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/appended-resouces/META-INF/NOTICE
@@ -0,0 +1,3 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Behavior.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Behavior.java
new file mode 100644
index 0000000..a27f01a
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Behavior.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface Behavior {
+  String name();
+  String description() default "";
+  boolean isDefault() default false;
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/BodyContentDescription.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/BodyContentDescription.java
new file mode 100644
index 0000000..6090609
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/BodyContentDescription.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface BodyContentDescription {
+
+  String anyTagOf() default "";
+  String contentType() default "";
+
+  // TODO should be Class see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5089128
+  String [] anyClassOf() default {};
+
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Category.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Category.java
new file mode 100644
index 0000000..fb01412
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Category.java
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+public enum Category {
+  
+  GENERAL, DATA, APPEARANCE, EVENT, ADVANCED;
+
+  public String toString() {
+    return this.name();
+
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Converter.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Converter.java
new file mode 100644
index 0000000..2fbce55
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Converter.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface Converter {
+  String id() default "";
+  String forClass() default "";
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/DynamicExpression.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/DynamicExpression.java
new file mode 100644
index 0000000..c77c474
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/DynamicExpression.java
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+public enum DynamicExpression {
+
+  VALUE_EXPRESSION(false, true, false),
+  VALUE_EXPRESSION_REQUIRED(true, true, false),
+  METHOD_EXPRESSION(false, false, true),
+  METHOD_EXPRESSION_REQUIRED(true, false, true),
+  PROHIBITED(false, false, false),
+  /** @deprecated since 2.0.0 */
+  @Deprecated
+  VALUE_BINDING(false, true, false),
+  /** @deprecated since 2.0.0 */
+  @Deprecated
+  VALUE_BINDING_REQUIRED(true, true, false),
+  /** @deprecated since 2.0.0 */
+  @Deprecated
+  METHOD_BINDING(false, false, true),
+  /** @deprecated since 2.0.0 */
+  @Deprecated
+  METHOD_BINDING_REQUIRED(true, false, true);
+
+  private boolean required;
+  private boolean valueExpression;
+  private boolean methodExpression;
+
+  DynamicExpression(final boolean required, final boolean valueExpression, final boolean methodExpression) {
+    this.required = required;
+    this.valueExpression = valueExpression;
+    this.methodExpression = methodExpression;
+  }
+
+  public boolean isRequired() {
+    return required;
+  }
+
+  public boolean isValueExpression() {
+    return valueExpression;
+  }
+
+  public boolean isMethodExpression() {
+    return methodExpression;
+  }
+
+  public String toMetaDataString() {
+    switch (this) {
+      case VALUE_EXPRESSION:
+      case VALUE_BINDING:
+        return "ALLOWED";
+      case METHOD_EXPRESSION:
+      case METHOD_BINDING:
+        return "ALLOWED";
+      case VALUE_EXPRESSION_REQUIRED:
+      case VALUE_BINDING_REQUIRED:
+        return "REQUIRED";
+      case METHOD_EXPRESSION_REQUIRED:
+      case METHOD_BINDING_REQUIRED:
+        return "REQUIRED";
+      case PROHIBITED:
+        return "PROHIBITED";
+      default:
+        throw new IllegalStateException("Unexpected DynamicExpression " + name());      
+    }
+  }
+
+  public String toString() {
+    switch (this) {
+      case VALUE_EXPRESSION:
+      case VALUE_BINDING:
+        return "VB";
+      case VALUE_EXPRESSION_REQUIRED:
+      case VALUE_BINDING_REQUIRED:
+        return "VB";
+      case METHOD_EXPRESSION:
+      case METHOD_BINDING:
+        return "MB";
+      case METHOD_EXPRESSION_REQUIRED:
+      case METHOD_BINDING_REQUIRED:
+        return "MB";
+      case PROHIBITED:
+        return "NONE";
+      default:
+        throw new IllegalStateException("Unexpected DynamicExpression " + name());
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ExtensionTag.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ExtensionTag.java
new file mode 100644
index 0000000..4daa838
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ExtensionTag.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface ExtensionTag {
+
+  String baseClassName();
+
+  String componentType() default "org.apache.myfaces.tobago.ExtensionPanel";
+
+  String rendererType() default "Panel";
+
+  String faceletHandler();
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Facet.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Facet.java
new file mode 100644
index 0000000..16589eb
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Facet.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface Facet {
+  String name();
+  String description() default "";
+
+  /**
+    * Array of supported component-types that explictly enumerates the
+    * set of allowd component children for this component. Other possible values are: ALL...
+   */
+  String [] allowedChildComponenents() default { "ALL" };
+
+  /**
+   * Specifies whether this component should be available on a component palette.
+   */
+  boolean isHidden() default false;
+
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Preliminary.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Preliminary.java
new file mode 100644
index 0000000..b8e301f
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Preliminary.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Mark the code as 'Preliminary'.
+ * The interface maybe subject to changed in a future version.
+ *
+ */
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface Preliminary {
+  String value() default "";
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/SimpleTag.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/SimpleTag.java
new file mode 100644
index 0000000..cbb3dac
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/SimpleTag.java
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(value = RetentionPolicy.SOURCE)
+public @interface SimpleTag {
+  String faceletHandler();
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Tag.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Tag.java
new file mode 100644
index 0000000..17aeb53
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Tag.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface Tag {
+
+  String name();
+
+  /**
+   * Currently not used.
+   * TBD: is there a way to use this with Facelets? In the handler...
+   */
+  String tagExtraInfoClassName() default "";
+
+  String deprecatedName() default "";
+
+  boolean isBodyTag() default false; 
+
+}
+
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/TagAttribute.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/TagAttribute.java
new file mode 100644
index 0000000..a67598b
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/TagAttribute.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.METHOD)
+
+public @interface TagAttribute {
+  /** type of the Tag  */
+  String type() default "java.lang.String";
+
+  /** allow JSP expression */
+  boolean rtexprvalue() default false;
+
+  boolean required() default false;
+
+  String name() default "";
+
+  boolean bodyContent() default false;
+
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Taglib.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Taglib.java
new file mode 100644
index 0000000..5e2968e
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Taglib.java
@@ -0,0 +1,37 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.PACKAGE)
+
+public @interface Taglib {
+
+  String shortName();
+  String uri();
+  String name();
+  String displayName();
+  String [] listener() default {};
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/UIComponentTag.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/UIComponentTag.java
new file mode 100644
index 0000000..72347b0
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/UIComponentTag.java
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+
+public @interface UIComponentTag {
+
+  String uiComponent();
+
+  String uiComponentBaseClass() default "javax.faces.component.UIComponentBase";
+
+  String uiComponentFacesClass() default "javax.faces.component.UIComponentBase";
+
+  String componentType() default "";
+
+  String componentFamily() default "";
+
+  String rendererType() default "";
+
+  String faceletHandler() default "org.apache.myfaces.tobago.facelets.TobagoComponentHandler";
+
+  String displayName() default "";
+
+  String[] interfaces() default {};
+
+  Facet[] facets() default {};
+
+  Behavior[] behaviors() default {};
+
+  boolean generate() default true;
+
+  boolean isComponentAlreadyDefined() default false;
+
+  /**
+   * Array of supported component-types that explicitly enumerates the
+   * set of allowed component children for this component. Other possible values are: ALL...
+   */
+  String [] allowedChildComponenents() default { "ALL" };
+
+  /**
+   * Specifies the category of a component palette.
+   */
+  Category category() default Category.GENERAL;
+
+  /**
+   * Specifies whether this component should be available on a component palette.
+   */
+  boolean isHidden() default false;
+
+
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/UIComponentTagAttribute.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/UIComponentTagAttribute.java
new file mode 100644
index 0000000..b0177c8
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/UIComponentTagAttribute.java
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.METHOD)
+
+public @interface UIComponentTagAttribute {
+
+  /** type of attribute in the UIComponent */
+  String[] type() default {"java.lang.String"};
+
+  String[] allowedValues() default { };
+
+  /** allow faces expression language, e.g. #{bean}  */
+  DynamicExpression expression() default DynamicExpression.VALUE_EXPRESSION;
+
+  String[] methodSignature() default { };
+
+  String methodReturnType() default "void";
+
+  String defaultValue() default "";
+
+  String defaultCode() default "";
+
+  String displayName() default "";
+
+  /**
+   * Specifies whether this property should be visible
+   * in a property editor
+   */
+  boolean isHidden() default false;
+
+  /**
+   * Specifies whether this property should be read-only
+   * in a property editor
+   */
+  boolean isReadOnly() default false;
+
+  boolean isTransient() default false;
+
+  boolean generate() default true;
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Validator.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Validator.java
new file mode 100644
index 0000000..9a56915
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/Validator.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(value = RetentionPolicy.SOURCE)
+@Target(value = ElementType.TYPE)
+public @interface Validator {
+  String id() default "";
+  String forClass() default "";
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ValidatorTag.java b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ValidatorTag.java
new file mode 100644
index 0000000..a206ca7
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-annotation/src/main/java/org/apache/myfaces/tobago/apt/annotation/ValidatorTag.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(value = RetentionPolicy.SOURCE)
+public @interface ValidatorTag {
+  String validatorId();
+  String faceletHandler() default "";
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/pom.xml b/tobago-3.0.x/tobago-tool/tobago-tool-apt/pom.xml
new file mode 100644
index 0000000..f80578f
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/pom.xml
@@ -0,0 +1,119 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.myfaces.tobago</groupId>
+    <artifactId>tobago-tool</artifactId>
+    <version>3.0.3</version>
+  </parent>
+  <artifactId>tobago-tool-apt</artifactId>
+  <packaging>jar</packaging>
+  <name>Tobago Tool Apt</name>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>animal-sniffer-maven-plugin</artifactId>
+        <configuration>
+          <signature>
+            <groupId>org.codehaus.mojo.signature</groupId>
+            <!-- the apt works only with 1.6 and higher, but that's okay, because it's needed for Tobago at runtime -->
+            <artifactId>java16</artifactId>
+            <version>1.0</version>
+          </signature>
+        </configuration>
+      </plugin>
+    </plugins>
+  </build>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.myfaces.core</groupId>
+      <artifactId>myfaces-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.myfaces.tobago</groupId>
+      <artifactId>tobago-tool-annotation</artifactId>
+      <version>${project.version}</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>ant</groupId>
+      <artifactId>ant</artifactId>
+      <version>1.6.2</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.modello</groupId>
+      <artifactId>modello-plugin-java</artifactId>
+      <version>1.5</version>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-utils</artifactId>
+      <version>2.0.6</version>
+    </dependency>
+    <dependency>
+      <groupId>org.antlr</groupId>
+      <artifactId>stringtemplate</artifactId>
+      <version>3.0</version>
+    </dependency>
+    <dependency>
+      <groupId>jdom</groupId>
+      <artifactId>jdom</artifactId>
+      <version>1.0</version>
+    </dependency>
+    <dependency>
+      <groupId>jaxen</groupId>
+      <artifactId>jaxen</artifactId>
+      <version>1.1</version>
+      <exclusions>
+        <exclusion>
+          <groupId>dom4j</groupId>
+          <artifactId>dom4j</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>xerces</groupId>
+          <artifactId>xmlParserAPIs</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>xerces</groupId>
+          <artifactId>xercesImpl</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>xom</groupId>
+          <artifactId>xom</artifactId>
+        </exclusion>
+      </exclusions>
+    </dependency>
+  </dependencies>
+</project>
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/appended-resouces/META-INF/NOTICE b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/appended-resouces/META-INF/NOTICE
new file mode 100644
index 0000000..b1db76e
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/appended-resouces/META-INF/NOTICE
@@ -0,0 +1,3 @@
+Based on source code originally developed by
+Atanion GmbH (http://www.atanion.com/)
+Copyright 2002-2005 Atanion GmbH.
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/AnnotationUtils.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/AnnotationUtils.java
new file mode 100644
index 0000000..222b941
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/AnnotationUtils.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt;
+
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+
+import javax.lang.model.element.TypeElement;
+
+public final class AnnotationUtils {
+
+  private AnnotationUtils() {
+  }
+
+  public static String componentType(final UIComponentTag componentTag) {
+    final String s = componentTag.componentType();
+    if (s != null && s.length() > 0) {
+      return s;
+    } else {
+      return componentTag.uiComponent().replace(".component.UI", ".");
+    }
+  }
+
+  public static String generatedTagName(final TypeElement typeElement) {
+    final String s = typeElement.getQualifiedName().toString();
+    return s.replace(".component.", ".");
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ClassInfo.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ClassInfo.java
new file mode 100644
index 0000000..b43b7b0
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ClassInfo.java
@@ -0,0 +1,92 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+public class ClassInfo {
+  private String className;
+  private String packageName;
+  private Imports imports;
+  private String superClassName;
+  private Set<String> interfaces = new HashSet<String>();
+  private String sourceClass;
+
+  public ClassInfo(final String sourceClass, final String qualifiedName) {
+    this.sourceClass = sourceClass;
+    this.className = ClassUtils.getSimpleName(qualifiedName);
+    this.packageName = ClassUtils.getPackageName(qualifiedName);
+    imports = new Imports(packageName);
+  }
+
+  public String getClassName() {
+    return className;
+  }
+
+  public String getPackageName() {
+    return packageName;
+  }
+
+  public void setSuperClass(final String qualifiedName) {
+    final String name = ClassUtils.getSimpleName(qualifiedName);
+    if (!name.equals(className)) {
+      imports.addImport(qualifiedName);
+      this.superClassName = name;
+    } else {
+      this.superClassName = qualifiedName;
+    }
+  }
+
+  public String getSuperClassName() {
+    return superClassName;
+  }
+
+  public boolean hasSuperClass() {
+    return superClassName != null && superClassName.length() > 0;
+  }
+
+  public void addImport(final String qualifiedName) {
+    imports.addImport(qualifiedName);
+  }
+
+  public Set<String> getImports() {
+    return imports.getImports();
+  }
+
+  public void addInterface(final String qualifiedName) {
+    final String name = ClassUtils.getSimpleName(qualifiedName);
+    if (!name.equals(className)) {
+      imports.addImport(qualifiedName);
+      this.interfaces.add(name);
+    } else {
+      this.interfaces.add(qualifiedName);
+    }
+  }
+
+  public Set<String> getInterfaces() {
+    return interfaces;
+  }
+
+  public String getSourceClass() {
+    return sourceClass;
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ClassUtils.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ClassUtils.java
new file mode 100644
index 0000000..fc48718
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ClassUtils.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+import java.util.HashMap;
+import java.util.Map;
+
+public class ClassUtils {
+
+  private static final Map<String, Class> PRIMITIVE_MAP;
+
+  static {
+    PRIMITIVE_MAP = new HashMap<String, Class>(8);
+    PRIMITIVE_MAP.put("boolean", Boolean.class);
+    PRIMITIVE_MAP.put("byte", Byte.class);
+    PRIMITIVE_MAP.put("char", Character.class);
+    PRIMITIVE_MAP.put("short", Short.class);
+    PRIMITIVE_MAP.put("int", Integer.class);
+    PRIMITIVE_MAP.put("long", Long.class);
+    PRIMITIVE_MAP.put("float", Float.class);
+    PRIMITIVE_MAP.put("double", Double.class);
+  }
+
+  private ClassUtils() {
+  }
+
+  public static String getPackageName(final String qualifiedName) {
+    final int pos = qualifiedName.lastIndexOf('.');
+    if (pos != -1) {
+      return qualifiedName.substring(0, pos);
+    }
+    return null;
+  }
+
+  public static String getSimpleName(final String qualifiedName) {
+    final int pos = qualifiedName.lastIndexOf('.');
+    if (pos != -1) {
+      return qualifiedName.substring(pos + 1);
+    }
+    return null;
+  }
+
+  public static boolean isSystemClass(final String qualifiedClassName) {
+    return qualifiedClassName.startsWith("java.lang.");
+  }
+
+  public static boolean isPrimitive(final String name) {
+    return PRIMITIVE_MAP.containsKey(name);
+  }
+
+  public static Class getWrapper(final String primitive) {
+    return PRIMITIVE_MAP.get(primitive);
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ComponentInfo.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ComponentInfo.java
new file mode 100644
index 0000000..10078aa
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ComponentInfo.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+import org.apache.myfaces.tobago.apt.AnnotationUtils;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+
+import javax.lang.model.element.TypeElement;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ComponentInfo extends TagInfo {
+  private List<PropertyInfo> nonTransientProperties = new ArrayList<PropertyInfo>();
+  private List<PropertyInfo> transientProperties = new ArrayList<PropertyInfo>();
+  private boolean messages;
+  private String description;
+  private boolean deprecated;
+  private int index = 0;
+  private int nonTransientIndex = 0;
+  private List<String> behaviors = new ArrayList<String>();
+  private String defaultBehavior;
+
+  public ComponentInfo(final TypeElement declaration, final UIComponentTag componentTag) {
+    super(declaration.getQualifiedName().toString(), componentTag.uiComponent(), componentTag.rendererType());
+
+    setComponentType(AnnotationUtils.componentType(componentTag));
+    setComponentFamily(componentTag.componentFamily());
+    setComponentClassName(componentTag.uiComponent());
+  }
+
+  @Deprecated
+  public ComponentInfo(final String sourceClass, final String qualifiedName, final String rendererType) {
+    super(sourceClass, qualifiedName, rendererType);
+  }
+
+  public void addPropertyInfo(final ComponentPropertyInfo propertyInfo) {
+    getProperties().add(propertyInfo);
+    propertyInfo.setIndex(index);
+    index++;
+    if (!propertyInfo.isTransient()) {
+      nonTransientProperties.add(propertyInfo);
+      propertyInfo.setNonTransientIndex(nonTransientIndex);
+      nonTransientIndex++;
+    } else {
+      transientProperties.add(propertyInfo);
+    }
+  }
+
+  public List<PropertyInfo> getNonTransientProperties() {
+    return nonTransientProperties;
+  }
+
+  public List<PropertyInfo> getTransientProperties() {
+    return transientProperties;
+  }
+
+  @Override
+  public int getPropertiesSize() {
+    return index;
+  }
+
+  @Override
+  public int getPropertiesSizePlusOne() {
+    return index + 1;
+  }
+
+  public int getNonTransientPropertiesSize() {
+    return nonTransientIndex;
+  }
+
+  public int getNonTransientPropertiesSizePlusOne() {
+    return nonTransientIndex + 1;
+  }
+
+  public boolean isMessages() {
+    return messages;
+  }
+
+  public void setMessages(final boolean messages) {
+    this.messages = messages;
+  }
+
+  public void setDescription(final String description) {
+    this.description = description;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public void setDeprecated(final boolean deprecated) {
+    this.deprecated = deprecated;
+  }
+
+  public boolean isDeprecated() {
+    return deprecated;
+  }
+
+  public List<String> getBehaviors() {
+    return behaviors;
+  }
+
+  public String getDefaultBehavior() {
+    return defaultBehavior;
+  }
+
+  public void setDefaultBehavior(String defaultBehavior) {
+    this.defaultBehavior = defaultBehavior;
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ComponentPropertyInfo.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ComponentPropertyInfo.java
new file mode 100644
index 0000000..e0f2f38
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/ComponentPropertyInfo.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+public class ComponentPropertyInfo extends PropertyInfo {
+  private int index;
+  private int nonTransientIndex;
+
+  public String getPropertyTemplate() {
+    return getShortTypeProperty() + "Property";
+  }
+
+  public String getPropertySaveStateTemplate() {
+    return getShortTypeProperty() + "SaveStateProperty";
+  }
+
+  public String getPropertyRestoreStateTemplate() {
+    return getShortTypeProperty() + "RestoreStateProperty";
+  }
+
+  public int getIndex() {
+    return index;
+  }
+
+  public void setIndex(final int index) {
+    this.index = index;
+  }
+
+  public int getNonTransientIndex() {
+    return nonTransientIndex;
+  }
+
+  public int getNonTransientIndexPlusOne() {
+    return nonTransientIndex + 1;
+  }
+
+  public void setNonTransientIndex(final int index) {
+    this.nonTransientIndex = index;
+  }
+
+  public int getIndexPlusOne() {
+    return index + 1;
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/Imports.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/Imports.java
new file mode 100644
index 0000000..a0af6ac
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/Imports.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+import java.util.TreeSet;
+import java.util.Set;
+
+
+public class Imports {
+
+  private Set<String> imports = new TreeSet<String>();
+
+  private String packageName;
+
+  public Imports() {
+  }
+
+  public Imports(final String packageName) {
+    this.packageName = packageName;
+  }
+
+  public void addImport(String qualifiedName) {
+    if (!ClassUtils.isSystemClass(qualifiedName) && !ClassUtils.isPrimitive(qualifiedName)) {
+      if (!(packageName != null && packageName.equals(ClassUtils.getPackageName(qualifiedName)))) {
+        final int index = qualifiedName.lastIndexOf('$');
+        if (index != -1) {
+          qualifiedName = qualifiedName.substring(0, index);
+        }
+        if (!imports.contains(qualifiedName)) {
+          imports.add(qualifiedName);
+        }
+      }
+    }
+  }
+
+  public void addImports(final Imports newImports) {
+    for (final String qualifiedName : newImports.imports) {
+      addImport(qualifiedName);
+    }
+  }
+
+  public boolean contains(final String qualifiedClassName) {
+    return imports.contains(qualifiedClassName);
+  }
+
+  public Set<String> getImports() {
+    return imports;
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/PropertyInfo.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/PropertyInfo.java
new file mode 100644
index 0000000..2e1635c
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/PropertyInfo.java
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+import org.apache.commons.lang.StringUtils;
+
+public class PropertyInfo {
+  private String name;
+  private String type;
+  private String[] allowedValues;
+  private String[] methodSignature;
+  private String defaultValue;
+  private String defaultCode;
+  private boolean valueExpressionRequired;
+  private boolean methodExpressionRequired;
+  private boolean literalOnly;
+  private boolean deprecated;
+  private boolean bodyContent;
+  private boolean tagAttribute;
+  private String description;
+  private boolean transientValue;
+  private boolean generate;
+
+  public PropertyInfo() {
+  }
+
+  public PropertyInfo(final String name) {
+    this.name = name;
+  }
+
+  public boolean isBodyContent() {
+    return bodyContent;
+  }
+
+  public void setBodyContent(final boolean bodyContent) {
+    this.bodyContent = bodyContent;
+  }
+
+  public boolean isLiteralOnly() {
+    return literalOnly;
+  }
+
+  public void setLiteralOnly(final boolean literalOnly) {
+    this.literalOnly = literalOnly;
+  }
+
+  public String getTemplate() {
+    if (valueExpressionRequired) {
+      return "ValueExpression";
+    }
+    if (isMethodExpression()) {
+      return getUpperCamelCaseName();
+    }
+    return getShortTypeProperty();
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(final String name) {
+    this.name = name;
+  }
+
+  public String getType() {
+    return type.replace("$", ".");
+  }
+
+  public String getUnmodifiedType() {
+    return type;
+  }
+
+  public String getInternalType() {
+    return "boolean".equals(type) ? Boolean.class.getName() : getType();
+  }
+
+  public boolean isWidthOrHeight() {
+    return "width".equals(name) || "height".equals(name);
+  }
+
+  public void setType(final String type) {
+    this.type = type;
+  }
+
+  public boolean isMethodExpression() {
+    return "javax.el.MethodExpression".equals(type);
+  }
+
+  public String getShortType() {
+    final String shortType = type.substring(type.lastIndexOf('.') + 1, type.length());
+    return shortType.replace("[]", "Array").replace("$", ".");
+  }
+
+  public String getShortTypeProperty() {
+    final String type = getShortType();
+    final int index = type.lastIndexOf('.');
+    if (index != -1) {
+      return type.substring(type.lastIndexOf('.') + 1, type.length());
+    }
+    return type;
+  }
+
+  public String getUpperCamelCaseName() {
+    return StringUtils.capitalize(name);
+  }
+
+  public String getPropertyName() {
+    if (name.equals("for")) {
+      return "forComponent";
+    }
+    return name;
+  }
+
+  public String[] getAllowedValues() {
+    return allowedValues;
+  }
+
+  public void setAllowedValues(final String[] allowdValues) {
+    this.allowedValues = allowdValues;
+  }
+
+  public String[] getMethodSignature() {
+    return methodSignature;
+  }
+
+  public void setMethodSignature(final String[] methodSignature) {
+    this.methodSignature = methodSignature;
+  }
+
+  public String getDefaultValue() {
+    return defaultValue;
+  }
+
+  public void setDefaultValue(final String defaultValue) {
+    this.defaultValue = defaultValue;
+  }
+
+  public void setDeprecated(final boolean deprecated) {
+    this.deprecated = deprecated;
+  }
+
+  public boolean isDeprecated() {
+    return deprecated;
+  }
+
+  public String getDefaultCode() {
+    if (defaultCode == null && defaultValue != null) {
+      if (String.class.getName().equals(type)) {
+        return "\"" + defaultValue + "\"";
+      } else if (Character.class.getName().equals(type)) {
+        return "'" + defaultValue + "'";
+      } else {
+        return defaultValue;
+      }
+    }
+    return defaultCode;
+  }
+
+  public void setDefaultCode(final String defaultCode) {
+    this.defaultCode = defaultCode;
+  }
+
+  public boolean isValueExpressionRequired() {
+    return valueExpressionRequired;
+  }
+
+  public void setValueExpressionRequired(final boolean valueExpressionRequired) {
+    this.valueExpressionRequired = valueExpressionRequired;
+  }
+
+  public boolean isMethodExpressionRequired() {
+    return methodExpressionRequired;
+  }
+
+  public void setMethodExpressionRequired(final boolean methodExpressionRequired) {
+    this.methodExpressionRequired = methodExpressionRequired;
+  }
+
+  public boolean isTagAttribute() {
+    return tagAttribute;
+  }
+
+  public void setTagAttribute(final boolean tagAttribute) {
+    this.tagAttribute = tagAttribute;
+  }
+
+  public PropertyInfo fill(final PropertyInfo info) {
+    info.setName(name);
+    info.setType(type);
+    info.setAllowedValues(allowedValues);
+    info.setDefaultValue(defaultValue);
+    info.setDeprecated(deprecated);
+    info.setMethodSignature(methodSignature);
+    info.setDefaultCode(defaultCode);
+    info.setValueExpressionRequired(valueExpressionRequired);
+    info.setLiteralOnly(literalOnly);
+    info.setMethodExpressionRequired(methodExpressionRequired);
+    info.setTagAttribute(tagAttribute);
+    info.setDescription(description);
+    info.setTransient(transientValue);
+    return info;
+  }
+
+  public boolean equals(final Object o) {
+    if (this == o) {
+      return true;
+    }
+    if (!(o instanceof PropertyInfo)) {
+      return false;
+    }
+
+    final PropertyInfo that = (PropertyInfo) o;
+
+    return name.equals(that.name);
+
+  }
+
+  public int hashCode() {
+    return name.hashCode();
+  }
+
+  public void setDescription(final String description) {
+    this.description = description;
+  }
+
+  public String getDescription() {
+    return description;
+  }
+
+  public boolean isTransient() {
+    return transientValue;
+  }
+
+  public void setTransient(final boolean transientValue) {
+    this.transientValue = transientValue;
+  }
+
+  public boolean isGenerate() {
+    return generate;
+  }
+
+  public void setGenerate(final boolean generate) {
+    this.generate = generate;
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/RendererInfo.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/RendererInfo.java
new file mode 100644
index 0000000..e98fc93
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/RendererInfo.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+public class RendererInfo extends ClassInfo {
+  private String rendererType;
+
+  public RendererInfo(final String sourceClass, final String qualifiedName) {
+    super(sourceClass, qualifiedName);
+  }
+
+  public RendererInfo(final String sourceClass, final String qualifiedName, final String rendererType) {
+    super(sourceClass, qualifiedName);
+    this.rendererType = rendererType;
+  }
+
+  public String getRendererType() {
+    if (rendererType != null && rendererType.length() == 0) {
+      return null;
+    }
+    return rendererType;
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/TagInfo.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/TagInfo.java
new file mode 100644
index 0000000..4febaef
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/generate/TagInfo.java
@@ -0,0 +1,95 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.generate;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+public class TagInfo extends RendererInfo {
+  private List<PropertyInfo> properties = new ArrayList<PropertyInfo>();
+  private String componentClassName;
+  private String componentType;
+  private String componentFamily;
+  private PropertyInfo bodyContent;
+  private boolean checkBodyContent;
+
+  public TagInfo(final String sourceClass, final String qualifiedName, final String rendererType) {
+    super(sourceClass, qualifiedName, rendererType);
+  }
+
+  public TagInfo(final String sourceClass, final String qualifiedName) {
+    super(sourceClass, qualifiedName);
+  }
+
+  public PropertyInfo getBodyContent() {
+    if (!checkBodyContent) {
+      checkBodyContent = true;
+      for (final PropertyInfo info : properties) {
+        if (info.isBodyContent()) {
+          bodyContent = info;
+          break;
+        }
+      }
+    }
+    return bodyContent;
+  }
+
+  public void setBodyContent(final PropertyInfo bodyContent) {
+    this.bodyContent = bodyContent;
+  }
+
+  public List<PropertyInfo> getProperties() {
+    return properties;
+  }
+
+  public int getPropertiesSize() {
+    return properties.size();
+  }
+
+  public int getPropertiesSizePlusOne() {
+    return properties.size() + 1;
+  }
+
+  public void setComponentClassName(final String componentClass) {
+    addImport(componentClass);
+    this.componentClassName = ClassUtils.getSimpleName(componentClass);
+  }
+
+  public String getComponentClassName() {
+    return componentClassName;
+  }
+
+  public String getComponentType() {
+    return componentType;
+  }
+
+  public void setComponentType(final String componentType) {
+    this.componentType = componentType;
+  }
+
+  public String getComponentFamily() {
+    return componentFamily;
+  }
+
+  public void setComponentFamily(final String componentFamily) {
+    this.componentFamily = componentFamily;
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/AbstractGenerator.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/AbstractGenerator.java
new file mode 100644
index 0000000..87aa0fa
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/AbstractGenerator.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.processor;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedSourceVersion;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Set;
+
+@SupportedSourceVersion(SourceVersion.RELEASE_6)
+public abstract class AbstractGenerator extends AbstractProcessor {
+
+  private List<TypeElement> types;
+  private List<PackageElement> packages;
+
+  @Override
+  public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
+
+    info("**********************************************************************************");
+    info("* Starting generator: " + getClass().getName());
+    info("* Number of annotations:   " + annotations.size());
+    for (final TypeElement typeElement : annotations) {
+      info("* Type element: " + typeElement.getQualifiedName());
+    }
+
+    if (annotations.size() == 0) {
+      // TDB Why this case happen?
+      return false;
+    }
+
+    types = new ArrayList<TypeElement>();
+    packages = new ArrayList<PackageElement>();
+    for (final TypeElement element : annotations) {
+      final Collection<? extends Element> elementsAnnotatedWith = roundEnv
+          .getElementsAnnotatedWith(element);
+      for (final Element e : elementsAnnotatedWith) {
+        if (e instanceof TypeElement) {
+          if (!types.contains(e)) { // todo: optimize, O(n^2)?
+            types.add((TypeElement) e);
+          }
+        }
+        if (e instanceof PackageElement) {
+          if (!packages.contains(e)) {
+            packages.add((PackageElement) e);
+          }
+        }
+      }
+    }
+
+    Collections.sort(types, new Comparator<TypeElement>() {
+      @Override
+      public int compare(final TypeElement d1, final TypeElement d2) {
+        return d1.getSimpleName().toString().compareTo(d2.getSimpleName().toString());
+      }
+    });
+
+    configure();
+
+    try {
+      generate();
+    } catch (final Exception e) {
+      error(e);
+    }
+
+    return false;
+  }
+
+  protected abstract void configure();
+
+  protected abstract void generate() throws Exception;
+
+  protected void info(final String message) {
+    processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE,
+        "<" + getClass().getSimpleName() + "> " + message);
+  }
+
+  protected void warn(final String message) {
+    processingEnv.getMessager().printMessage(Diagnostic.Kind.WARNING,
+        "<" + getClass().getSimpleName() + "> " + message);
+  }
+
+  protected void error(final Exception e) {
+    final StringWriter out = new StringWriter();
+    e.printStackTrace(new PrintWriter(out));
+    processingEnv.getMessager().printMessage(Diagnostic.Kind.ERROR,
+        "<" + getClass().getSimpleName() + "> " + e.getMessage() + "\n" + out.toString());
+  }
+
+  public List<TypeElement> getTypes() {
+    return types;
+  }
+
+  public List<PackageElement> getPackages() {
+    return packages;
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java
new file mode 100644
index 0000000..2e08bd7
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGenerator.java
@@ -0,0 +1,350 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.processor;
+
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.myfaces.tobago.apt.AnnotationUtils;
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.Taglib;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.ValidatorTag;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib"})
+@SupportedOptions({
+    CheckstyleConfigGenerator.TARGET_CHECKSTYLE})
+public class CheckstyleConfigGenerator extends AbstractGenerator {
+
+  static final String TARGET_CHECKSTYLE = "targetCheckstyle";
+
+  private Set<String> tagSet = new HashSet<String>();
+
+  private String targetCheckstyle;
+
+  @Override
+  public void configure() {
+    final Map<String, String> options = processingEnv.getOptions();
+    targetCheckstyle = options.get(TARGET_CHECKSTYLE);
+
+    info("Generating the tobago-checkstyle.xml"); // XXX name?
+    info("Options:");
+    info(TARGET_CHECKSTYLE + ": " + targetCheckstyle);
+  }
+
+  @Override
+  public void generate() throws ParserConfigurationException, IOException, TransformerException,
+      ClassNotFoundException {
+    final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+    dbf.setValidating(false);
+    final DocumentBuilder parser = dbf.newDocumentBuilder();
+    final Document document = parser.newDocument();
+    final Element module = document.createElement("module");
+    module.setAttribute("name", "Checker");
+
+    for (final PackageElement packageElement : getPackages()) {
+      final Taglib taglibAnnotation = packageElement.getAnnotation(Taglib.class);
+      createCheckstyleConfig(taglibAnnotation, packageElement, module, document);
+    }
+
+    document.appendChild(module);
+
+    writeCheckstyleConfig(document);
+  }
+
+  private Document createCheckstyleConfig(
+      final Taglib taglibAnnotation, final PackageElement packageElement, final Element module, final Document document)
+      throws ParserConfigurationException, ClassNotFoundException {
+    resetDuplicateList();
+
+    addLib(taglibAnnotation, module, document);
+
+    for (final TypeElement typeElement : getTypes()) {
+      if (processingEnv.getElementUtils().getPackageOf(typeElement).equals(packageElement)) {
+        appendTag(typeElement, taglibAnnotation.shortName(), module, document);
+      }
+    }
+    return document;
+  }
+
+  protected void writeCheckstyleConfig(final Document document) throws IOException, TransformerException {
+    Writer writer = null;
+    try {
+      final String path = "checkstyle-tobago.xml";
+      final String name = (StringUtils.isNotBlank(targetCheckstyle) ? targetCheckstyle + '/' : "") + path;
+      final FileObject resource = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", name);
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
+
+      final TransformerFactory transFactory = TransformerFactory.newInstance();
+      transFactory.setAttribute("indent-number", 2);
+      final Transformer transformer = transFactory.newTransformer();
+      transformer.setOutputProperty(OutputKeys.DOCTYPE_PUBLIC, "-//Puppy Crawl//DTD Check Configuration 1.2//EN");
+      transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "http://www.puppycrawl.com/dtds/configuration_1_2.dtd");
+      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+      transformer.transform(new DOMSource(document), new StreamResult(writer));
+    } finally {
+      IOUtils.closeQuietly(writer);
+    }
+  }
+
+  protected void appendTag(
+      final TypeElement typeElement, final String taglib, final Element parent, final Document document)
+      throws ClassNotFoundException {
+    final Tag annotationTag = typeElement.getAnnotation(Tag.class);
+    if (annotationTag != null) {
+      checkDuplicates(annotationTag.name());
+      // TODO configure replacement
+      final String className;
+      if (typeElement.getAnnotation(SimpleTag.class) != null || typeElement.getAnnotation(ValidatorTag.class) != null) {
+        className = AnnotationUtils.generatedTagName(typeElement);
+      } else if (typeElement.getAnnotation(UIComponentTag.class) != null) {
+        className = "org.apache.myfaces.tobago.internal.taglib." + StringUtils.capitalize(annotationTag.name())
+            + "Tag";
+      } else {
+        throw new RuntimeException("Not supported: " + typeElement.getQualifiedName());
+      }
+      info("Replacing: " + typeElement.getQualifiedName() + " -> " + className);
+      if (typeElement.getAnnotation(Deprecated.class) != null) {
+        addTag(taglib, parent, annotationTag.name(), document);
+      }
+      addAttributes(typeElement, taglib, parent, annotationTag.name(), document);
+      if (annotationTag.deprecatedName() != null && annotationTag.deprecatedName().length() > 0) {
+        addTag(taglib, parent, annotationTag.deprecatedName(), document);
+        addAttributes(typeElement, taglib, parent, annotationTag.name(), document);
+      }
+      addAttributesForTag(typeElement, taglib, parent, annotationTag.name(), document);
+    }
+  }
+
+  protected void addTag(final String taglib, final Element parent, final String tagName, final Document document) {
+
+    final String format = "<" + taglib + ":" + tagName + "\\b";
+    final String message = "The tag '" + tagName + "' is deprecated.";
+
+    final Element tag = createRegexpModule(format, message, document);
+
+    parent.appendChild(tag);
+  }
+
+  private void checkDuplicates(final String tagName) {
+    if (tagSet.contains(tagName)) {
+      throw new IllegalArgumentException("tag with name " + tagName + " already defined!");
+    } else {
+      tagSet.add(tagName);
+    }
+  }
+
+  private void resetDuplicateList() {
+    tagSet = new HashSet<String>();
+  }
+
+  protected void addAttributesForTag(
+      final TypeElement type, final String taglib, final Element parent, final String tagName,
+      final Document document)
+      throws ClassNotFoundException {
+
+    List<String> attributes = new ArrayList<String>();
+    for (final javax.lang.model.element.Element element : getAllMembers(type)) {
+      if (element instanceof ExecutableElement) {
+        final ExecutableElement executableElement = (ExecutableElement) element;
+        if (executableElement.getAnnotation(TagAttribute.class) == null
+            && executableElement.getAnnotation(UIComponentTagAttribute.class) == null) {
+          continue;
+        }
+        final TagAttribute tagAttribute = executableElement.getAnnotation(TagAttribute.class);
+        if (tagAttribute != null) {
+          final String simpleName = executableElement.getSimpleName().toString();
+          if (simpleName.startsWith("set") || simpleName.startsWith("get")) {
+
+            String attributeStr = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
+            if (tagAttribute.name().length() > 0) {
+              attributeStr = tagAttribute.name();
+            }
+            attributes.add(attributeStr);
+          }
+        }
+      }
+    }
+    final String regexp = getRegExpForUndefinedAttributes(taglib, tagName, attributes);
+
+    final String message = "Found an unknown attribute in tag '" + tagName + "'.";
+
+    Element module = createRegexpModule(regexp, message, document);
+    parent.appendChild(module);
+
+    if (taglib.equals("tx")) {
+      final String m2 = "The taglib tx is deprecated, please use tc with labelLayout. Found tag 'tx:" + tagName + "'.";
+      module = createRegexpModule("<" + taglib + ":" + tagName + "\\b", m2, document);
+      parent.appendChild(module);
+    }
+
+  }
+
+  protected void addAttributes(
+      final TypeElement type, final String taglib, final Element tagElement, final String tagName,
+      final Document document)
+      throws ClassNotFoundException {
+
+    for (final javax.lang.model.element.Element element : getAllMembers(type)) {
+      if (element instanceof ExecutableElement) {
+        final ExecutableElement executableElement = (ExecutableElement) element;
+        if (executableElement.getAnnotation(TagAttribute.class) == null
+            && executableElement.getAnnotation(UIComponentTagAttribute.class) == null) {
+          continue;
+        }
+        addAttribute(executableElement, taglib, tagElement, tagName, document);
+      }
+    }
+  }
+
+  protected void addAttribute(
+      final ExecutableElement declaration, final String taglib, final Element parent, final String tagName,
+      final Document document) {
+    final TagAttribute tagAttribute = declaration.getAnnotation(TagAttribute.class);
+    final Deprecated deprecatedAnnotation = declaration.getAnnotation(Deprecated.class);
+    if (tagAttribute != null && deprecatedAnnotation != null) {
+      final String simpleName = declaration.getSimpleName().toString();
+      if (simpleName.startsWith("set") || simpleName.startsWith("get")) {
+
+        String attributeStr = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
+        if (tagAttribute.name().length() > 0) {
+          attributeStr = tagAttribute.name();
+        }
+
+        final String format = "<" + taglib + ":" + tagName + "\\b[^<]*\\b" + attributeStr + "=";
+        final String message = "The attribute '" + attributeStr + "' is deprecated for tag '" + tagName + "'";
+
+        final Element module = createRegexpModule(format, message, document);
+
+        parent.appendChild(module);
+      } else {
+        throw new IllegalArgumentException("Only setter allowed found: " + simpleName);
+      }
+    }
+  }
+
+  private List<? extends javax.lang.model.element.Element> getAllMembers(final TypeElement type) {
+    final List<? extends javax.lang.model.element.Element> members
+        = new ArrayList<javax.lang.model.element.Element>(processingEnv.getElementUtils().getAllMembers(type));
+    Collections.sort(members, new Comparator<javax.lang.model.element.Element>() {
+      @Override
+      public int compare(final javax.lang.model.element.Element d1, final javax.lang.model.element.Element d2) {
+        return d1.getSimpleName().toString().compareTo(d2.getSimpleName().toString());
+      }
+    });
+    return members;
+  }
+
+  private void addLib(final Taglib taglibAnnotation, final Element parent, final Document document) {
+
+    final String shortName = taglibAnnotation.shortName();
+    if (shortName.length() != 2) {
+
+    }
+    final String uri = taglibAnnotation.uri();
+
+    final String format = "(?<!" + shortName + ")=(\"|')" + uri + "(\"|')";
+    final String message = "The taglib declaration is not like 'xmlns:" + shortName + "=\"" + uri + "\"'";
+
+    final Element module = createRegexpModule(format, message, document);
+
+    parent.appendChild(module);
+  }
+
+  protected Element createRegexpModule(final String formatValue, final String messageValue, final Document document) {
+    final Element module = document.createElement("module");
+    module.setAttribute("name", "RegexpMultiline");
+
+    final Element format = document.createElement("property");
+    format.setAttribute("name", "format");
+    format.setAttribute("value", formatValue);
+    module.appendChild(format);
+
+    final Element message = document.createElement("property");
+    message.setAttribute("name", "message");
+    message.setAttribute("value", messageValue);
+    module.appendChild(message);
+
+    final Element severity = document.createElement("property");
+    severity.setAttribute("name", "severity");
+    severity.setAttribute("value", "warning");
+    module.appendChild(severity);
+
+    return module;
+  }
+
+  protected static String getRegExpForUndefinedAttributes(
+      String taglib, String tagName, List<String> attributes) {
+    final StringBuilder builder = new StringBuilder();
+    builder.append("<");
+    builder.append(taglib);
+    builder.append(":");
+    builder.append(tagName);
+    builder.append("(\\s+(");
+    for (String attribute : attributes) {
+      builder.append(attribute);
+      builder.append('|');
+    }
+    builder.append("xmlns:\\w*)=\\\"([^\"=<>]*)\\\")*\\s+(?!(");
+    for (String attribute : attributes) {
+      builder.append(attribute);
+      builder.append('|');
+    }
+    builder.append("xmlns:\\w*|\\W))");
+    return builder.toString();
+  }
+
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/ClassesGenerator.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/ClassesGenerator.java
new file mode 100644
index 0000000..faf6482
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/ClassesGenerator.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.processor;
+
+import org.antlr.stringtemplate.StringTemplate;
+import org.antlr.stringtemplate.StringTemplateGroup;
+import org.apache.commons.io.IOUtils;
+import org.apache.myfaces.tobago.apt.annotation.Behavior;
+import org.apache.myfaces.tobago.apt.annotation.DynamicExpression;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.apt.generate.ClassInfo;
+import org.apache.myfaces.tobago.apt.generate.ComponentInfo;
+import org.apache.myfaces.tobago.apt.generate.ComponentPropertyInfo;
+import org.apache.myfaces.tobago.apt.generate.PropertyInfo;
+
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.faces.component.UIComponent;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeKind;
+import javax.lang.model.type.TypeMirror;
+import javax.tools.FileObject;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.Writer;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTag",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib",
+    "org.apache.myfaces.tobago.apt.annotation.SimpleTag"})
+public class ClassesGenerator extends AbstractGenerator {
+
+  private StringTemplateGroup componentStringTemplateGroup;
+  private Set<String> ignoredProperties;
+
+  @Override
+  public void configure() {
+
+    info("Generating the classes *Component");
+
+    final InputStream componentStream
+        = getClass().getClassLoader().getResourceAsStream("org/apache/myfaces/tobago/apt/component.stg");
+    final Reader componentReader = new InputStreamReader(componentStream);
+    componentStringTemplateGroup = new StringTemplateGroup(componentReader);
+
+    ignoredProperties = new HashSet<String>();
+    ignoredProperties.add("id");
+    ignoredProperties.add("rendered");
+    ignoredProperties.add("binding");
+  }
+
+  @Override
+  public void generate() throws Exception {
+    for (final TypeElement element : getTypes()) {
+      if (element.getAnnotation(UIComponentTag.class) != null) {
+        try {
+          createTagOrComponent(element);
+        } catch (final Exception e) {
+          throw new RuntimeException(
+              "Error during processing of " + element.getAnnotation(UIComponentTag.class).uiComponent(), e);
+        }
+      }
+    }
+  }
+
+  private void createTagOrComponent(final TypeElement declaration) throws IOException, ClassNotFoundException {
+    final UIComponentTag componentTag = declaration.getAnnotation(UIComponentTag.class);
+    final Map<String, PropertyInfo> properties = new HashMap<String, PropertyInfo>();
+    addProperties(declaration, properties);
+
+    if (componentTag.generate()) {
+      final StringTemplate componentStringTemplate = componentStringTemplateGroup.getInstanceOf("component");
+      final ComponentInfo componentInfo = new ComponentInfo(declaration, componentTag);
+      componentInfo.setSuperClass(componentTag.uiComponentBaseClass());
+      componentInfo.setDescription(getDescription(declaration));
+      componentInfo.setDeprecated(declaration.getAnnotation(Deprecated.class) != null);
+      for (final String interfaces : componentTag.interfaces()) {
+        componentInfo.addInterface(interfaces);
+      }
+
+      if (componentTag.behaviors().length > 0) {
+        for (Behavior behavior : componentTag.behaviors()) {
+          info("*************** ----------------------" + componentTag.behaviors().length);
+          info("*************** " + behavior.name());
+          info("*************** " + componentInfo.getBehaviors());
+          componentInfo.getBehaviors().add(behavior.name());
+          if (behavior.isDefault()) {
+            if (componentInfo.getDefaultBehavior() != null) {
+              throw new RuntimeException("defaultBehavior '" + componentInfo.getDefaultBehavior()
+                  + "' will be overwritten with '" + behavior.name()
+                  + "' in component '" + componentInfo.getSourceClass() + "'");
+            }
+            componentInfo.setDefaultBehavior(behavior.name());
+          }
+        }
+        if (componentInfo.getDefaultBehavior() == null) {
+          throw new RuntimeException("defaultBehavior not set in component '" + componentInfo.getSourceClass() + "'");
+        }
+      }
+
+      final Class<? extends UIComponent> facesClass
+          = Class.forName(componentTag.uiComponentFacesClass()).asSubclass(UIComponent.class);
+
+      for (final PropertyInfo info : properties.values()) {
+        final String infoType = info.getType();
+        final String methodName
+            = ((infoType.equals("java.lang.Boolean") || infoType.equals("boolean")) ? "is" : "get")
+            + info.getUpperCamelCaseName();
+
+        boolean generate = info.isGenerate();
+        try {
+          final Method method = facesClass.getMethod(methodName);
+          if (!Modifier.isAbstract(method.getModifiers())) {
+            generate = false;
+          }
+        } catch (final NoSuchMethodException e) {
+          // generate = true
+        }
+        if (generate) {
+          addPropertyToComponent(componentInfo, info);
+        }
+
+      }
+
+      componentStringTemplate.setAttribute("componentInfo", componentInfo);
+      writeFile(componentInfo, componentStringTemplate);
+    }
+  }
+
+  private ComponentPropertyInfo addPropertyToComponent(final ComponentInfo componentInfo, final PropertyInfo info) {
+
+    final ComponentPropertyInfo componentPropertyInfo = (ComponentPropertyInfo) info.fill(new ComponentPropertyInfo());
+    componentInfo.addImport(componentPropertyInfo.getUnmodifiedType());
+    componentInfo.addImport("javax.faces.context.FacesContext");
+    if ("markup".equals(info.getName())) {
+      componentInfo.addInterface("org.apache.myfaces.tobago.component.Visual");
+    }
+    if ("requiredMessage".equals(info.getName())) {
+      componentInfo.setMessages(true);
+    }
+    componentInfo.addPropertyInfo(componentPropertyInfo);
+    return componentPropertyInfo;
+  }
+
+  protected void addProperties(final TypeElement type, final Map<String, PropertyInfo> properties) {
+    addProperties(type.getInterfaces(), properties);
+    addProperties(type.getSuperclass(), properties);
+
+    final List<? extends Element> members = processingEnv.getElementUtils().getAllMembers(type);
+    for (final Element member : members) {
+      if (member instanceof ExecutableElement) {
+        final ExecutableElement executableElement = (ExecutableElement) member;
+        addProperty(executableElement, properties);
+      }
+    }
+  }
+
+  protected void addProperties(
+      final List<? extends TypeMirror> interfaces, final Map<String, PropertyInfo> properties) {
+    for (final TypeMirror typeMirror : interfaces) {
+      addProperties(typeMirror, properties);
+    }
+  }
+
+  protected void addProperties(final TypeMirror typeMirror, final Map<String, PropertyInfo> properties) {
+    if (typeMirror.getKind() != TypeKind.NONE) {
+      addProperties((TypeElement) (processingEnv.getTypeUtils().asElement(typeMirror)), properties);
+    }
+  }
+
+  protected void addProperty(final ExecutableElement declaration, final Map<String, PropertyInfo> properties) {
+    final TagAttribute tagAttribute = declaration.getAnnotation(TagAttribute.class);
+    final UIComponentTagAttribute uiComponentTagAttribute = declaration.getAnnotation(UIComponentTagAttribute.class);
+    if (uiComponentTagAttribute != null) {
+      final String simpleName = declaration.getSimpleName().toString();
+      if (simpleName.startsWith("set") || simpleName.startsWith("get")) {
+        final String name = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
+        if (ignoredProperties.contains(name)) {
+          return;
+        }
+        final PropertyInfo propertyInfo = new PropertyInfo(name);
+        propertyInfo.setAllowedValues(uiComponentTagAttribute.allowedValues());
+        if (tagAttribute != null) {
+          propertyInfo.setBodyContent(tagAttribute.bodyContent());
+          propertyInfo.setTagAttribute(true);
+        }
+        final String type;
+        if (uiComponentTagAttribute.expression().isMethodExpression()) {
+          propertyInfo.setMethodExpressionRequired(true);
+          type = "javax.el.MethodExpression";
+        } else {
+          if (uiComponentTagAttribute.expression() == DynamicExpression.VALUE_EXPRESSION_REQUIRED) {
+            propertyInfo.setValueExpressionRequired(true);
+          } else if (uiComponentTagAttribute.expression() == DynamicExpression.PROHIBITED) {
+            propertyInfo.setLiteralOnly(true);
+          }
+
+          if (uiComponentTagAttribute.type().length > 1) {
+            type = "java.lang.Object";
+          } else {
+            type = uiComponentTagAttribute.type()[0];
+          }
+        }
+        propertyInfo.setType(type);
+        propertyInfo.setDefaultValue(
+            uiComponentTagAttribute.defaultValue().length() > 0 ? uiComponentTagAttribute.defaultValue() : null);
+        propertyInfo.setDefaultCode(
+            uiComponentTagAttribute.defaultCode().length() > 0 ? uiComponentTagAttribute.defaultCode() : null);
+        propertyInfo.setMethodSignature(uiComponentTagAttribute.methodSignature());
+        propertyInfo.setDeprecated(declaration.getAnnotation(Deprecated.class) != null);
+        propertyInfo.setDescription(getDescription(declaration));
+        propertyInfo.setTransient(uiComponentTagAttribute.isTransient());
+        propertyInfo.setGenerate(uiComponentTagAttribute.generate());
+        if (properties.containsKey(name)) {
+          warn("Redefinition of attribute '" + name + "'.");
+        }
+        properties.put(name, propertyInfo);
+      }
+    }
+  }
+
+  private String getDescription(final Element element) {
+    String comment = processingEnv.getElementUtils().getDocComment(element);
+    if (comment != null) {
+      final int index = comment.indexOf('@');
+      if (index != -1) {
+        comment = comment.substring(0, index);
+      }
+      comment = comment.trim();
+      if (comment.length() > 0) {
+        return comment;
+      }
+    }
+    return null;
+  }
+
+  private void writeFile(final ClassInfo info, final StringTemplate stringTemplate) throws IOException {
+    Writer writer = null;
+    try {
+      final FileObject resource = processingEnv.getFiler().createSourceFile(
+          info.getPackageName() + '.' + info.getClassName());
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
+
+      writer.append(stringTemplate.toString());
+    } finally {
+      IOUtils.closeQuietly(writer);
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FacesConfigGenerator.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FacesConfigGenerator.java
new file mode 100644
index 0000000..e15f91f
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/FacesConfigGenerator.java
@@ -0,0 +1,648 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.processor;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.myfaces.tobago.apt.annotation.Converter;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.Validator;
+import org.apache.myfaces.tobago.apt.generate.ComponentInfo;
+import org.codehaus.plexus.util.FileUtils;
+import org.jdom.Attribute;
+import org.jdom.Comment;
+import org.jdom.Document;
+import org.jdom.Namespace;
+import org.jdom.filter.ContentFilter;
+import org.jdom.input.SAXBuilder;
+import org.jdom.output.Format;
+import org.jdom.output.XMLOutputter;
+
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.UIComponentTag",
+    "org.apache.myfaces.tobago.apt.annotation.Facet",
+    "org.apache.myfaces.tobago.apt.annotation.Preliminary",
+    "org.apache.myfaces.tobago.apt.annotation.Converter",
+    "org.apache.myfaces.tobago.apt.annotation.Validator"})
+@SupportedOptions({
+    FacesConfigGenerator.SOURCE_FACES_CONFIG,
+    FacesConfigGenerator.TARGET_FACES_CONFIG})
+public class FacesConfigGenerator extends AbstractGenerator {
+
+  static final String SOURCE_FACES_CONFIG = "sourceFacesConfig";
+  static final String TARGET_FACES_CONFIG = "targetFacesConfig";
+
+  private static final String SEPARATOR = System.getProperty("line.separator");
+  private static final String COMPONENT = "component";
+  private static final String COMPONENT_TYPE = "component-type";
+  private static final String COMPONENT_CLASS = "component-class";
+  private static final String COMPONENT_EXTENSION = "component-extension";
+  private static final String ALLOWED_CHILD_COMPONENTS = "allowed-child-components";
+  private static final String CATEGORY = "category";
+  private static final String DEPRECATED = "deprecated";
+  private static final String HIDDEN = "hidden";
+  private static final String FACET = "facet";
+  private static final String DISPLAY_NAME = "display-name";
+  private static final String DESCRIPTION = "description";
+  private static final String FACET_NAME = "facet-name";
+  private static final String FACET_EXTENSION = "facet-extension";
+  private static final String PROPERTY = "property";
+  private static final String PROPERTY_NAME = "property-name";
+  private static final String PROPERTY_CLASS = "property-class";
+  private static final String PROPERTY_EXTENSION = "property-extension";
+  private static final String VALUE_EXPRESSION = "value-expression"; //UIComponentTagAttribute.valueExpression()
+  private static final String PROPERTY_VALUES = "property-values"; //UIComponentTagAttribute.allowedValues()
+  private static final String READONLY = "read-only";
+  private static final String REQUIRED = "required"; //UITagAttribute.required()
+  private static final String DEFAULT_VALUE = "default-value";
+  private static final String ATTRIBUTE = "attribute";
+  private static final String ATTRIBUTE_NAME = "attribute-name";
+  private static final String ATTRIBUTE_CLASS = "attribute-class";
+  private static final String ATTRIBUTE_EXTENSION = "attribute-extension";
+  private static final String APPLICATION = "application";
+  private static final String FACTORY = "factory";
+  private static final String CONVERTER = "converter";
+  private static final String CONVERTER_ID = "converter-id";
+  private static final String CONVERTER_FOR_CLASS = "converter-for-class";
+  private static final String CONVERTER_CLASS = "converter-class";
+  private static final String VALIDATOR = "validator";
+  private static final String VALIDATOR_ID = "validator-id";
+  private static final String VALIDATOR_FOR_CLASS = "validator-for-class";
+  private static final String VALIDATOR_CLASS = "validator-class";
+  private static final String RENDERER = "renderer";
+  private static final String COMPONENT_FAMILY = "component-family";
+  private static final String RENDER_KIT = "render-kit";
+  private static final String RENDER_KIT_ID = "render-kit-id";
+  private static final String RENDER_KIT_CLASS = "render-kit-class";
+  private static final String RENDERER_TYPE = "renderer-type";
+  private static final String RENDERER_CLASS = "renderer-class";
+  private static final String BEHAVIOR = "behavior";
+  private static final String BEHAVIOR_ID = "behavior-id";
+  private static final String BEHAVIOR_CLASS = "behavior-class";
+  private static final String CLIENT_BEHAVIOR_RENDERER = "client-behavior-renderer";
+  private static final String CLIENT_BEHAVIOR_RENDERER_TYPE = "client-behavior-renderer-type";
+  private static final String CLIENT_BEHAVIOR_RENDERER_CLASS = "client-behavior-renderer-class";
+
+  private static final Set<String> IGNORED_PROPERTIES = new HashSet<String>(Arrays.asList("binding"));
+
+  private String sourceFacesConfigFile;
+  private String targetFacesConfigFile;
+
+  @Override
+  public void configure() {
+    final Map<String, String> options = processingEnv.getOptions();
+    sourceFacesConfigFile = options.get(SOURCE_FACES_CONFIG);
+    targetFacesConfigFile = options.get(TARGET_FACES_CONFIG);
+
+    info("Generating the faces-config.xml");
+    info("Options:");
+    info(SOURCE_FACES_CONFIG + ": " + sourceFacesConfigFile);
+    info(TARGET_FACES_CONFIG + ": " + targetFacesConfigFile);
+  }
+
+  @Override
+  protected void generate() throws Exception {
+    final Document document;
+    Writer writer = null;
+    try {
+      final String content = FileUtils.fileRead(sourceFacesConfigFile);
+      final SAXBuilder builder = new SAXBuilder();
+      document = builder.build(new StringReader(content));
+
+      // Normalise line endings. For some reason, JDOM replaces \r\n inside a comment with \n.
+      normaliseLineEndings(document);
+
+      // rewrite DOM as a string to find differences, since text outside the root element is not tracked
+
+      final org.jdom.Element rootElement = document.getRootElement();
+
+      rootElement.setNamespace(Namespace.getNamespace("http://java.sun.com/xml/ns/javaee"));
+      final Namespace xsi = Namespace.getNamespace("xsi", "http://www.w3.org/2001/XMLSchema-instance");
+      rootElement.addNamespaceDeclaration(Namespace.getNamespace("xi", "http://www.w3.org/2001/XInclude"));
+      rootElement.setAttribute(new Attribute("schemaLocation",
+          "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd", xsi));
+      rootElement.setAttribute("version", "2.0");
+
+      final Namespace namespace = rootElement.getNamespace();
+      applyNamespace(rootElement, namespace);
+      final List<org.jdom.Element> components = rootElement.getChildren(COMPONENT, namespace);
+
+      final List<org.jdom.Element> newComponents = new ArrayList<org.jdom.Element>();
+      final List<org.jdom.Element> newRenderer = new ArrayList<org.jdom.Element>();
+      final List<org.jdom.Element> newConverters = new ArrayList<org.jdom.Element>();
+      final List<org.jdom.Element> newValidators = new ArrayList<org.jdom.Element>();
+
+      for (final TypeElement element : getTypes()) {
+        if (element.getAnnotation(UIComponentTag.class) != null) {
+          addElement(element, newComponents, newRenderer, namespace);
+        } else if (element.getAnnotation(Converter.class) != null) {
+          addConverter(element, newConverters, namespace);
+        } else if (element.getAnnotation(Validator.class) != null) {
+          addValidator(element, newValidators, namespace);
+        }
+      }
+
+      final List<org.jdom.Element> elementsToAdd = new ArrayList<org.jdom.Element>();
+      // sort out duplicates
+      for (final org.jdom.Element newElement : newComponents) {
+        final boolean found = containsElement(components, newElement);
+        if (!found) {
+          elementsToAdd.add(newElement);
+        }
+      }
+      if (!elementsToAdd.isEmpty()) {
+        // if faces-config contains no component section add the components after factory or application
+        final int lastIndex = getIndexAfter(rootElement, COMPONENT, FACTORY, APPLICATION);
+        rootElement.addContent(lastIndex, elementsToAdd);
+      }
+      if (!newRenderer.isEmpty()) {
+        final org.jdom.Element renderKit = new org.jdom.Element(RENDER_KIT, namespace);
+        final org.jdom.Element renderKitId = new org.jdom.Element(RENDER_KIT_ID, namespace);
+        renderKitId.setText("tobago");
+        renderKit.addContent(renderKitId);
+        final org.jdom.Element renderKitClass = new org.jdom.Element(RENDER_KIT_CLASS, namespace);
+        renderKitClass.setText("org.apache.myfaces.tobago.renderkit.TobagoRenderKit");
+        renderKit.addContent(renderKitClass);
+        renderKit.addContent(newRenderer);
+
+        final org.jdom.Element behaviorRender = new org.jdom.Element(CLIENT_BEHAVIOR_RENDERER, namespace);
+        final org.jdom.Element behaviorType = new org.jdom.Element(CLIENT_BEHAVIOR_RENDERER_TYPE, namespace);
+        behaviorType.setText("javax.faces.behavior.Ajax");
+        behaviorRender.addContent(behaviorType);
+        final org.jdom.Element behaviorClass = new org.jdom.Element(CLIENT_BEHAVIOR_RENDERER_CLASS, namespace);
+        behaviorClass.setText("org.apache.myfaces.tobago.internal.renderkit.renderer.TobagoClientBehaviorRenderer");
+        behaviorRender.addContent(behaviorClass);
+        renderKit.addContent(behaviorRender);
+
+        final org.jdom.Element baviorRender2 = new org.jdom.Element(CLIENT_BEHAVIOR_RENDERER, namespace);
+        final org.jdom.Element behaviorType2 = new org.jdom.Element(CLIENT_BEHAVIOR_RENDERER_TYPE, namespace);
+        behaviorType2.setText("org.apache.myfaces.tobago.behavior.Event");
+        baviorRender2.addContent(behaviorType2);
+        final org.jdom.Element behaviorClass2 = new org.jdom.Element(CLIENT_BEHAVIOR_RENDERER_CLASS, namespace);
+        behaviorClass2.setText("org.apache.myfaces.tobago.internal.renderkit.renderer.TobagoClientBehaviorRenderer");
+        baviorRender2.addContent(behaviorClass2);
+        renderKit.addContent(baviorRender2);
+
+        final int last = getIndexAfter(rootElement, CONVERTER, COMPONENT, FACTORY, APPLICATION, BEHAVIOR);
+        rootElement.addContent(last, renderKit);
+      }
+      if (!newConverters.isEmpty()) {
+        final int last = getIndexAfter(rootElement, RENDER_KIT, CONVERTER, COMPONENT, FACTORY, APPLICATION, BEHAVIOR);
+        rootElement.addContent(last, newConverters);
+      }
+      if (!newValidators.isEmpty()) {
+        rootElement.addContent(newValidators);
+      }
+      final FileObject resource = processingEnv.getFiler().createResource(
+          StandardLocation.SOURCE_OUTPUT, "", targetFacesConfigFile);
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
+
+      final StringWriter facesConfig = new StringWriter(1024);
+      final Format format = Format.getPrettyFormat();
+      format.setLineSeparator(SEPARATOR);
+      final XMLOutputter out = new XMLOutputter(format);
+      out.output(document, facesConfig);
+      writer.append(facesConfig.toString());
+
+    } finally {
+      IOUtils.closeQuietly(writer);
+    }
+  }
+
+  private void applyNamespace(final org.jdom.Element parent, final Namespace namespace) {
+    for (final org.jdom.Element element : (List<org.jdom.Element>) parent.getChildren()) {
+      element.setNamespace(namespace);
+      applyNamespace(element, namespace);
+    }
+  }
+
+  private void addConverter(
+      final TypeElement typeElement, final List<org.jdom.Element> newConverters, final Namespace namespace) {
+    final Converter converterAnn = typeElement.getAnnotation(Converter.class);
+    final org.jdom.Element converter = new org.jdom.Element(CONVERTER, namespace);
+    if (converterAnn.id().length() > 0) {
+      final org.jdom.Element converterId = new org.jdom.Element(CONVERTER_ID, namespace);
+      converterId.setText(converterAnn.id());
+      converter.addContent(converterId);
+    } else if (converterAnn.forClass().length() > 0) {
+      final org.jdom.Element converterForClass = new org.jdom.Element(CONVERTER_FOR_CLASS, namespace);
+      converterForClass.setText(converterAnn.forClass());
+      converter.addContent(converterForClass);
+    }
+
+    final org.jdom.Element converterClass = new org.jdom.Element(CONVERTER_CLASS, namespace);
+    converterClass.setText(typeElement.getQualifiedName().toString());
+    converter.addContent(converterClass);
+    newConverters.add(converter);
+  }
+
+  private void addValidator(
+      final TypeElement typeElement, final List<org.jdom.Element> newValidators, final Namespace namespace) {
+    final Validator validatorAnn = typeElement.getAnnotation(Validator.class);
+    final org.jdom.Element validator = new org.jdom.Element(VALIDATOR, namespace);
+    if (validatorAnn.id().length() > 0) {
+      final org.jdom.Element validatorId = new org.jdom.Element(VALIDATOR_ID, namespace);
+      validatorId.setText(validatorAnn.id());
+      validator.addContent(validatorId);
+    } else if (validatorAnn.forClass().length() > 0) {
+      final org.jdom.Element validatorForClass = new org.jdom.Element(VALIDATOR_FOR_CLASS, namespace);
+      validatorForClass.setText(validatorAnn.forClass());
+      validator.addContent(validatorForClass);
+    }
+
+    final org.jdom.Element validatorClass = new org.jdom.Element(VALIDATOR_CLASS, namespace);
+    validatorClass.setText(typeElement.getQualifiedName().toString());
+    validator.addContent(validatorClass);
+    newValidators.add(validator);
+  }
+
+  private boolean containsElement(final List<org.jdom.Element> components, final org.jdom.Element newElement) {
+    return getEqualElement(components, newElement) != null;
+  }
+
+  private org.jdom.Element getEqualElement(final List<org.jdom.Element> components, final org.jdom.Element newElement) {
+    for (final org.jdom.Element element : components) {
+      if (equals(element, newElement)) {
+        return element;
+      }
+    }
+    return null;
+  }
+
+  private int getIndexAfter(final org.jdom.Element rootElement, final String... tagNames) {
+    for (final String tagName : tagNames) {
+      final int index = getIndexAfter(rootElement, tagName);
+      if (index != 0) {
+        return index;
+      }
+    }
+    return 0;
+  }
+
+  private int getIndexAfter(final org.jdom.Element rootElement, final String tagName) {
+    final List<org.jdom.Element> components = rootElement.getChildren(tagName, rootElement.getNamespace());
+    if (!components.isEmpty()) {
+      return rootElement.indexOf(components.get(components.size() - 1)) + 1;
+    }
+    return 0;
+  }
+
+  public boolean equals(final org.jdom.Element element1, final org.jdom.Element element2) {
+    final Namespace namespace = element1.getNamespace();
+    if (element1.getName().equals(element2.getName()) && element1.getNamespace().equals(element2.getNamespace())) {
+      if (element1.getChildText(COMPONENT_CLASS, namespace).equals(element2.getChildText(COMPONENT_CLASS, namespace))) {
+        if (element1.getChildText(COMPONENT_TYPE, namespace).equals(element2.getChildText(COMPONENT_TYPE, namespace))) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  protected org.jdom.Element createComponentElement(
+      final ComponentInfo componentInfo, final UIComponentTag componentTag, final Namespace namespace)
+      throws IOException, NoSuchFieldException, IllegalAccessException {
+    final org.jdom.Element element = new org.jdom.Element(COMPONENT, namespace);
+    final org.jdom.Element elementDisplayName = new org.jdom.Element(DISPLAY_NAME, namespace);
+    elementDisplayName.setText(componentInfo.getComponentClassName());
+    element.addContent(elementDisplayName);
+    final org.jdom.Element elementType = new org.jdom.Element(COMPONENT_TYPE, namespace);
+    elementType.setText(componentInfo.getComponentType());
+    element.addContent(elementType);
+    final org.jdom.Element elementClass = new org.jdom.Element(COMPONENT_CLASS, namespace);
+    elementClass.setText(componentTag.uiComponent());
+    element.addContent(elementClass);
+
+    return element;
+  }
+
+  protected void addRendererElement(
+      final ComponentInfo componentInfo, final UIComponentTag componentTag, final List<org.jdom.Element> renderer,
+      final Namespace namespace)
+      throws IOException, NoSuchFieldException, IllegalAccessException {
+    final String rendererType = componentTag.rendererType();
+    if (rendererType != null && rendererType.length() > 0) {
+      final org.jdom.Element element = new org.jdom.Element(RENDERER, namespace);
+      String displayName = componentTag.displayName();
+      if (displayName.equals("")) {
+        displayName = componentInfo.getComponentClassName();
+      }
+      final org.jdom.Element elementDisplayName = new org.jdom.Element(DISPLAY_NAME, namespace);
+      elementDisplayName.setText(displayName);
+      element.addContent(elementDisplayName);
+      final org.jdom.Element elementComponentFamily = new org.jdom.Element(COMPONENT_FAMILY, namespace);
+      elementComponentFamily.addContent(componentInfo.getComponentFamily());
+      element.addContent(elementComponentFamily);
+      final org.jdom.Element elementType = new org.jdom.Element(RENDERER_TYPE, namespace);
+      elementType.setText(rendererType);
+      element.addContent(elementType);
+      final org.jdom.Element elementClass = new org.jdom.Element(RENDERER_CLASS, namespace);
+      final String className = "org.apache.myfaces.tobago.internal.renderkit.renderer." + rendererType + "Renderer";
+      elementClass.setText(className);
+      element.addContent(elementClass);
+      renderer.add(element);
+    }
+  }
+
+
+  private org.jdom.Element createElementExtension(
+      final TypeElement typeElement, final UIComponentTag uiComponentTag,
+      final Namespace namespace) {
+    final org.jdom.Element elementExtension = new org.jdom.Element(COMPONENT_EXTENSION, namespace);
+    final org.jdom.Element elementAllowedChildComponents = new org.jdom.Element(ALLOWED_CHILD_COMPONENTS, namespace);
+    final String[] allowedChildComponents = uiComponentTag.allowedChildComponenents();
+    String allowedComponentTypes = "";
+    for (final String componentType : allowedChildComponents) {
+      allowedComponentTypes += componentType + " ";
+    }
+    elementAllowedChildComponents.setText(allowedComponentTypes);
+    elementExtension.addContent(elementAllowedChildComponents);
+    final org.jdom.Element elementCategory = new org.jdom.Element(CATEGORY, namespace);
+    elementCategory.setText(uiComponentTag.category().toString());
+    elementExtension.addContent(elementCategory);
+    final Deprecated deprecated = typeElement.getAnnotation(Deprecated.class);
+    if (deprecated != null) {
+      final org.jdom.Element elementDeprecated = new org.jdom.Element(DEPRECATED, namespace);
+      elementDeprecated.setText("Warning: This component is deprecated!");
+      elementExtension.addContent(elementDeprecated);
+    }
+    final org.jdom.Element elementHidden = new org.jdom.Element(HIDDEN, namespace);
+    elementHidden.setText(Boolean.toString(uiComponentTag.isHidden()));
+    elementExtension.addContent(elementHidden);
+
+    return elementExtension;
+  }
+
+  protected void addAttribute(
+      final ExecutableElement executableElement, final List<org.jdom.Element> attributes,
+      final List<org.jdom.Element> properties,
+      final Namespace namespace) {
+    final UIComponentTagAttribute componentAttribute = executableElement.getAnnotation(UIComponentTagAttribute.class);
+    if (componentAttribute != null) {
+      final String simpleName = executableElement.getSimpleName().toString();
+      if (simpleName.startsWith("set")) {
+        final String name = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
+        if (IGNORED_PROPERTIES.contains(name)) {
+          final org.jdom.Element attribute = new org.jdom.Element(ATTRIBUTE, namespace);
+          final org.jdom.Element attributeName = new org.jdom.Element(ATTRIBUTE_NAME, namespace);
+          final org.jdom.Element attributeClass = new org.jdom.Element(ATTRIBUTE_CLASS, namespace);
+
+          attributeName.setText(name);
+          addClass(componentAttribute, attributeClass);
+
+          addDescription(executableElement, attribute, namespace);
+
+          attribute.addContent(attributeName);
+          attribute.addContent(attributeClass);
+          if (componentAttribute.defaultValue().length() > 0) {
+            final org.jdom.Element defaultValue = new org.jdom.Element(DEFAULT_VALUE, namespace);
+            defaultValue.setText(componentAttribute.defaultValue());
+            attribute.addContent(defaultValue);
+          }
+
+          attribute.addContent(createPropertyOrAttributeExtension(ATTRIBUTE_EXTENSION, executableElement,
+              componentAttribute, namespace));
+
+          attributes.add(attribute);
+        } else {
+          final org.jdom.Element property = new org.jdom.Element(PROPERTY, namespace);
+          final org.jdom.Element propertyName = new org.jdom.Element(PROPERTY_NAME, namespace);
+          final org.jdom.Element propertyClass = new org.jdom.Element(PROPERTY_CLASS, namespace);
+
+          propertyName.setText(name);
+          addClass(componentAttribute, propertyClass);
+
+          addDescription(executableElement, property, namespace);
+
+          property.addContent(propertyName);
+          property.addContent(propertyClass);
+          if (componentAttribute.defaultValue().length() > 0) {
+            final org.jdom.Element defaultValue = new org.jdom.Element(DEFAULT_VALUE, namespace);
+            defaultValue.setText(componentAttribute.defaultValue());
+            property.addContent(defaultValue);
+          }
+
+          property.addContent(
+              createPropertyOrAttributeExtension(PROPERTY_EXTENSION, executableElement, componentAttribute, namespace));
+          properties.add(property);
+        }
+      } else {
+        throw new IllegalArgumentException("Only setter allowed found: " + simpleName);
+      }
+    }
+  }
+
+  private void addClass(final UIComponentTagAttribute componentAttribute, final org.jdom.Element attributeClass) {
+    if (componentAttribute.type().length > 1) {
+      attributeClass.setText(Object.class.getName());
+    } else if (componentAttribute.type().length == 1) {
+      String className = componentAttribute.type()[0];
+      if (componentAttribute.expression().isMethodExpression()) {
+        className = "javax.el.MethodExpression";
+      }
+      attributeClass.setText(className);
+    } else {
+      if (componentAttribute.expression().isMethodExpression()) {
+        attributeClass.setText("javax.el.MethodExpression");
+      }
+    }
+  }
+
+  private void addDescription(
+      final ExecutableElement element, final org.jdom.Element attribute, final Namespace namespace) {
+    String comment = processingEnv.getElementUtils().getDocComment(element);
+    if (comment != null) {
+      final int index = comment.indexOf('@');
+      if (index != -1) {
+        comment = comment.substring(0, index);
+      }
+      comment = comment.trim();
+      if (comment.length() > 0) {
+        final org.jdom.Element description = new org.jdom.Element(DESCRIPTION, namespace);
+        description.setText(comment);
+        attribute.addContent(description);
+      }
+    }
+  }
+
+  private org.jdom.Element createPropertyOrAttributeExtension(
+      final String extensionType, final ExecutableElement executableElement,
+      final UIComponentTagAttribute uiComponentTagAttribute,
+      final Namespace namespace)
+      throws IllegalArgumentException {
+    final org.jdom.Element extensionElement = new org.jdom.Element(extensionType, namespace);
+    final org.jdom.Element valueExpression = new org.jdom.Element(VALUE_EXPRESSION, namespace);
+    valueExpression.setText(uiComponentTagAttribute.expression().toMetaDataString());
+    extensionElement.addContent(valueExpression);
+    final String[] allowedValues = uiComponentTagAttribute.allowedValues();
+    if (allowedValues.length > 0) {
+      final org.jdom.Element propertyValues = new org.jdom.Element(PROPERTY_VALUES, namespace);
+      String values = "";
+      for (final String value : allowedValues) {
+        values += value + " ";
+      }
+      propertyValues.setText(values);
+      extensionElement.addContent(propertyValues);
+    }
+    final Deprecated deprecated = executableElement.getAnnotation(Deprecated.class);
+    if (deprecated != null) {
+      final org.jdom.Element elementDeprecated = new org.jdom.Element(DEPRECATED, namespace);
+      elementDeprecated.setText("Warning: This property is deprecated!");
+      extensionElement.addContent(elementDeprecated);
+    }
+    final org.jdom.Element hidden = new org.jdom.Element(HIDDEN, namespace);
+    hidden.setText(Boolean.toString(uiComponentTagAttribute.isHidden()));
+    extensionElement.addContent(hidden);
+    final org.jdom.Element readOnly = new org.jdom.Element(READONLY, namespace);
+    readOnly.setText(Boolean.toString(uiComponentTagAttribute.isReadOnly()));
+    extensionElement.addContent(readOnly);
+    final TagAttribute tagAttribute = executableElement.getAnnotation(TagAttribute.class);
+    if (tagAttribute != null) {
+      final org.jdom.Element required = new org.jdom.Element(REQUIRED, namespace);
+      required.setText(Boolean.toString(tagAttribute.required()));
+      extensionElement.addContent(required);
+    }
+
+    return extensionElement;
+  }
+
+  protected void addAttributes(
+      final TypeElement typeElement, final List<org.jdom.Element> attributes, final List<org.jdom.Element> properties,
+      final Namespace namespace) {
+
+    for (final javax.lang.model.element.Element element : processingEnv.getElementUtils().getAllMembers(typeElement)) {
+      final ExecutableElement executableElement = (ExecutableElement) element;
+      if (executableElement.getAnnotation(TagAttribute.class) == null
+          && executableElement.getAnnotation(UIComponentTagAttribute.class) == null) {
+        continue;
+      }
+
+      addAttribute(executableElement, attributes, properties, namespace);
+    }
+  }
+
+  private void addFacets(final UIComponentTag componentTag, final Namespace namespace, final org.jdom.Element element) {
+    final Facet[] facets = componentTag.facets();
+    for (final Facet facet : facets) {
+      final org.jdom.Element facetElement = new org.jdom.Element(FACET, namespace);
+      final String description = facet.description();
+      if (description != null && description.length() > 0) {
+        final org.jdom.Element facetDescription = new org.jdom.Element(DESCRIPTION, namespace);
+        facetDescription.setText(description);
+        facetElement.addContent(facetDescription);
+      }
+      final org.jdom.Element facetName = new org.jdom.Element(FACET_NAME, namespace);
+      facetName.setText(facet.name());
+      facetElement.addContent(facetName);
+      final org.jdom.Element facetExtension = new org.jdom.Element(FACET_EXTENSION, namespace);
+      final org.jdom.Element elementAllowedChildComponents = new org.jdom.Element(ALLOWED_CHILD_COMPONENTS, namespace);
+      final String[] allowedChildComponents = facet.allowedChildComponenents();
+      String allowedComponentTypes = "";
+      for (final String componentType : allowedChildComponents) {
+        allowedComponentTypes += componentType + " ";
+      }
+      elementAllowedChildComponents.setText(allowedComponentTypes);
+      facetExtension.addContent(elementAllowedChildComponents);
+      facetElement.addContent(facetExtension);
+      element.addContent(facetElement);
+    }
+  }
+
+  protected void addElement(
+      final TypeElement typeElement, final List<org.jdom.Element> components, final List<org.jdom.Element> renderer,
+      final Namespace namespace) throws Exception {
+    final UIComponentTag componentTag = typeElement.getAnnotation(UIComponentTag.class);
+    if (componentTag != null) {
+      final ComponentInfo componentInfo = new ComponentInfo(typeElement, componentTag);
+      if (!componentTag.isComponentAlreadyDefined()) {
+        final org.jdom.Element element = createComponentElement(componentInfo, componentTag, namespace);
+        if (element != null) {
+          if (!containsElement(components, element)) {
+            addFacets(componentTag, namespace, element);
+            final List<org.jdom.Element> attributes = new ArrayList<org.jdom.Element>();
+            final List<org.jdom.Element> properties = new ArrayList<org.jdom.Element>();
+            addAttributes(typeElement, attributes, properties, namespace);
+            if (!attributes.isEmpty()) {
+              Collections.sort(attributes, new Comparator<org.jdom.Element>() {
+                @Override
+                public int compare(final org.jdom.Element d1, final org.jdom.Element d2) {
+                  return d1.getChildText(ATTRIBUTE_NAME, namespace).compareTo(
+                      d2.getChildText(ATTRIBUTE_NAME, namespace));
+                }
+              });
+              element.addContent(attributes);
+            }
+            if (!properties.isEmpty()) {
+              Collections.sort(properties, new Comparator<org.jdom.Element>() {
+                @Override
+                public int compare(final org.jdom.Element d1, final org.jdom.Element d2) {
+                  return d1.getChildText(PROPERTY_NAME, namespace).compareTo(
+                      d2.getChildText(PROPERTY_NAME, namespace));
+                }
+              });
+              element.addContent(properties);
+            }
+            element.addContent(createElementExtension(typeElement, componentTag, namespace));
+            components.add(element);
+          } else {
+            // TODO add facet and attributes
+          }
+        }
+      }
+      addRendererElement(componentInfo, componentTag, renderer, namespace);
+    }
+  }
+
+  private void normaliseLineEndings(final Document document) {
+    final Iterator i = document.getDescendants(new ContentFilter(ContentFilter.COMMENT));
+    while (i.hasNext()) {
+      final Comment c = (Comment) i.next();
+      c.setText(c.getText().replaceAll("\n", SEPARATOR));
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/TaglibGenerator.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/TaglibGenerator.java
new file mode 100644
index 0000000..98d8280
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/java/org/apache/myfaces/tobago/apt/processor/TaglibGenerator.java
@@ -0,0 +1,523 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.processor;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.myfaces.tobago.apt.AnnotationUtils;
+import org.apache.myfaces.tobago.apt.annotation.Facet;
+import org.apache.myfaces.tobago.apt.annotation.Preliminary;
+import org.apache.myfaces.tobago.apt.annotation.SimpleTag;
+import org.apache.myfaces.tobago.apt.annotation.Tag;
+import org.apache.myfaces.tobago.apt.annotation.TagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.Taglib;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTag;
+import org.apache.myfaces.tobago.apt.annotation.UIComponentTagAttribute;
+import org.apache.myfaces.tobago.apt.annotation.ValidatorTag;
+import org.apache.myfaces.tobago.apt.generate.ClassUtils;
+import org.w3c.dom.Comment;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.annotation.processing.SupportedOptions;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.PackageElement;
+import javax.lang.model.element.TypeElement;
+import javax.tools.FileObject;
+import javax.tools.StandardLocation;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+@SupportedAnnotationTypes({
+    "org.apache.myfaces.tobago.apt.annotation.Tag",
+    "org.apache.myfaces.tobago.apt.annotation.TagAttribute",
+    "org.apache.myfaces.tobago.apt.annotation.Taglib"})
+@SupportedOptions({
+    TaglibGenerator.TARGET_TAGLIB})
+public class TaglibGenerator extends AbstractGenerator {
+
+  static final String TARGET_TAGLIB = "targetTaglib";
+
+  private Set<String> tagSet = new HashSet<String>();
+  private Set<String> attributeSet = new HashSet<String>();
+  private String currentTag;
+
+  private String targetTaglib;
+
+  @Override
+  public void configure() {
+    final Map<String, String> options = processingEnv.getOptions();
+    targetTaglib = options.get(TARGET_TAGLIB);
+
+    info("Generating the *.tld and *.taglib.xml");
+    info("Options:");
+    info(TARGET_TAGLIB + ": " + targetTaglib);
+  }
+
+  @Override
+  public void generate()
+      throws IOException, TransformerException, ParserConfigurationException, ClassNotFoundException {
+    for (final PackageElement packageElement : getPackages()) {
+      final Taglib taglibAnnotation = packageElement.getAnnotation(Taglib.class);
+
+      createTaglib(taglibAnnotation, packageElement);
+    }
+  }
+
+  protected void createTaglib(final Taglib taglibAnnotation, final PackageElement packageElement)
+      throws ParserConfigurationException, ClassNotFoundException, IOException, TransformerException {
+    resetDuplicateList();
+    final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+    dbf.setValidating(false);
+
+    // building the XML document
+
+    final DocumentBuilder parser = dbf.newDocumentBuilder();
+    final Document document = parser.newDocument();
+
+    final Element taglib = createTaglib(document, taglibAnnotation);
+    final String description = processingEnv.getElementUtils().getDocComment(packageElement);
+
+    addComment("The next tags are commented because of MYFACES-3537. "
+        + "The application will not run with MyFaces before 2.0.14/2.1.8. "
+        + "This also affects WebSphere 8.5", taglib, document);
+    addComment("<description>" + description + "</description>", taglib, document);
+    addComment("<display-name>" + taglibAnnotation.displayName() + "</display-name>", taglib, document);
+
+/* XXX disabled, because of the bug explained in the comment above.
+    if (description != null) {
+      addLeafCDATAElement(description, "description", taglib, document);
+    }
+    addLeafTextElement(taglibAnnotation.displayName(), "display-name", taglib, document);
+*/
+
+    addLeafTextElement(taglibAnnotation.uri(), "namespace", taglib, document);
+
+    // XXX hack: should be configurable or generated from annotations.
+    if ("http://myfaces.apache.org/tobago/component".equals(taglibAnnotation.uri())) {
+      addFunction(document, taglib, "columnPartition", "org.apache.myfaces.tobago.layout.ColumnPartition",
+          "org.apache.myfaces.tobago.layout.ColumnPartition valueOf(java.lang.String)");
+
+      for (int i = 1; i < 10; i++) {
+        addFunction(document, taglib, "format" + i, "org.apache.myfaces.tobago.util.MessageFormat",
+            "java.lang.String format(java.lang.String"+ StringUtils.repeat(", java.lang.Object", i) +")");
+      }
+    }
+
+    for (final TypeElement typeElement : getTypes()) {
+      if (processingEnv.getElementUtils().getPackageOf(typeElement).equals(packageElement)) {
+        appendTag(typeElement, taglib, document);
+      }
+    }
+    document.appendChild(taglib);
+
+    // writing the XML document
+
+    Writer writer = null;
+    try {
+      String target = targetTaglib;
+      target = StringUtils.isNotBlank(target) ? target + '/' : "";
+      final String name = target + taglibAnnotation.name() + ".taglib.xml";
+      final FileObject resource = processingEnv.getFiler().createResource(StandardLocation.SOURCE_OUTPUT, "", name);
+      info("Writing to file: " + resource.toUri());
+      writer = resource.openWriter();
+
+      final TransformerFactory transFactory = TransformerFactory.newInstance();
+      transFactory.setAttribute("indent-number", 2);
+      final Transformer transformer = transFactory.newTransformer();
+      transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+      transformer.transform(new DOMSource(document), new StreamResult(writer));
+    } finally {
+      IOUtils.closeQuietly(writer);
+    }
+  }
+
+  private void addFunction(Document document, Element taglib, String functionName, String functionClass,
+                           String functionSignature) {
+    final Element function = document.createElement("function");
+    taglib.appendChild(function);
+    addLeafTextElement(functionName, "function-name", function, document);
+    addLeafTextElement(functionClass, "function-class", function, document);
+    addLeafTextElement(functionSignature, "function-signature", function, document);
+  }
+
+  protected void appendTag(
+      final TypeElement typeElement, final Element parent, final Document document)
+      throws ClassNotFoundException {
+    final Tag annotationTag = typeElement.getAnnotation(Tag.class);
+    if (annotationTag != null) {
+      checkDuplicates(annotationTag.name());
+      resetAttributeDuplicateList();
+      // TODO configure replacement
+//      final String className;
+//      if (typeElement.getAnnotation(SimpleTag.class) != null
+// || typeElement.getAnnotation(ValidatorTag.class) != null) {
+//        className = AnnotationUtils.generatedTagName(typeElement);
+//      } else if (typeElement.getAnnotation(ExtensionTag.class) != null) {
+//        className = typeElement.getQualifiedName().toString();
+//      } else if (typeElement.getAnnotation(UIComponentTag.class) != null) {
+//        className = "org.apache.myfaces.tobago.internal.taglib." + StringUtils.capitalize(annotationTag.name())
+//            + "Tag";
+//      } else {
+//        throw new RuntimeException("Not supported: " + typeElement.getQualifiedName());
+//      }
+//      info("Replacing: " + typeElement.getQualifiedName() + " -> " + className);
+      final Element tag = createTag(typeElement, annotationTag, document, false);
+      addAttributes(typeElement, tag, document);
+      parent.appendChild(tag);
+      if (annotationTag.deprecatedName() != null && annotationTag.deprecatedName().length() > 0) {
+        final Element deprecatedTag = createTag(typeElement, annotationTag, document, true);
+        addAttributes(typeElement, deprecatedTag, document);
+        parent.appendChild(deprecatedTag);
+      }
+    }
+  }
+
+  protected Element createTag(
+      final TypeElement typeElement, final Tag annotationTag, final Document document,
+      final boolean deprecated) {
+    final Element tagElement = document.createElement("tag");
+    addDescription(typeElement, tagElement, document, deprecated);
+    addTagContent(typeElement, tagElement, document, deprecated, annotationTag);
+    return tagElement;
+  }
+
+  private void checkAttributeDuplicates(final String attributeName) {
+    if (attributeSet.contains(attributeName)) {
+      throw new IllegalArgumentException("Attribute " + attributeName + " in tag " + currentTag + " already defined!");
+    } else {
+      attributeSet.add(attributeName);
+    }
+  }
+
+  private void checkDuplicates(final String tagName) {
+    currentTag = tagName;
+    if (tagSet.contains(tagName)) {
+      throw new IllegalArgumentException("tag with name " + tagName + " already defined!");
+    } else {
+      tagSet.add(tagName);
+    }
+  }
+
+  protected void addDescription(
+      final javax.lang.model.element.Element typeElement, final Element element, final Document document,
+      final boolean deprecated) {
+    final StringBuilder description = new StringBuilder();
+    final Deprecated deprecatedAnnotation = typeElement.getAnnotation(Deprecated.class);
+    String comment = processingEnv.getElementUtils().getDocComment(typeElement);
+    final String deprecationComment = deprecationComment(comment);
+
+    if (deprecatedAnnotation != null || deprecationComment != null) {
+      description.append("<p>**** @deprecated. Will be removed in a future version **** </p>");
+    }
+    if (deprecated) {
+      final Tag annotationTag = typeElement.getAnnotation(Tag.class);
+      description.append("<p>**** @deprecated. Will be removed in a future version. Use ");
+      description.append(annotationTag.name());
+      description.append(" instead. **** </p>");
+    }
+    if (deprecationComment != null) {
+      description.append("<p>").append(deprecationComment).append("</p>");
+    }
+
+    final Preliminary preliminary = typeElement.getAnnotation(Preliminary.class);
+    if (preliminary != null) {
+      description.append("<p>**** Preliminary. Maybe subject to changed in a future version");
+      if (preliminary.value().length() > 0) {
+        description.append(": ");
+        description.append(preliminary.value());
+      }
+      description.append(" **** </p>");
+    }
+    if (comment != null) {
+      // remove @param section
+      final int index = comment.indexOf(" @");
+      if (index != -1) {
+        comment = comment.substring(0, index);
+      }
+      comment = comment.trim();
+      if (comment.length() > 0) {
+        //description.append("<p>");
+        description.append(comment);
+        //description.append("</p>");
+      }
+    }
+    final UIComponentTag componentTag = typeElement.getAnnotation(UIComponentTag.class);
+    if (componentTag != null) {
+      description.append(createDescription(componentTag));
+    }
+    final UIComponentTagAttribute attributeTag = typeElement.getAnnotation(UIComponentTagAttribute.class);
+    if (attributeTag != null) {
+      if (null != attributeTag.type() && attributeTag.type().length > 0) {
+        description.append("<br />Type: <code>")
+            .append(attributeTag.type().length == 1 ? attributeTag.type()[0] : Arrays.toString(attributeTag.type()))
+            .append("</code>");
+      }
+      if (StringUtils.isNotEmpty(attributeTag.defaultValue())) {
+        description.append("<br />Default: <code>")
+            .append(attributeTag.defaultValue())
+            .append("</code>");
+      }
+      if (attributeTag.allowedValues().length > 0) {
+        description.append("<br />Allowed Values: <code>")
+            .append(Arrays.toString(attributeTag.allowedValues()))
+            .append("</code>");
+      }
+    }
+    if (description.length() > 0) {
+      addLeafCDATAElement(description.toString(), "description", element, document);
+    }
+  }
+
+  private String deprecationComment(String string) {
+    if (string == null) {
+      return null;
+    }
+    final String deprecated = "@deprecated";
+    final int begin = string.indexOf(deprecated);
+    if (begin > -1) {
+      string = string.substring(begin + deprecated.length());
+      final int end = string.indexOf("@");
+      if (end > -1) {
+        string = string.substring(0, end);
+      }
+      return string.trim();
+    } else {
+      return null;
+    }
+  }
+
+  private TypeElement getInterfaceDeclaration(final String name) {
+    for (final TypeElement type : getTypes()) {
+      if (name.equals(type.getQualifiedName().toString())) {
+        return type;
+      }
+    }
+    return null;
+  }
+
+  private String createDescription(final UIComponentTag componentTag) {
+    final StringBuilder description = new StringBuilder();
+    description.append("<p><b>UIComponentClass: </b>");
+    description.append(componentTag.uiComponent());
+    description.append("</p>");
+    description.append("<p><b>RendererType: </b>");
+    description.append(componentTag.rendererType());
+    description.append("</p>");
+    final Facet[] facets = componentTag.facets();
+    if (facets.length > 0) {
+      description.append("<p><b>Supported facets:</b></p>");
+      description.append("<dl>");
+      for (final Facet facet : facets) {
+        description.append("<dt><b>");
+        description.append(facet.name());
+        description.append("</b></dt>");
+        description.append("<dd>");
+        description.append(facet.description());
+        description.append("</dd>");
+      }
+      description.append("</dl>");
+    }
+    return description.toString();
+  }
+
+  protected void addAttributes(
+      final TypeElement typeElement, final Element tagElement, final Document document)
+      throws ClassNotFoundException {
+
+    for (final javax.lang.model.element.Element element : getAllMembers(typeElement)) {
+      if (element instanceof ExecutableElement) {
+        final ExecutableElement executableElement = (ExecutableElement) element;
+        if (executableElement.getAnnotation(TagAttribute.class) == null
+            && executableElement.getAnnotation(UIComponentTagAttribute.class) == null) {
+          continue;
+        }
+        addAttribute(executableElement, tagElement, document);
+      }
+    }
+  }
+
+  private List<? extends javax.lang.model.element.Element> getAllMembers(final TypeElement type) {
+    final List<? extends javax.lang.model.element.Element> members
+        = new ArrayList<javax.lang.model.element.Element>(processingEnv.getElementUtils().getAllMembers(type));
+    Collections.sort(members, new Comparator<javax.lang.model.element.Element>() {
+      @Override
+      public int compare(final javax.lang.model.element.Element d1, final javax.lang.model.element.Element d2) {
+        return d1.getSimpleName().toString().compareTo(d2.getSimpleName().toString());
+      }
+    });
+    return members;
+  }
+
+  private void resetDuplicateList() {
+    tagSet = new HashSet<String>();
+  }
+
+  private void resetAttributeDuplicateList() {
+    attributeSet = new HashSet<String>();
+  }
+
+  protected void addAttribute(
+      final ExecutableElement element, final Element tagElement, final Document document)
+      throws ClassNotFoundException {
+    final TagAttribute tagAttribute = element.getAnnotation(TagAttribute.class);
+    if (tagAttribute != null) {
+      final String simpleName = element.getSimpleName().toString();
+      if (simpleName.startsWith("set") || simpleName.startsWith("get")) {
+        final Element attribute = document.createElement("attribute");
+        String attributeName = simpleName.substring(3, 4).toLowerCase(Locale.ENGLISH) + simpleName.substring(4);
+        if (tagAttribute.name().length() > 0) {
+          attributeName = tagAttribute.name();
+        }
+        checkAttributeDuplicates(attributeName);
+        addDescription(element, attribute, document, false);
+        addLeafTextElement(attributeName, "name", attribute, document);
+
+        addLeafTextElement(Boolean.toString(tagAttribute.required()), "required", attribute, document);
+        final UIComponentTagAttribute componentTagAttribute = element.getAnnotation(UIComponentTagAttribute.class);
+        addAttributeType(attribute, tagAttribute, componentTagAttribute, document);
+        tagElement.appendChild(attribute);
+      } else {
+        throw new IllegalArgumentException("Only setter allowed found: " + simpleName);
+      }
+    }
+  }
+
+  protected void addComment(final String text, final org.w3c.dom.Element parent, final Document document) {
+    final Comment comment = document.createComment(text);
+    parent.appendChild(comment);
+  }
+
+  protected void addLeafTextElement(
+      final String text, final String node, final org.w3c.dom.Element parent, final Document document) {
+    final org.w3c.dom.Element element = document.createElement(node);
+    element.appendChild(document.createTextNode(text));
+    parent.appendChild(element);
+  }
+
+  protected void addLeafCDATAElement(
+      final String text, final String node, final org.w3c.dom.Element parent, final Document document) {
+    final org.w3c.dom.Element element = document.createElement(node);
+    element.appendChild(document.createCDATASection(text));
+    parent.appendChild(element);
+  }
+
+  protected Element createTaglib(final Document document, Taglib taglibAnnotation) {
+    final Element taglib;
+    taglib = document.createElement("facelet-taglib");
+    taglib.setAttribute("id", taglibAnnotation.shortName());
+    taglib.setAttribute("xmlns", "http://java.sun.com/xml/ns/javaee");
+    taglib.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
+    taglib.setAttribute("xsi:schemaLocation",
+        "http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd");
+    taglib.setAttribute("version", "2.0");
+    return taglib;
+  }
+
+  protected void addTagContent(
+      final TypeElement typeElement, final Element tagElement, final Document document, final boolean deprecated,
+      final Tag annotationTag) {
+    if (deprecated) {
+      addLeafTextElement(annotationTag.deprecatedName(), "tag-name", tagElement, document);
+    } else {
+      addLeafTextElement(annotationTag.name(), "tag-name", tagElement, document);
+    }
+
+    final UIComponentTag componentTag = typeElement.getAnnotation(UIComponentTag.class);
+    if (componentTag != null) {
+      final Element componentElement = document.createElement("component");
+      tagElement.appendChild(componentElement);
+      addLeafTextElement(
+          AnnotationUtils.componentType(componentTag), "component-type", componentElement, document);
+      if (StringUtils.isNotBlank(componentTag.rendererType())) {
+        addLeafTextElement(componentTag.rendererType(), "renderer-type", componentElement, document);
+      }
+      addLeafTextElement(componentTag.faceletHandler(), "handler-class", componentElement, document);
+    }
+
+    final SimpleTag simpleTag = typeElement.getAnnotation(SimpleTag.class);
+    if (simpleTag != null) {
+      addLeafTextElement(simpleTag.faceletHandler(), "handler-class", tagElement, document);
+    }
+
+    final ValidatorTag validatorTag = typeElement.getAnnotation(ValidatorTag.class);
+    if (validatorTag != null) {
+      final Element validatorElement = document.createElement("validator");
+      tagElement.appendChild(validatorElement);
+      addLeafTextElement(validatorTag.validatorId(), "validator-id", validatorElement, document);
+      if (StringUtils.isNotBlank(validatorTag.faceletHandler())) {
+        addLeafTextElement(validatorTag.faceletHandler(), "handler-class", validatorElement, document);
+      }
+    }
+  }
+
+  protected void addAttributeType(
+      final Element attribute, final TagAttribute tagAttribute, final UIComponentTagAttribute componentTagAttribute,
+      final Document document) {
+    if (!tagAttribute.rtexprvalue()) {
+      if (componentTagAttribute != null) {
+        if (componentTagAttribute.expression().isMethodExpression()) {
+          // todo
+        } else if (componentTagAttribute.expression().isValueExpression()) {
+          String clazz;
+          if (componentTagAttribute.type().length == 1) {
+            clazz = componentTagAttribute.type()[0];
+            final Class wrapper = ClassUtils.getWrapper(clazz);
+            if (wrapper != null) {
+              clazz = wrapper.getName(); // primitive types aren't allowed here
+      /*                } else {
+                      XXX what is with inner classes and arrays?
+                      if (clazz.endsWith("[]")) {
+                        Class.forName(clazz.substring(0, clazz.length() - 2)); // type check
+                      } else {
+                        Class.forName(clazz); // type check
+                      }
+      */
+            }
+          } else {
+            clazz = "java.lang.Object";
+          }
+          addLeafTextElement(clazz, "type", attribute, document);
+        }
+      } else {
+        addLeafTextElement(tagAttribute.type(), "type", attribute, document);
+      }
+    }
+  }
+}
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/resources/org/apache/myfaces/tobago/apt/component.stg b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/resources/org/apache/myfaces/tobago/apt/component.stg
new file mode 100644
index 0000000..0a47d87
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/main/resources/org/apache/myfaces/tobago/apt/component.stg
@@ -0,0 +1,587 @@
+group components;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+component(componentInfo) ::= <<
+// ---------- Attention: Generated code, please do not modify! -----------  
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package <componentInfo.packageName>;
+
+<componentInfo.imports:import(); separator="\n">
+import org.apache.myfaces.tobago.internal.util.ArrayUtils;
+import org.apache.myfaces.tobago.internal.util.StringUtils;
+import org.apache.myfaces.tobago.internal.util.Deprecation;
+import javax.el.ELException;
+import javax.faces.FacesException;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import javax.el.MethodExpression;
+import javax.el.ValueExpression;
+
+/** 
+ <if(componentInfo.description)>
+ <componentInfo.description>
+ <endif>
+  * UIComponent class, generated from template {@code component.stg} with class
+  * {@link <componentInfo.sourceClass>}.
+   <if(componentInfo.deprecated)>
+   @deprecated
+   <endif>
+ */
+<if(componentInfo.deprecated)>
+@Deprecated
+
+<endif>
+public class <componentInfo.className>
+    extends <componentInfo.superClassName> <first(componentInfo.interfaces):{ n | implements <n>}><rest(componentInfo.interfaces):{ n |, <n>}> {
+
+  <if(componentInfo.componentType)>
+  public static final String COMPONENT_TYPE = "<componentInfo.componentType>";
+
+  <endif>
+  <if(componentInfo.componentFamily)>
+  public static final String COMPONENT_FAMILY = "<componentInfo.componentFamily>";
+
+  <endif>
+  <if(componentInfo.behaviors)>
+  private static final Collection\<String\> EVENT_NAMES = Arrays.asList(<first(componentInfo.behaviors):{ it | "<it>"}><rest(componentInfo.behaviors):{ it |, "<it>"}>);
+
+  @Override
+  public Collection\<String\> getEventNames() {
+    return EVENT_NAMES;
+  }
+
+  <endif>
+  <if(componentInfo.defaultBehavior)>
+  @Override
+  public String getDefaultEventName() {
+    return "<componentInfo.defaultBehavior>";
+  }
+
+  <endif>
+  <componentInfo.transientProperties:field(); separator="\n">
+
+  <if(componentInfo.properties)>
+  enum PropertyKeys {
+    <componentInfo.nonTransientProperties:enumName(); separator="\n">
+  }
+  <endif>
+
+  <if(componentInfo.componentFamily)>
+  public String getFamily() {
+    return COMPONENT_FAMILY;
+  }
+
+  <endif>
+  <componentInfo.properties:{ p | <p:(p.propertyTemplate)()>}; separator="\n">
+
+  <if(componentInfo.transientProperties)>
+  public Object saveState(FacesContext context) {
+    <componentInfo.transientProperties:{ p | <p:resetField()>}; separator="\n">
+    return super.saveState(context);
+  }
+  <endif>
+
+}
+>>
+
+import() ::= <<
+import <it>;
+>>
+
+createDescription(property) ::= <<
+<if(property.description)>
+/**
+<property.description>
+<if(property.defaultValue)>
+\<br\>Default: \<code\><property.defaultValue>\</code\>
+<endif>
+<if(property.allowedValues)>
+\<br\>Allowed Values: \<code\><property.allowedValues:allowedValue(); separator=",">\</code\>
+<endif>
+
+<if(property.deprecated)>
+@deprecated
+<endif>
+*/
+<endif>
+>>
+
+checkDeprecated(property) ::= <<
+<if(property.deprecated)>
+@Deprecated
+<endif>
+>>
+
+logDeprecated(property) ::= <<
+<if(property.deprecated)>
+  Deprecation.LOG.error("The attribute '<property.propertyName>' of '<componentInfo.className>' is deprecated. "
+      + "Please refer the documentation for further information.");
+<endif>
+>>
+
+allowedValue() ::= <<
+<it>
+>>
+
+IntegerProperty(property) ::= <<
+
+<createDescription(property)>
+<checkDeprecated(property)>
+public <property.type> get<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  Number value  = (Number) getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (value != null) {
+    return value.intValue();
+  }
+  <endif>
+  <if(property.defaultCode)>
+  return <property.defaultCode>;
+  <else>
+  return null;
+  <endif>
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(<property.type> <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  this.<property.propertyName> = <property.propertyName>;
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+ObjectProperty(property) ::= <<
+
+<createDescription(property)>
+<checkDeprecated(property)>
+public <property.type> get<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  return getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  <endif>
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(<property.type> <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  this.<property.propertyName> = <property.propertyName>;
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+StringArrayProperty(property) ::= <<
+
+<createDescription(property)>
+<checkDeprecated(property)>
+public String[] get<property.upperCamelCaseName>() {
+  Object strArray = getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (strArray != null) {
+    if (strArray instanceof String[]) {
+      return (String[]) strArray;
+    } else if (strArray instanceof String) {
+      String[] strings = StringUtils.split((String) strArray, ", ");
+      List\<String\> result = new ArrayList\<String\>(strings.length);
+      for (String string : strings) {
+        if (string.trim().length() != 0) {
+          result.add(string.trim());
+        }
+      }
+      return result.toArray(new String[result.size()]);
+    } else if (strArray == null) {
+      return org.apache.myfaces.tobago.internal.util.ArrayUtils.EMPTY_STRING_ARRAY;
+    } else {
+      return new String[]{strArray.toString()};
+    }
+  }
+  return org.apache.myfaces.tobago.internal.util.ArrayUtils.EMPTY_STRING_ARRAY;
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(String[] <property.propertyName>) {
+  <logDeprecated(property)>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+}
+>>
+
+booleanProperty(property) ::= <<
+
+<createDescription(property)>
+<checkDeprecated(property)>
+public boolean is<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  Boolean bool = (Boolean) getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (bool != null) {
+    return bool;
+  }
+  <endif>
+  <if(property.defaultCode)>
+  return <property.defaultCode>;
+  <else>
+  return false;
+  <endif>
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(boolean <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  this.<property.propertyName> = <property.propertyName>;
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+BooleanProperty(property) ::= <<
+
+<createDescription(property)>
+<checkDeprecated(property)>
+public Boolean get<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  Boolean bool = (Boolean) getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (bool != null) {
+    return bool;
+  }
+  <endif>
+  <if(property.defaultCode)>
+  return <property.defaultCode>;
+  <else>
+  return null;
+  <endif>
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(Boolean <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  this.<property.propertyName> = <property.propertyName>;
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+SeverityProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+TextAlignProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+SuggestFilterProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+DisplayProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+OrientationProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+PositionProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+OverflowProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+SanitizeModeProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+CollapseModeProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+ShowPositionProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+StyleProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+CustomClassProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+OrderByProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+SelectableProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+AlignItemsProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+JustifyContentProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+SwitchTypeProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+StringProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+CharacterProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+ColumnPartitionProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+LabelLayoutProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+ClientBehaviorsProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+DoubleProperty(property) ::= <<
+<NormalProperty(property)>
+>>
+
+MethodExpressionProperty(property) ::= <<
+
+/**
+ * @deprecated since 2.0.0
+ */
+@Deprecated
+public javax.faces.el.MethodBinding get<property.upperCamelCaseName>() {
+  javax.el.MethodExpression expression = get<property.upperCamelCaseName>Expression();
+  if (expression instanceof MethodBindingToMethodExpression) {
+    return ((MethodBindingToMethodExpression)expression).getMethodBinding();
+  }
+  if (expression != null) {
+     return new MethodExpressionToMethodBinding(expression);
+  }
+  return null;
+}
+
+/**
+ * @deprecated since 2.0.0
+ */
+@Deprecated
+public void set<property.upperCamelCaseName>(javax.faces.el.MethodBinding <property.propertyName>) {
+  if (<property.propertyName> != null) {
+    set<property.upperCamelCaseName>Expression(new MethodBindingToMethodExpression(<property.propertyName>));
+  } else {
+    set<property.upperCamelCaseName>Expression(null);
+  }
+}
+
+public <property.type> get<property.upperCamelCaseName>Expression() {
+  return (<property.type>) getStateHelper().eval(PropertyKeys.<property.propertyName>);
+}
+
+public void set<property.upperCamelCaseName>Expression(<property.type> <property.propertyName>) {
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+}
+
+>>
+
+NormalProperty(property) ::= <<
+
+<createDescription(property)>
+<checkDeprecated(property)>
+public <property.type> get<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  <if(property.defaultCode)>
+  <property.type> <property.propertyName> = (<property.type>) getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  return (<property.type>) getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  <endif>
+  <endif>
+  <if(property.defaultCode)>
+  return <property.defaultCode>;
+  <endif>
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(<property.type> <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+MeasureProperty(property) ::= <<
+
+<createDescription(property)>
+<checkDeprecated(property)>
+public <property.type> get<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  Object object = getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (object != null) {
+     return Measure.valueOf(object);
+  }
+  <endif>
+  <if(property.defaultCode)>
+  return <property.defaultCode>;
+  <else>
+  return null;
+  <endif>
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(<property.type> <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  this.<property.propertyName> = <property.propertyName>;
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+MarkupProperty(property) ::= <<
+
+<checkDeprecated(property)>
+public <property.type> get<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  Object object = getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (object != null) {
+    return Markup.valueOf(object);
+  }
+  <endif>
+  return null;
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(<property.type> <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  this.<property.propertyName> = <property.propertyName>;
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+CssProperty(property) ::= <<
+
+<checkDeprecated(property)>
+public <property.type> get<property.upperCamelCaseName>() {
+  <if(property.transient)>
+  if (<property.propertyName> != null) {
+    return <property.propertyName>;
+  }
+  <else>
+  Object object = getStateHelper().eval(PropertyKeys.<property.propertyName>);
+  if (object != null) {
+    return Css.valueOf(object);
+  }
+  <endif>
+  return null;
+}
+
+<checkDeprecated(property)>
+public void set<property.upperCamelCaseName>(<property.type> <property.propertyName>) {
+  <logDeprecated(property)>
+  <if(property.transient)>
+  this.<property.propertyName> = <property.propertyName>;
+  <else>
+  getStateHelper().put(PropertyKeys.<property.propertyName>, <property.propertyName>);
+  <endif>
+}
+>>
+
+enumName() ::= <<
+<it.propertyName>,
+>>
+
+strings() ::= <<
+<it.propertyName>,
+>>
+
+field() ::= <<
+private <it.internalType> <it.propertyName>;
+>>
+
+resetField() ::= <<
+<it.propertyName> = null;
+>>
diff --git a/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/test/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGeneratorUnitTest.java b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/test/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGeneratorUnitTest.java
new file mode 100644
index 0000000..b870279
--- /dev/null
+++ b/tobago-3.0.x/tobago-tool/tobago-tool-apt/src/test/java/org/apache/myfaces/tobago/apt/processor/CheckstyleConfigGeneratorUnitTest.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.myfaces.tobago.apt.processor;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import java.util.Arrays;
+
+public class CheckstyleConfigGeneratorUnitTest {
+
+  @Test
+  public void testGetRegExpForUndefinedAttributes() {
+
+    String regexp = CheckstyleConfigGenerator.getRegExpForUndefinedAttributes(
+        "tc", "textarea", Arrays.asList("attr1", "attr2"));
+
+    Assert.assertEquals(
+        "<tc:textarea(\\s+(attr1|attr2|xmlns:\\w*)=\\\"([^\"=<>]*)\\\")*\\s+(?!(attr1|attr2|xmlns:\\w*|\\W))", regexp);
+
+    regexp = ".*" + regexp + ".*";
+
+    Assert.assertFalse("<tc:textarea attr1=\"bla bla\"/>".matches(regexp));
+    Assert.assertFalse("<tc:textarea attr2=\"bla bla\"/>".matches(regexp));
+    Assert.assertFalse("<tc:textarea attr2=\"bla bla\" attr1=\".....\"/>".matches(regexp));
+    Assert.assertTrue("<tc:textarea hallo=\"bla bla\"/>".matches(regexp));
+
+    Assert.assertFalse("<tc:textarea xmlns:f=\"http://java.sun.com/jsf/core\" attr1=\"bla bla\"/>".matches(regexp));
+    Assert.assertTrue("<tc:textarea xmlns:f=\"http://java.sun.com/jsf/core\" hallo=\"bla bla\"/>".matches(regexp));
+
+    Assert.assertFalse("<any> <tc:textarea      attr1=\"bla bla\"     /> <any>".matches(regexp));
+    Assert.assertFalse("<any> <tc:textarea         attr2=\"bla bla\"  /><any>".matches(regexp));
+    Assert.assertFalse("<any> <tc:textarea            attr2=\"bla bla\"    attr1=\".....\"/><any> ".matches(regexp));
+    Assert.assertTrue("<any> <tc:textarea        hallo=\"bla bla\"         /> <any> ".matches(regexp));
+  }
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@myfaces.apache.org" <co...@myfaces.apache.org>.

[myfaces-tobago] 01/03: [maven-release-plugin] copy for tag tobago-3.0.3

Posted by de...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

deki pushed a commit to tag tobago-3.0.3
in repository https://gitbox.apache.org/repos/asf/myfaces-tobago.git

commit 3a6454b6eddd16984fc1afae41552e15bf34b00c
Author: Udo Schnurpfeil <lo...@apache.org>
AuthorDate: Thu Feb 2 12:53:15 2017 +0000

    [maven-release-plugin] copy for tag tobago-3.0.3

-- 
To stop receiving notification emails like this one, please contact
"commits@myfaces.apache.org" <co...@myfaces.apache.org>.