diff --git a/developer_manual/app/controllers.rst b/developer_manual/app/controllers.rst index da077544f..2d20ab0d5 100644 --- a/developer_manual/app/controllers.rst +++ b/developer_manual/app/controllers.rst @@ -322,6 +322,7 @@ By default there is only a responder for JSON but more can be added easily: namespace OCA\MyApp\Controller; use \OCP\AppFramework\Controller; + use \OCP\AppFramework\Http\DataResponse; class PageController extends Controller { @@ -329,7 +330,15 @@ By default there is only a responder for JSON but more can be added easily: // XMLResponse has to be implemented $this->registerResponder('xml', function($value) { - return new XMLResponse($value); + if ($value instanceof DataResponse) { + return new XMLResponse( + $value->getData(), + $value->getStatus(), + $value->getHeaders() + ); + } else { + return new XMLResponse($value); + } }); return array('test' => 'hi'); @@ -339,6 +348,32 @@ By default there is only a responder for JSON but more can be added easily: .. note:: The above example would only return XML if the **format** parameter was *xml*. If you want to return an XMLResponse regardless of the format parameter, extend the Response class and return a new instance of it from the controller method instead. +.. versionadded:: 8 + +Because returning values works fine in case of a success but not in case of failure that requires a custom HTTP error code, you can always wrap the value in a **DataResponse**. This works for both normal responses and error responses. + +.. code-block:: php + + 'not found!'), Http::STATUS_NOT_FOUND); + } + } + + } + + Templates --------- A :doc:`template ` can be rendered by returning a TemplateResponse. A TemplateResponse takes the following parameters: diff --git a/developer_manual/app/css.rst b/developer_manual/app/css.rst index a0f3d08e9..0991d2a51 100644 --- a/developer_manual/app/css.rst +++ b/developer_manual/app/css.rst @@ -37,9 +37,15 @@ To use the commonly used layout consisting of sidebar navigation and content the
Your navigation
-
Your content
+
+
+ Your content in here +
+
+For built in mobile support your content has to be wrapped inside another div with the id **app-content-wrapper**. + Navigation ========== ownCloud provides a default CSS navigation layout. If list entries should have 16x16 px icons, the **with-icon** class can be added to the base **ul**. The maximum supported indention level is two, further indentions are not recommended. @@ -102,6 +108,155 @@ The class which should be applied to a first level element (**li**) that hosts o +Menus +----- + +.. versionadded:: 8 + +To add actions that affect the current list element you can add a menu for second and/or first level elements by adding the button and menu inside the corresponding **li** element and adding the **with-menu** css class: + +.. code-block:: html + +
+
+ +The div with the class **app-navigation-entry-utils** contains only the button (class: **app-navigation-entry-utils-menu-button**) to display the menu but in many cases another entry is needed to display some sort of count (mails count, unread feed count, etc.). In that case add the **with-counter** class to the list entry to adjust the correct padding and text-oveflow of the entry's title. + +The count should be limitted to 999 and turn to 999+ if any higher number is given. If AngularJS is used the following filter can be used to get the correct behaviour: + +.. code-block:: js + + app.filter('counterFormatter', function () { + 'use strict'; + return function (count) { + if (count > 999) { + return '999+'; + } + return count; + }; + }); + +Use it like this: + +.. code-block:: html + +
  • {{ count | counterFormatter }}
  • + +The menu is hidden by default (**display: none**) and has to be triggered by adding the **open** class to the **app-navigation-entry-menu** div. + +In case of AngularJS the following small directive can be added to handle all the display and click logic out of the box: + +.. code-block:: js + + app.run(function ($document, $rootScope) { + 'use strict'; + $document.click(function (event) { + $rootScope.$broadcast('documentClicked', event); + }); + }); + + app.directive('appNavigationEntryUtils', function () { + 'use strict'; + return { + restrict: 'C', + link: function (scope, elm) { + var menu = elm.siblings('.app-navigation-entry-menu'); + var button = $(elm) + .find('.app-navigation-entry-utils-menu-button button'); + + button.click(function () { + menu.toggleClass('open'); + }); + + scope.$on('documentClicked', function (scope, event) { + if (event.target !== button[0]) { + menu.removeClass('open'); + } + }); + } + }; + }); + +Editing +------- + +.. versionadded:: 8 + +Often an edit option is needed an entry. To add one for a given entry simply hide the title and add the following div inside the entry: + +.. code-block:: html + +
    + +
    + +If AngularJS is used you want to autofocus the input box. This can be achieved by placing the show condition inside an **ng-if** on the **app-navigation-entry-edit** div and adding the following directive: + +.. code-block:: js + + app.directive('autofocusOnInsert', function () { + 'use strict'; + return function (scope, elm) { + elm.focus(); + }; + }); + +**ng-if** is required because it removes/inserts the element into the DOM dynamically instead of just adding a **display: none** to it like **ng-show** and **ng-hide**. + +Undo entry +---------- + +.. versionadded:: 8 + +If you want to undo a performed action on a navigation entry such as deletion, you should show the undo directly in place of the entry and make it disappear after location change or 7 seconds: + + +.. code-block:: html + +
    + +
    + Settings Area =============